commit for fix to a deadlock which would occur when stopping a live, queue'd thread worker

This commit is contained in:
David Anderson 2006-04-25 20:41:18 +00:00
parent 3f5bae615b
commit 2a74d2229f
3 changed files with 42 additions and 42 deletions

View File

@ -5,7 +5,7 @@
// Module info // Module info
#define MODULE_NAME "MySQL X" #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_AUTHOR "AMX Mod X Dev Team"
#define MODULE_URL "http://www.amxmodx.org/" #define MODULE_URL "http://www.amxmodx.org/"
#define MODULE_LOGTAG "SQLX" #define MODULE_LOGTAG "SQLX"

View File

@ -46,7 +46,7 @@ void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
void ThreadWorker::RunThread(IThreadHandle *pHandle) void ThreadWorker::RunThread(IThreadHandle *pHandle)
{ {
WorkerState this_state; WorkerState this_state = Worker_Running;
size_t num; size_t num;
while (true) while (true)
@ -54,6 +54,8 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle)
/** /**
* Check number of items in the queue * Check number of items in the queue
*/ */
if (this_state != Worker_Stopped)
{
m_QueueLock->Lock(); m_QueueLock->Lock();
num = m_ThreadQueue.size(); num = m_ThreadQueue.size();
if (!num) if (!num)
@ -68,19 +70,21 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle)
} else { } else {
m_QueueLock->Unlock(); m_QueueLock->Unlock();
} }
/** }
* Pause in the case of .. pausing!
*/
m_StateLock->Lock(); m_StateLock->Lock();
this_state = m_state; this_state = m_state;
m_StateLock->Unlock(); m_StateLock->Unlock();
if (this_state != Worker_Running) if (this_state != Worker_Running)
{ {
if (this_state == Worker_Paused || this_state == Worker_Stopped)
{
//wait until the lock is cleared.
if (this_state == Worker_Paused)
m_PauseSignal->Wait();
if (this_state == Worker_Stopped) if (this_state == Worker_Stopped)
{ {
//if we're supposed to flush cleanly, //if we're supposed to flush cleanrly,
// run all of the remaining frames first. // run all of the remaining frames first.
// also, don't sleep.
if (!m_FlushType) if (!m_FlushType)
{ {
while (m_ThreadQueue.size()) while (m_ThreadQueue.size())
@ -88,10 +92,6 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle)
} }
break; break;
} }
if (this_state == Worker_Paused)
{
//wait until the lock is cleared.
m_PauseSignal->Wait();
} }
} }
/** /**
@ -174,24 +174,24 @@ bool ThreadWorker::Stop(bool flush_cancel)
if (m_state == Worker_Invalid || m_state == Worker_Stopped) if (m_state == Worker_Invalid || m_state == Worker_Stopped)
return false; return false;
if (m_state == Worker_Paused) WorkerState oldstate;
{
if (!Unpause())
return false;
}
//set new state //set new state
m_StateLock->Lock(); m_StateLock->Lock();
oldstate = m_state;
m_state = Worker_Stopped; m_state = Worker_Stopped;
m_FlushType = flush_cancel;
m_StateLock->Unlock(); m_StateLock->Unlock();
m_FlushType = flush_cancel; if (oldstate == Worker_Paused)
//wait for thread to catch up
if (m_Waiting)
{ {
Unpause();
} else {
m_AddSignal->Signal(); m_AddSignal->Signal();
Pause();
Unpause();
} }
me->WaitForThread(); me->WaitForThread();
//destroy it //destroy it
me->DestroyThis(); me->DestroyThis();

View File

@ -33,8 +33,8 @@ protected:
IEventSignal *m_AddSignal; IEventSignal *m_AddSignal;
IThreadHandle *me; IThreadHandle *me;
unsigned int m_think_time; unsigned int m_think_time;
bool m_Waiting; volatile bool m_Waiting;
bool m_FlushType; volatile bool m_FlushType;
}; };
#endif //_INCLUDE_SOURCEMOD_THREADWORKER_H #endif //_INCLUDE_SOURCEMOD_THREADWORKER_H