3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "ThreadWorker.h"
34 ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks) : BaseWorker(hooks),
41 m_think_time(DEFAULT_THINK_TIME_MS)
43 m_state = Worker_Invalid;
46 ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime) :
48 m_Threader(pThreader),
54 m_think_time(thinktime)
58 m_state = Worker_Stopped;
60 m_state = Worker_Invalid;
64 ThreadWorker::~ThreadWorker()
66 if (m_state != Worker_Stopped || m_state != Worker_Invalid)
71 if (m_ThreadQueue.size())
77 void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
79 //we don't particularly care
83 void ThreadWorker::RunThread(IThreadHandle *pHandle)
85 WorkerState this_state = Worker_Running;
90 m_pHooks->OnWorkerStart(this);
96 * Check number of items in the queue
100 m_StateLock->Unlock();
101 if (this_state != Worker_Stopped)
104 num = m_ThreadQueue.size();
108 * if none, wait for an item
111 m_QueueLock->Unlock();
112 /* first check if we should end again */
113 if (this_state == Worker_Stopped)
120 m_QueueLock->Unlock();
124 this_state = m_state;
125 m_StateLock->Unlock();
126 if (this_state != Worker_Running)
128 if (this_state == Worker_Paused || this_state == Worker_Stopped)
130 //wait until the lock is cleared.
131 if (this_state == Worker_Paused)
133 m_PauseSignal->Wait();
135 if (this_state == Worker_Stopped)
137 //if we're supposed to flush cleanrly,
138 // run all of the remaining frames first.
141 while (m_ThreadQueue.size())
156 * wait in between threads if specified
160 m_Threader->ThreadSleep(m_think_time);
166 m_pHooks->OnWorkerStop(this);
170 SWThreadHandle *ThreadWorker::PopThreadFromQueue()
172 if (m_state <= Worker_Stopped && !m_QueueLock)
179 swt = BaseWorker::PopThreadFromQueue();
180 m_QueueLock->Unlock();
185 void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
187 if (m_state <= Worker_Stopped)
193 BaseWorker::AddThreadToQueue(pHandle);
196 m_AddSignal->Signal();
198 m_QueueLock->Unlock();
201 WorkerState ThreadWorker::GetStatus(unsigned int *threads)
206 state = BaseWorker::GetStatus(threads);
207 m_StateLock->Unlock();
212 bool ThreadWorker::Start()
214 if (m_state == Worker_Invalid)
216 if (m_Threader == NULL)
220 } else if (m_state != Worker_Stopped) {
225 m_QueueLock = m_Threader->MakeMutex();
226 m_StateLock = m_Threader->MakeMutex();
227 m_PauseSignal = m_Threader->MakeEventSignal();
228 m_AddSignal = m_Threader->MakeEventSignal();
229 m_state = Worker_Running;
231 pt.flags = Thread_Default;
232 pt.prio = ThreadPrio_Normal;
233 me = m_Threader->MakeThread(this, &pt);
238 bool ThreadWorker::Stop(bool flush_cancel)
240 if (m_state == Worker_Invalid || m_state == Worker_Stopped)
245 WorkerState oldstate;
250 m_state = Worker_Stopped;
251 m_FlushType = flush_cancel;
252 m_StateLock->Unlock();
254 if (oldstate == Worker_Paused)
261 m_AddSignal->Signal();
263 m_QueueLock->Unlock();
269 //flush all remaining events
273 m_QueueLock->DestroyThis();
274 m_StateLock->DestroyThis();
275 m_PauseSignal->DestroyThis();
276 m_AddSignal->DestroyThis();
281 m_PauseSignal = NULL;
288 bool ThreadWorker::Pause()
290 if (m_state != Worker_Running)
296 m_state = Worker_Paused;
297 m_StateLock->Unlock();
303 bool ThreadWorker::Unpause()
305 if (m_state != Worker_Paused)
311 m_state = Worker_Running;
312 m_StateLock->Unlock();
313 m_PauseSignal->Signal();
316 m_AddSignal->Signal();