3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
15 #include "ThreadWorker.h"
17 ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks) : BaseWorker(hooks),
24 m_think_time(DEFAULT_THINK_TIME_MS)
26 m_state = Worker_Invalid;
29 ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime) :
31 m_Threader(pThreader),
37 m_think_time(thinktime)
41 m_state = Worker_Stopped;
43 m_state = Worker_Invalid;
47 ThreadWorker::~ThreadWorker()
49 if (m_state != Worker_Stopped || m_state != Worker_Invalid)
54 if (m_ThreadQueue.size())
60 void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
62 //we don't particularly care
66 void ThreadWorker::RunThread(IThreadHandle *pHandle)
68 WorkerState this_state = Worker_Running;
73 m_pHooks->OnWorkerStart(this);
79 * Check number of items in the queue
83 m_StateLock->Unlock();
84 if (this_state != Worker_Stopped)
87 num = m_ThreadQueue.size();
91 * if none, wait for an item
94 m_QueueLock->Unlock();
95 /* first check if we should end again */
96 if (this_state == Worker_Stopped)
103 m_QueueLock->Unlock();
107 this_state = m_state;
108 m_StateLock->Unlock();
109 if (this_state != Worker_Running)
111 if (this_state == Worker_Paused || this_state == Worker_Stopped)
113 //wait until the lock is cleared.
114 if (this_state == Worker_Paused)
116 m_PauseSignal->Wait();
118 if (this_state == Worker_Stopped)
120 //if we're supposed to flush cleanrly,
121 // run all of the remaining frames first.
124 while (m_ThreadQueue.size())
139 * wait in between threads if specified
143 m_Threader->ThreadSleep(m_think_time);
149 m_pHooks->OnWorkerStop(this);
153 SWThreadHandle *ThreadWorker::PopThreadFromQueue()
155 if (m_state <= Worker_Stopped && !m_QueueLock)
162 swt = BaseWorker::PopThreadFromQueue();
163 m_QueueLock->Unlock();
168 void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
170 if (m_state <= Worker_Stopped)
176 BaseWorker::AddThreadToQueue(pHandle);
179 m_AddSignal->Signal();
181 m_QueueLock->Unlock();
184 WorkerState ThreadWorker::GetStatus(unsigned int *threads)
189 state = BaseWorker::GetStatus(threads);
190 m_StateLock->Unlock();
195 bool ThreadWorker::Start()
197 if (m_state == Worker_Invalid)
199 if (m_Threader == NULL)
203 } else if (m_state != Worker_Stopped) {
208 m_QueueLock = m_Threader->MakeMutex();
209 m_StateLock = m_Threader->MakeMutex();
210 m_PauseSignal = m_Threader->MakeEventSignal();
211 m_AddSignal = m_Threader->MakeEventSignal();
212 m_state = Worker_Running;
214 pt.flags = Thread_Default;
215 pt.prio = ThreadPrio_Normal;
216 me = m_Threader->MakeThread(this, &pt);
221 bool ThreadWorker::Stop(bool flush_cancel)
223 if (m_state == Worker_Invalid || m_state == Worker_Stopped)
228 WorkerState oldstate;
233 m_state = Worker_Stopped;
234 m_FlushType = flush_cancel;
235 m_StateLock->Unlock();
237 if (oldstate == Worker_Paused)
244 m_AddSignal->Signal();
246 m_QueueLock->Unlock();
252 //flush all remaining events
256 m_QueueLock->DestroyThis();
257 m_StateLock->DestroyThis();
258 m_PauseSignal->DestroyThis();
259 m_AddSignal->DestroyThis();
264 m_PauseSignal = NULL;
271 bool ThreadWorker::Pause()
273 if (m_state != Worker_Running)
279 m_state = Worker_Paused;
280 m_StateLock->Unlock();
286 bool ThreadWorker::Unpause()
288 if (m_state != Worker_Paused)
294 m_state = Worker_Running;
295 m_StateLock->Unlock();
296 m_PauseSignal->Signal();
299 m_AddSignal->Signal();