Но мне нравится как Сионист делает ревизию кода. Интересно какие он тут найдет ошибки.
Код: Выделить всё
#include <memory>
#include <string>
#include <iostream>
#include <Windows.h>
#include <process.h>
#include <stdexcept>
#include <tuple>
#include <atomic>
class MyThread {
HANDLE handle_;
unsigned tid_;
bool detached_;
struct TypeErasure {
virtual unsigned run(unsigned tid) = 0;
virtual ~TypeErasure() = default;
};
std::unique_ptr<TypeErasure> runnable_;
template<typename ThreadRoutine> struct Thunc : public TypeErasure {
ThreadRoutine tr_;
Thunc(ThreadRoutine tr)
:tr_(tr)
{}
unsigned run(unsigned tid) override
{
return tr_(tid);
}
};
static unsigned __stdcall entry(void* arg)
{
MyThread* cookie = static_cast<MyThread*>(arg);
return cookie->runnable_->run(cookie->tid_);
}
public:
template<typename ThreadRoutine> MyThread(ThreadRoutine tr)
: runnable_(std::make_unique< MyThread::Thunc<ThreadRoutine> >(tr))
, detached_(false)
{
handle_ = (HANDLE)_beginthreadex(NULL, 0, &entry, this, CREATE_SUSPENDED, &tid_);
}
void operator()()
{
ResumeThread(handle_);
}
void detach()
{
detached_ = true;
}
std::tuple<unsigned, bool> join(DWORD millis = INFINITE)
{
if (!detached_) {
DWORD waitResult = WaitForSingleObject(handle_, millis);
if (waitResult == WAIT_OBJECT_0) {
DWORD exitCode = 0;
if (GetExitCodeThread(handle_, &exitCode)) {
return std::make_tuple(exitCode, true);
} else {
return std::make_tuple(-1, false);
}
} else {
return std::make_tuple(-1, false);
}
} else {
throw std::runtime_error("Attempt to join a detached thread");
}
}
~MyThread()
{
if (!detached_) {
bool joinSucc = false;
try {
std::tie(std::ignore, joinSucc) = join(0);
} catch (...) { }
if (!joinSucc) {
std::terminate();
}
}
}
};
namespace {
std::atomic_flag own_io = ATOMIC_FLAG_INIT;
}
unsigned func(unsigned tid)
{
for (int i = 0; i < 100; ++i) {
while (own_io.test_and_set(std::memory_order_acquire)) {
Sleep(0);
}
std::cout << "ThreadID {" << std::hex << tid << "} say " << std::dec << i << "\n";
own_io.clear(std::memory_order_release);
}
return 0;
}
int main()
{
MyThread thread1(func), thread2(func), thread3(func);
thread1();
thread2();
thread3();
thread1.join();
thread2.join();
thread3.join();
return 0;
}