Index: src/libchcore/TThreadedQueueRunner.h =================================================================== diff -u -r5127141ac49a45db27f748dfb659d31f2e4983c4 -rbaad6054459abaaf69cbfd1ebad8783085160d99 --- src/libchcore/TThreadedQueueRunner.h (.../TThreadedQueueRunner.h) (revision 5127141ac49a45db27f748dfb659d31f2e4983c4) +++ src/libchcore/TThreadedQueueRunner.h (.../TThreadedQueueRunner.h) (revision baad6054459abaaf69cbfd1ebad8783085160d99) @@ -22,6 +22,7 @@ #include "WaitableQueue.h" #include #include +#include "TEventGuard.h" namespace chcore { @@ -56,41 +57,42 @@ void Stop() { m_eventLocalKill.SetEvent(); + if(m_thread.joinable()) m_thread.join(); } void PushTask(T&& func) { + // order is important here. First push task to be processed, then launch thread if not running already; + // this is to ensure the queued functions are called before thread is killed (which might happen with inverted order) + m_queue.PushBack(std::forward(func)); + if(!m_thread.joinable()) Start(); - - m_queue.PushBack(std::forward(func)); } private: void ThreadProc() { - enum { eKill, eLocalKill, eQueue, eCount }; - std::array arrHandles = { m_hKill, m_eventLocalKill.Handle(), m_queue.GetWaitHandle() }; + TEventGuard eventGuard(m_eventLocalKill, true); + enum { eQueue, eLocalKill, eCount }; + std::array arrHandles = { m_queue.GetWaitHandle(), m_eventLocalKill.Handle() }; + bool bStop = false; do { - DWORD dwResult = WaitForMultipleObjectsEx(eCount, arrHandles.data(), FALSE, INFINITE, TRUE); + DWORD dwResult = WaitForMultipleObjectsEx(eCount, arrHandles.data(), FALSE, INFINITE, FALSE); switch(dwResult) { - case STATUS_USER_APC: - break; - case WAIT_OBJECT_0 + eQueue: { T func = m_queue.PopFront(); func(); break; } - case WAIT_OBJECT_0 + eKill: case WAIT_OBJECT_0 + eLocalKill: default: {