3 * ================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * ================================================================
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License,
10 * version 3.0, as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to
21 * link the code of this program (as well as its derivative works) to
22 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any
23 * Game MODs that run on software by the Valve Corporation. You must
24 * obey the GNU General Public License in all respects for all other
25 * code used. Additionally, AlliedModders LLC grants this exception
26 * to all derivative works. AlliedModders LLC defines further
27 * exceptions, found in LICENSE.txt (as of this writing, version
28 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
33 #include "ThreadWorker.h"
35 ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks) : BaseWorker(hooks),
42 m_think_time(DEFAULT_THINK_TIME_MS)
44 m_state = Worker_Invalid;
47 ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime) :
49 m_Threader(pThreader),
55 m_think_time(thinktime)
59 m_state = Worker_Stopped;
61 m_state = Worker_Invalid;
65 ThreadWorker::~ThreadWorker()
67 if (m_state != Worker_Stopped || m_state != Worker_Invalid)
72 if (m_ThreadQueue.size())
78 void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
80 //we don't particularly care
84 void ThreadWorker::RunThread(IThreadHandle *pHandle)
86 WorkerState this_state = Worker_Running;
91 m_pHooks->OnWorkerStart(this);
97 * Check number of items in the queue
100 this_state = m_state;
101 m_StateLock->Unlock();
102 if (this_state != Worker_Stopped)
105 num = m_ThreadQueue.size();
109 * if none, wait for an item
112 m_QueueLock->Unlock();
113 /* first check if we should end again */
114 if (this_state == Worker_Stopped)
121 m_QueueLock->Unlock();
125 this_state = m_state;
126 m_StateLock->Unlock();
127 if (this_state != Worker_Running)
129 if (this_state == Worker_Paused || this_state == Worker_Stopped)
131 //wait until the lock is cleared.
132 if (this_state == Worker_Paused)
134 m_PauseSignal->Wait();
136 if (this_state == Worker_Stopped)
138 //if we're supposed to flush cleanrly,
139 // run all of the remaining frames first.
142 while (m_ThreadQueue.size())
157 * wait in between threads if specified
161 m_Threader->ThreadSleep(m_think_time);
167 m_pHooks->OnWorkerStop(this);
171 SWThreadHandle *ThreadWorker::PopThreadFromQueue()
173 if (m_state <= Worker_Stopped && !m_QueueLock)
180 swt = BaseWorker::PopThreadFromQueue();
181 m_QueueLock->Unlock();
186 void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
188 if (m_state <= Worker_Stopped)
194 BaseWorker::AddThreadToQueue(pHandle);
197 m_AddSignal->Signal();
199 m_QueueLock->Unlock();
202 WorkerState ThreadWorker::GetStatus(unsigned int *threads)
207 state = BaseWorker::GetStatus(threads);
208 m_StateLock->Unlock();
213 bool ThreadWorker::Start()
215 if (m_state == Worker_Invalid)
217 if (m_Threader == NULL)
221 } else if (m_state != Worker_Stopped) {
226 m_QueueLock = m_Threader->MakeMutex();
227 m_StateLock = m_Threader->MakeMutex();
228 m_PauseSignal = m_Threader->MakeEventSignal();
229 m_AddSignal = m_Threader->MakeEventSignal();
230 m_state = Worker_Running;
232 pt.flags = Thread_Default;
233 pt.prio = ThreadPrio_Normal;
234 me = m_Threader->MakeThread(this, &pt);
239 bool ThreadWorker::Stop(bool flush_cancel)
241 if (m_state == Worker_Invalid || m_state == Worker_Stopped)
246 WorkerState oldstate;
251 m_state = Worker_Stopped;
252 m_FlushType = flush_cancel;
253 m_StateLock->Unlock();
255 if (oldstate == Worker_Paused)
262 m_AddSignal->Signal();
264 m_QueueLock->Unlock();
270 //flush all remaining events
274 m_QueueLock->DestroyThis();
275 m_StateLock->DestroyThis();
276 m_PauseSignal->DestroyThis();
277 m_AddSignal->DestroyThis();
282 m_PauseSignal = NULL;
289 bool ThreadWorker::Pause()
291 if (m_state != Worker_Running)
297 m_state = Worker_Paused;
298 m_StateLock->Unlock();
304 bool ThreadWorker::Unpause()
306 if (m_state != Worker_Paused)
312 m_state = Worker_Running;
313 m_StateLock->Unlock();
314 m_PauseSignal->Signal();
317 m_AddSignal->Signal();