diff -r 000000000000 -r c24a6fa957db core/thread/WinThreads.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/thread/WinThreads.cpp Sun Jul 06 04:49:55 2008 +0000
@@ -0,0 +1,320 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#define _WIN32_WINNT 0x0400
+#include "WinThreads.h"
+#include "ThreadWorker.h"
+
+IThreadWorker *WinThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
+{
+ if (threaded)
+ {
+ return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
+ } else {
+ return new BaseWorker(hooks);
+ }
+}
+
+void WinThreader::DestroyWorker(IThreadWorker *pWorker)
+{
+ delete pWorker;
+}
+
+void WinThreader::ThreadSleep(unsigned int ms)
+{
+ Sleep((DWORD)ms);
+}
+
+IMutex *WinThreader::MakeMutex()
+{
+ WinMutex *pMutex = new WinMutex();
+
+ return pMutex;
+}
+
+IThreadHandle *WinThreader::MakeThread(IThread *pThread, ThreadFlags flags)
+{
+ ThreadParams defparams;
+
+ defparams.flags = flags;
+ defparams.prio = ThreadPrio_Normal;
+
+ return MakeThread(pThread, &defparams);
+}
+
+void WinThreader::MakeThread(IThread *pThread)
+{
+ ThreadParams defparams;
+
+ defparams.flags = Thread_AutoRelease;
+ defparams.prio = ThreadPrio_Normal;
+
+ MakeThread(pThread, &defparams);
+}
+
+DWORD WINAPI Win32_ThreadGate(LPVOID param)
+{
+ WinThreader::ThreadHandle *pHandle =
+ reinterpret_cast(param);
+
+ pHandle->m_run->RunThread(pHandle);
+
+ ThreadParams params;
+ EnterCriticalSection(&pHandle->m_crit);
+ pHandle->m_state = Thread_Done;
+ pHandle->GetParams(¶ms);
+ LeaveCriticalSection(&pHandle->m_crit);
+
+ pHandle->m_run->OnTerminate(pHandle, false);
+ if (params.flags & Thread_AutoRelease)
+ delete pHandle;
+
+ return 0;
+}
+
+void WinThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
+{
+ max = ThreadPrio_Maximum;
+ min = ThreadPrio_Minimum;
+}
+
+ThreadParams g_defparams;
+IThreadHandle *WinThreader::MakeThread(IThread *pThread, const ThreadParams *params)
+{
+ if (params == NULL)
+ params = &g_defparams;
+
+ WinThreader::ThreadHandle *pHandle =
+ new WinThreader::ThreadHandle(this, NULL, pThread, params);
+
+ DWORD tid;
+ pHandle->m_thread =
+ CreateThread(NULL, 0, &Win32_ThreadGate, (LPVOID)pHandle, CREATE_SUSPENDED, &tid);
+
+ if (!pHandle->m_thread)
+ {
+ delete pHandle;
+ return NULL;
+ }
+
+ if (pHandle->m_params.prio != ThreadPrio_Normal)
+ {
+ pHandle->SetPriority(pHandle->m_params.prio);
+ }
+
+ if (!(pHandle->m_params.flags & Thread_CreateSuspended))
+ {
+ pHandle->Unpause();
+ }
+
+ return pHandle;
+}
+
+IEventSignal *WinThreader::MakeEventSignal()
+{
+ HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ if (!event)
+ return NULL;
+
+ WinEvent *pEvent = new WinEvent(event);
+
+ return pEvent;
+}
+
+/*****************
+ **** Mutexes ****
+ *****************/
+
+WinThreader::WinMutex::WinMutex()
+{
+ InitializeCriticalSection(&m_crit);
+}
+
+WinThreader::WinMutex::~WinMutex()
+{
+ DeleteCriticalSection(&m_crit);
+}
+
+bool WinThreader::WinMutex::TryLock()
+{
+ return (TryEnterCriticalSection(&m_crit) != FALSE);
+}
+
+void WinThreader::WinMutex::Lock()
+{
+ EnterCriticalSection(&m_crit);
+}
+
+void WinThreader::WinMutex::Unlock()
+{
+ LeaveCriticalSection(&m_crit);
+}
+
+void WinThreader::WinMutex::DestroyThis()
+{
+ delete this;
+}
+
+/******************
+ * Thread Handles *
+ ******************/
+
+WinThreader::ThreadHandle::ThreadHandle(IThreader *parent, HANDLE hthread, IThread *run, const ThreadParams *params) :
+ m_parent(parent), m_thread(hthread), m_run(run), m_params(*params),
+ m_state(Thread_Paused)
+{
+ InitializeCriticalSection(&m_crit);
+}
+
+WinThreader::ThreadHandle::~ThreadHandle()
+{
+ if (m_thread)
+ {
+ CloseHandle(m_thread);
+ m_thread = NULL;
+ }
+ DeleteCriticalSection(&m_crit);
+}
+
+bool WinThreader::ThreadHandle::WaitForThread()
+{
+ if (m_thread == NULL)
+ return false;
+
+ if (WaitForSingleObject(m_thread, INFINITE) != 0)
+ return false;
+
+ return true;
+}
+
+ThreadState WinThreader::ThreadHandle::GetState()
+{
+ ThreadState state;
+
+ EnterCriticalSection(&m_crit);
+ state = m_state;
+ LeaveCriticalSection(&m_crit);
+
+ return state;
+}
+
+IThreadCreator *WinThreader::ThreadHandle::Parent()
+{
+ return m_parent;
+}
+
+void WinThreader::ThreadHandle::DestroyThis()
+{
+ if (m_params.flags & Thread_AutoRelease)
+ return;
+
+ delete this;
+}
+
+void WinThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
+{
+ if (!ptparams)
+ return;
+
+ *ptparams = m_params;
+}
+
+ThreadPriority WinThreader::ThreadHandle::GetPriority()
+{
+ return m_params.prio;
+}
+
+bool WinThreader::ThreadHandle::SetPriority(ThreadPriority prio)
+{
+ if (!m_thread)
+ return false;
+
+ BOOL res = FALSE;
+
+ if (prio >= ThreadPrio_Maximum)
+ res = SetThreadPriority(m_thread, THREAD_PRIORITY_HIGHEST);
+ else if (prio <= ThreadPrio_Minimum)
+ res = SetThreadPriority(m_thread, THREAD_PRIORITY_LOWEST);
+ else if (prio == ThreadPrio_Normal)
+ res = SetThreadPriority(m_thread, THREAD_PRIORITY_NORMAL);
+ else if (prio == ThreadPrio_High)
+ res = SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
+ else if (prio == ThreadPrio_Low)
+ res = SetThreadPriority(m_thread, THREAD_PRIORITY_BELOW_NORMAL);
+
+ m_params.prio = prio;
+
+ return (res != FALSE);
+}
+
+bool WinThreader::ThreadHandle::Unpause()
+{
+ if (!m_thread)
+ return false;
+
+ if (m_state != Thread_Paused)
+ return false;
+
+ m_state = Thread_Running;
+
+ if (ResumeThread(m_thread) == -1)
+ {
+ m_state = Thread_Paused;
+ return false;
+ }
+
+ return true;
+}
+
+/*****************
+ * EVENT SIGNALS *
+ *****************/
+
+WinThreader::WinEvent::~WinEvent()
+{
+ CloseHandle(m_event);
+}
+
+void WinThreader::WinEvent::Wait()
+{
+ WaitForSingleObject(m_event, INFINITE);
+}
+
+void WinThreader::WinEvent::Signal()
+{
+ SetEvent(m_event);
+}
+
+void WinThreader::WinEvent::DestroyThis()
+{
+ delete this;
+}