mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-24 13:55:36 +03:00
commit for fix to a deadlock which would occur when stopping a live, queue'd thread worker
This commit is contained in:
parent
3f5bae615b
commit
2a74d2229f
@ -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"
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user