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 #define _WIN32_WINNT 0x0400
34 #include "WinThreads.h"
35 #include "ThreadWorker.h"
37 IThreadWorker *WinThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
41 return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
43 return new BaseWorker(hooks);
47 void WinThreader::DestroyWorker(IThreadWorker *pWorker)
52 void WinThreader::ThreadSleep(unsigned int ms)
57 IMutex *WinThreader::MakeMutex()
59 WinMutex *pMutex = new WinMutex();
64 IThreadHandle *WinThreader::MakeThread(IThread *pThread, ThreadFlags flags)
66 ThreadParams defparams;
68 defparams.flags = flags;
69 defparams.prio = ThreadPrio_Normal;
71 return MakeThread(pThread, &defparams);
74 void WinThreader::MakeThread(IThread *pThread)
76 ThreadParams defparams;
78 defparams.flags = Thread_AutoRelease;
79 defparams.prio = ThreadPrio_Normal;
81 MakeThread(pThread, &defparams);
84 DWORD WINAPI Win32_ThreadGate(LPVOID param)
86 WinThreader::ThreadHandle *pHandle =
87 reinterpret_cast<WinThreader::ThreadHandle *>(param);
89 pHandle->m_run->RunThread(pHandle);
92 EnterCriticalSection(&pHandle->m_crit);
93 pHandle->m_state = Thread_Done;
94 pHandle->GetParams(¶ms);
95 LeaveCriticalSection(&pHandle->m_crit);
97 pHandle->m_run->OnTerminate(pHandle, false);
98 if (params.flags & Thread_AutoRelease)
104 void WinThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
106 max = ThreadPrio_Maximum;
107 min = ThreadPrio_Minimum;
110 ThreadParams g_defparams;
111 IThreadHandle *WinThreader::MakeThread(IThread *pThread, const ThreadParams *params)
114 params = &g_defparams;
116 WinThreader::ThreadHandle *pHandle =
117 new WinThreader::ThreadHandle(this, NULL, pThread, params);
121 CreateThread(NULL, 0, &Win32_ThreadGate, (LPVOID)pHandle, CREATE_SUSPENDED, &tid);
123 if (!pHandle->m_thread)
129 if (pHandle->m_params.prio != ThreadPrio_Normal)
131 pHandle->SetPriority(pHandle->m_params.prio);
134 if (!(pHandle->m_params.flags & Thread_CreateSuspended))
142 IEventSignal *WinThreader::MakeEventSignal()
144 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
149 WinEvent *pEvent = new WinEvent(event);
158 WinThreader::WinMutex::WinMutex()
160 InitializeCriticalSection(&m_crit);
163 WinThreader::WinMutex::~WinMutex()
165 DeleteCriticalSection(&m_crit);
168 bool WinThreader::WinMutex::TryLock()
170 return (TryEnterCriticalSection(&m_crit) != FALSE);
173 void WinThreader::WinMutex::Lock()
175 EnterCriticalSection(&m_crit);
178 void WinThreader::WinMutex::Unlock()
180 LeaveCriticalSection(&m_crit);
183 void WinThreader::WinMutex::DestroyThis()
192 WinThreader::ThreadHandle::ThreadHandle(IThreader *parent, HANDLE hthread, IThread *run, const ThreadParams *params) :
193 m_parent(parent), m_thread(hthread), m_run(run), m_params(*params),
194 m_state(Thread_Paused)
196 InitializeCriticalSection(&m_crit);
199 WinThreader::ThreadHandle::~ThreadHandle()
203 CloseHandle(m_thread);
206 DeleteCriticalSection(&m_crit);
209 bool WinThreader::ThreadHandle::WaitForThread()
211 if (m_thread == NULL)
214 if (WaitForSingleObject(m_thread, INFINITE) != 0)
220 ThreadState WinThreader::ThreadHandle::GetState()
224 EnterCriticalSection(&m_crit);
226 LeaveCriticalSection(&m_crit);
231 IThreadCreator *WinThreader::ThreadHandle::Parent()
236 void WinThreader::ThreadHandle::DestroyThis()
238 if (m_params.flags & Thread_AutoRelease)
244 void WinThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
249 *ptparams = m_params;
252 ThreadPriority WinThreader::ThreadHandle::GetPriority()
254 return m_params.prio;
257 bool WinThreader::ThreadHandle::SetPriority(ThreadPriority prio)
264 if (prio >= ThreadPrio_Maximum)
265 res = SetThreadPriority(m_thread, THREAD_PRIORITY_HIGHEST);
266 else if (prio <= ThreadPrio_Minimum)
267 res = SetThreadPriority(m_thread, THREAD_PRIORITY_LOWEST);
268 else if (prio == ThreadPrio_Normal)
269 res = SetThreadPriority(m_thread, THREAD_PRIORITY_NORMAL);
270 else if (prio == ThreadPrio_High)
271 res = SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
272 else if (prio == ThreadPrio_Low)
273 res = SetThreadPriority(m_thread, THREAD_PRIORITY_BELOW_NORMAL);
275 m_params.prio = prio;
277 return (res != FALSE);
280 bool WinThreader::ThreadHandle::Unpause()
285 if (m_state != Thread_Paused)
288 m_state = Thread_Running;
290 if (ResumeThread(m_thread) == -1)
292 m_state = Thread_Paused;
303 WinThreader::WinEvent::~WinEvent()
305 CloseHandle(m_event);
308 void WinThreader::WinEvent::Wait()
310 WaitForSingleObject(m_event, INFINITE);
313 void WinThreader::WinEvent::Signal()
318 void WinThreader::WinEvent::DestroyThis()