Fixed a bug that caused a race between ~Thread and Thread::Runner receiving a new job from the threadpool
82 lines
1.5 KiB
C++
82 lines
1.5 KiB
C++
#include <utility>
|
|
#include <MultiThreading/Thread.h>
|
|
|
|
|
|
using namespace MultiThreading;
|
|
|
|
Thread::~Thread() {
|
|
std::shared_ptr<TaskBase> task;
|
|
|
|
{
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
task = current_task;
|
|
}
|
|
|
|
if (task)
|
|
task->WaitComplete();
|
|
|
|
stop = true;
|
|
cv.notify_one();
|
|
Join();
|
|
}
|
|
|
|
bool Thread::SetTask(std::shared_ptr<TaskBase> task) {
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
|
|
if (Busy())
|
|
return false;
|
|
|
|
if (current_task)
|
|
return false;
|
|
|
|
busy = true;
|
|
current_task = std::move(task);
|
|
|
|
cv.notify_all();
|
|
return true;
|
|
}
|
|
|
|
bool Thread::SetTask(const std::function<void()>& task) {
|
|
return SetTask(Task<void>::Create(task));
|
|
}
|
|
|
|
void Thread::Runner() {
|
|
std::unique_lock<std::mutex> lock(mtx);
|
|
|
|
while (!stop) {
|
|
cv.wait(lock, [this] { return stop || current_task != nullptr; });
|
|
|
|
if (stop)
|
|
break;
|
|
|
|
auto task = current_task;
|
|
lock.unlock();
|
|
|
|
task->Run();
|
|
|
|
lock.lock();
|
|
|
|
current_task = nullptr;
|
|
busy = false;
|
|
}
|
|
}
|
|
|
|
Thread::Thread(std::shared_ptr<TaskBase> task) {
|
|
worker = std::thread([this] { this->Runner(); });
|
|
|
|
if (!SetTask(std::move(task)))
|
|
throw std::runtime_error("Thread constructor failure.");
|
|
}
|
|
|
|
Thread::Thread(const std::function<void()>& task) {
|
|
worker = std::thread([this] { this->Runner(); });
|
|
|
|
if (!SetTask(task))
|
|
throw std::runtime_error("Thread constructor failure.");
|
|
}
|
|
|
|
void Thread::Join() {
|
|
if (worker.joinable())
|
|
worker.join();
|
|
}
|