From 2a74d2229ff9d671c197e92fcf544c14f56965d4 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 25 Apr 2006 20:41:18 +0000 Subject: [PATCH] commit for fix to a deadlock which would occur when stopping a live, queue'd thread worker --- dlls/mysqlx/sdk/moduleconfig.h | 2 +- dlls/mysqlx/thread/ThreadWorker.cpp | 78 ++++++++++++++--------------- dlls/mysqlx/thread/ThreadWorker.h | 4 +- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/dlls/mysqlx/sdk/moduleconfig.h b/dlls/mysqlx/sdk/moduleconfig.h index ce7e3304..d1dfd0b4 100755 --- a/dlls/mysqlx/sdk/moduleconfig.h +++ b/dlls/mysqlx/sdk/moduleconfig.h @@ -5,7 +5,7 @@ // Module info #define MODULE_NAME "MySQL X" -#define MODULE_VERSION "1.00" +#define MODULE_VERSION "1.01" #define MODULE_AUTHOR "AMX Mod X Dev Team" #define MODULE_URL "http://www.amxmodx.org/" #define MODULE_LOGTAG "SQLX" diff --git a/dlls/mysqlx/thread/ThreadWorker.cpp b/dlls/mysqlx/thread/ThreadWorker.cpp index d40cdb4e..daff21ed 100644 --- a/dlls/mysqlx/thread/ThreadWorker.cpp +++ b/dlls/mysqlx/thread/ThreadWorker.cpp @@ -46,7 +46,7 @@ void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel) void ThreadWorker::RunThread(IThreadHandle *pHandle) { - WorkerState this_state; + WorkerState this_state = Worker_Running; size_t num; while (true) @@ -54,44 +54,44 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle) /** * Check number of items in the queue */ - m_QueueLock->Lock(); - num = m_ThreadQueue.size(); - if (!num) + if (this_state != Worker_Stopped) { - /** - * if none, wait for an item - */ - m_Waiting = true; - m_QueueLock->Unlock(); - m_AddSignal->Wait(); - m_Waiting = false; - } else { - m_QueueLock->Unlock(); + m_QueueLock->Lock(); + num = m_ThreadQueue.size(); + if (!num) + { + /** + * if none, wait for an item + */ + m_Waiting = true; + m_QueueLock->Unlock(); + m_AddSignal->Wait(); + m_Waiting = false; + } else { + m_QueueLock->Unlock(); + } } - /** - * Pause in the case of .. pausing! - */ m_StateLock->Lock(); this_state = m_state; m_StateLock->Unlock(); if (this_state != Worker_Running) { - if (this_state == Worker_Stopped) - { - //if we're supposed to flush cleanly, - // run all of the remaining frames first. - // also, don't sleep. - if (!m_FlushType) - { - while (m_ThreadQueue.size()) - RunFrame(); - } - break; - } - if (this_state == Worker_Paused) + if (this_state == Worker_Paused || this_state == Worker_Stopped) { //wait until the lock is cleared. - m_PauseSignal->Wait(); + if (this_state == Worker_Paused) + m_PauseSignal->Wait(); + if (this_state == Worker_Stopped) + { + //if we're supposed to flush cleanrly, + // run all of the remaining frames first. + if (!m_FlushType) + { + while (m_ThreadQueue.size()) + RunFrame(); + } + break; + } } } /** @@ -174,24 +174,24 @@ bool ThreadWorker::Stop(bool flush_cancel) if (m_state == Worker_Invalid || m_state == Worker_Stopped) return false; - if (m_state == Worker_Paused) - { - if (!Unpause()) - return false; - } + WorkerState oldstate; //set new state m_StateLock->Lock(); + oldstate = m_state; m_state = Worker_Stopped; + m_FlushType = flush_cancel; m_StateLock->Unlock(); - m_FlushType = flush_cancel; - - //wait for thread to catch up - if (m_Waiting) + if (oldstate == Worker_Paused) { + Unpause(); + } else { m_AddSignal->Signal(); + Pause(); + Unpause(); } + me->WaitForThread(); //destroy it me->DestroyThis(); diff --git a/dlls/mysqlx/thread/ThreadWorker.h b/dlls/mysqlx/thread/ThreadWorker.h index ab89cf0f..a8c57be3 100644 --- a/dlls/mysqlx/thread/ThreadWorker.h +++ b/dlls/mysqlx/thread/ThreadWorker.h @@ -33,8 +33,8 @@ protected: IEventSignal *m_AddSignal; IThreadHandle *me; unsigned int m_think_time; - bool m_Waiting; - bool m_FlushType; + volatile bool m_Waiting; + volatile bool m_FlushType; }; #endif //_INCLUDE_SOURCEMOD_THREADWORKER_H