I have the following code which creates a group of threads and detaches them immediately:
#include <mutex>
#include <thread>
#include <queue>
#include <atomic>
#include <functional>
class TGroup final
{
private:
std::mutex mutex;
std::condition_variable condition;
std::queue<std::function<void()>> tasks;
std::atomic_bool stop;
public:
TGroup();
~TGroup();
TGroup(const TGroup&) = delete;
TGroup& operator = (const TGroup&) = delete;
void terminate();
void execute(std::function<void()> &&task);
};
TGroup::TGroup() : mutex(), condition(), tasks(), stop(false)
{
for (std::size_t i = 0; i < std::thread::hardware_concurrency(); ++i)
{
std::thread([this] {
while(true)
{
std::unique_lock<std::mutex> lock(this->mutex);
condition.wait(lock, [this] {
return !this->tasks.empty() || this->stop;
});
if (this->stop)
{
lock.unlock();
break;
}
auto task = std::move(this->tasks.front());
this->tasks.pop();
lock.unlock();
task();
}
}).detach();
}
}
TGroup::~TGroup()
{
this->terminate();
}
void TGroup::terminate()
{
if (!this->stop)
{
std::unique_lock<std::mutex> lock(this->mutex);
this->stop = true;
lock.unlock();
this->condition.notify_all(); //Causes a crash on Windows but not MacOS or Linux..
}
}
void TGroup::execute(std::function<void()> &&task)
{
if (!this->stop)
{
std::unique_lock<std::mutex> lock(this->mutex);
this->tasks.emplace(task);
lock.unlock();
this->condition.notify_one();
}
}
In my DLL_DETACHED
inside of DLLMain
, I call group.terminate()
. It works perfectly fine if I comment out this->condition.notify_all();
in TGroup.terminate()
.
Is there a reason that notifying the condition variable would cause a deadlock? It currently causes my process to NOT exit when I press the exit button (I have to use TaskManager to kill it).
Any ideas?
Aucun commentaire:
Enregistrer un commentaire