core/logic/thread/WinThreads.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Aug 14 14:20:57 2013 -0400 (2013-08-14)
changeset 4008 490b01aa0683
parent 2726 c96f3fab8211
child 4025 542dde661d5c
permissions -rw-r--r--
Updated some CS:GO gamedata.
dvander@2726
     1
/**
dvander@2726
     2
 * vim: set ts=4 :
dvander@2726
     3
 * =============================================================================
dvander@2726
     4
 * SourceMod
dvander@2726
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@2726
     6
 * =============================================================================
dvander@2726
     7
 *
dvander@2726
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@2726
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2726
    10
 * Free Software Foundation.
dvander@2726
    11
 * 
dvander@2726
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2726
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2726
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2726
    15
 * details.
dvander@2726
    16
 *
dvander@2726
    17
 * You should have received a copy of the GNU General Public License along with
dvander@2726
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2726
    19
 *
dvander@2726
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2726
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2726
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2726
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2726
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2726
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@2726
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2726
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@2726
    28
 *
dvander@2726
    29
 * Version: $Id$
dvander@2726
    30
 */
dvander@2726
    31
dvander@2726
    32
#define _WIN32_WINNT 0x0400
dvander@2726
    33
#include "WinThreads.h"
dvander@2726
    34
#include "ThreadWorker.h"
dvander@2726
    35
dvander@2726
    36
IThreadWorker *WinThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
dvander@2726
    37
{
dvander@2726
    38
	if (threaded)
dvander@2726
    39
	{
dvander@2726
    40
		return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
dvander@2726
    41
	} else {
dvander@2726
    42
		return new BaseWorker(hooks);
dvander@2726
    43
	}
dvander@2726
    44
}
dvander@2726
    45
dvander@2726
    46
void WinThreader::DestroyWorker(IThreadWorker *pWorker)
dvander@2726
    47
{
dvander@2726
    48
	delete pWorker;
dvander@2726
    49
}
dvander@2726
    50
dvander@2726
    51
void WinThreader::ThreadSleep(unsigned int ms)
dvander@2726
    52
{
dvander@2726
    53
	Sleep((DWORD)ms);
dvander@2726
    54
}
dvander@2726
    55
dvander@2726
    56
IMutex *WinThreader::MakeMutex()
dvander@2726
    57
{
dvander@2726
    58
	WinMutex *pMutex = new WinMutex();
dvander@2726
    59
dvander@2726
    60
	return pMutex;
dvander@2726
    61
}
dvander@2726
    62
dvander@2726
    63
IThreadHandle *WinThreader::MakeThread(IThread *pThread, ThreadFlags flags)
dvander@2726
    64
{
dvander@2726
    65
	ThreadParams defparams;
dvander@2726
    66
dvander@2726
    67
	defparams.flags = flags;
dvander@2726
    68
	defparams.prio = ThreadPrio_Normal;
dvander@2726
    69
dvander@2726
    70
	return MakeThread(pThread, &defparams);
dvander@2726
    71
}
dvander@2726
    72
dvander@2726
    73
void WinThreader::MakeThread(IThread *pThread)
dvander@2726
    74
{
dvander@2726
    75
	ThreadParams defparams;
dvander@2726
    76
dvander@2726
    77
	defparams.flags = Thread_AutoRelease;
dvander@2726
    78
	defparams.prio = ThreadPrio_Normal;
dvander@2726
    79
dvander@2726
    80
	MakeThread(pThread, &defparams);
dvander@2726
    81
}
dvander@2726
    82
dvander@2726
    83
DWORD WINAPI Win32_ThreadGate(LPVOID param)
dvander@2726
    84
{
dvander@2726
    85
	WinThreader::ThreadHandle *pHandle = 
dvander@2726
    86
		reinterpret_cast<WinThreader::ThreadHandle *>(param);
dvander@2726
    87
dvander@2726
    88
	pHandle->m_run->RunThread(pHandle);
dvander@2726
    89
dvander@2726
    90
	ThreadParams params;
dvander@2726
    91
	EnterCriticalSection(&pHandle->m_crit);
dvander@2726
    92
	pHandle->m_state = Thread_Done;
dvander@2726
    93
	pHandle->GetParams(&params);
dvander@2726
    94
	LeaveCriticalSection(&pHandle->m_crit);
dvander@2726
    95
dvander@2726
    96
	pHandle->m_run->OnTerminate(pHandle, false);
dvander@2726
    97
	if (params.flags & Thread_AutoRelease)
dvander@2726
    98
		delete pHandle;
dvander@2726
    99
dvander@2726
   100
	return 0;
dvander@2726
   101
}
dvander@2726
   102
dvander@2726
   103
void WinThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
dvander@2726
   104
{
dvander@2726
   105
	max = ThreadPrio_Maximum;
dvander@2726
   106
	min = ThreadPrio_Minimum;
dvander@2726
   107
}
dvander@2726
   108
dvander@2726
   109
ThreadParams g_defparams;
dvander@2726
   110
IThreadHandle *WinThreader::MakeThread(IThread *pThread, const ThreadParams *params)
dvander@2726
   111
{
dvander@2726
   112
	if (params == NULL)
dvander@2726
   113
		params = &g_defparams;
dvander@2726
   114
dvander@2726
   115
	WinThreader::ThreadHandle *pHandle = 
dvander@2726
   116
		new WinThreader::ThreadHandle(this, NULL, pThread, params);
dvander@2726
   117
dvander@2726
   118
	DWORD tid;
dvander@2726
   119
	pHandle->m_thread = 
dvander@2726
   120
		CreateThread(NULL, 0, &Win32_ThreadGate, (LPVOID)pHandle, CREATE_SUSPENDED, &tid);
dvander@2726
   121
dvander@2726
   122
	if (!pHandle->m_thread)
dvander@2726
   123
	{
dvander@2726
   124
		delete pHandle;
dvander@2726
   125
		return NULL;
dvander@2726
   126
	}
dvander@2726
   127
dvander@2726
   128
	if (pHandle->m_params.prio != ThreadPrio_Normal)
dvander@2726
   129
	{
dvander@2726
   130
		pHandle->SetPriority(pHandle->m_params.prio);
dvander@2726
   131
	}
dvander@2726
   132
dvander@2726
   133
	if (!(pHandle->m_params.flags & Thread_CreateSuspended))
dvander@2726
   134
	{
dvander@2726
   135
		pHandle->Unpause();
dvander@2726
   136
	}
dvander@2726
   137
dvander@2726
   138
	return pHandle;
dvander@2726
   139
}
dvander@2726
   140
dvander@2726
   141
IEventSignal *WinThreader::MakeEventSignal()
dvander@2726
   142
{
dvander@2726
   143
	HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
dvander@2726
   144
dvander@2726
   145
	if (!event)
dvander@2726
   146
		return NULL;
dvander@2726
   147
dvander@2726
   148
	WinEvent *pEvent = new WinEvent(event);
dvander@2726
   149
dvander@2726
   150
	return pEvent;
dvander@2726
   151
}
dvander@2726
   152
dvander@2726
   153
/*****************
dvander@2726
   154
 **** Mutexes ****
dvander@2726
   155
 *****************/
dvander@2726
   156
dvander@2726
   157
WinThreader::WinMutex::WinMutex()
dvander@2726
   158
{
dvander@2726
   159
	InitializeCriticalSection(&m_crit);
dvander@2726
   160
}
dvander@2726
   161
dvander@2726
   162
WinThreader::WinMutex::~WinMutex()
dvander@2726
   163
{
dvander@2726
   164
	DeleteCriticalSection(&m_crit);
dvander@2726
   165
}
dvander@2726
   166
dvander@2726
   167
bool WinThreader::WinMutex::TryLock()
dvander@2726
   168
{
dvander@2726
   169
	return (TryEnterCriticalSection(&m_crit) != FALSE);
dvander@2726
   170
}
dvander@2726
   171
dvander@2726
   172
void WinThreader::WinMutex::Lock()
dvander@2726
   173
{
dvander@2726
   174
	EnterCriticalSection(&m_crit);
dvander@2726
   175
}
dvander@2726
   176
dvander@2726
   177
void WinThreader::WinMutex::Unlock()
dvander@2726
   178
{
dvander@2726
   179
	LeaveCriticalSection(&m_crit);
dvander@2726
   180
}
dvander@2726
   181
dvander@2726
   182
void WinThreader::WinMutex::DestroyThis()
dvander@2726
   183
{
dvander@2726
   184
	delete this;
dvander@2726
   185
}
dvander@2726
   186
dvander@2726
   187
/******************
dvander@2726
   188
 * Thread Handles *
dvander@2726
   189
 ******************/
dvander@2726
   190
dvander@2726
   191
WinThreader::ThreadHandle::ThreadHandle(IThreader *parent, HANDLE hthread, IThread *run, const ThreadParams *params) : 
dvander@2726
   192
	m_parent(parent), m_thread(hthread), m_run(run), m_params(*params),
dvander@2726
   193
	m_state(Thread_Paused)
dvander@2726
   194
{
dvander@2726
   195
	InitializeCriticalSection(&m_crit);
dvander@2726
   196
}
dvander@2726
   197
dvander@2726
   198
WinThreader::ThreadHandle::~ThreadHandle()
dvander@2726
   199
{
dvander@2726
   200
	if (m_thread)
dvander@2726
   201
	{
dvander@2726
   202
		CloseHandle(m_thread);
dvander@2726
   203
		m_thread = NULL;
dvander@2726
   204
	}
dvander@2726
   205
	DeleteCriticalSection(&m_crit);
dvander@2726
   206
}
dvander@2726
   207
dvander@2726
   208
bool WinThreader::ThreadHandle::WaitForThread()
dvander@2726
   209
{
dvander@2726
   210
	if (m_thread == NULL)
dvander@2726
   211
		return false;
dvander@2726
   212
dvander@2726
   213
	if (WaitForSingleObject(m_thread, INFINITE) != 0)
dvander@2726
   214
		return false;
dvander@2726
   215
dvander@2726
   216
	return true;
dvander@2726
   217
}
dvander@2726
   218
dvander@2726
   219
ThreadState WinThreader::ThreadHandle::GetState()
dvander@2726
   220
{
dvander@2726
   221
	ThreadState state;
dvander@2726
   222
dvander@2726
   223
	EnterCriticalSection(&m_crit);
dvander@2726
   224
	state = m_state;
dvander@2726
   225
	LeaveCriticalSection(&m_crit);
dvander@2726
   226
dvander@2726
   227
	return state;
dvander@2726
   228
}
dvander@2726
   229
dvander@2726
   230
IThreadCreator *WinThreader::ThreadHandle::Parent()
dvander@2726
   231
{
dvander@2726
   232
	return m_parent;
dvander@2726
   233
}
dvander@2726
   234
dvander@2726
   235
void WinThreader::ThreadHandle::DestroyThis()
dvander@2726
   236
{
dvander@2726
   237
	if (m_params.flags & Thread_AutoRelease)
dvander@2726
   238
		return;
dvander@2726
   239
dvander@2726
   240
	delete this;
dvander@2726
   241
}
dvander@2726
   242
dvander@2726
   243
void WinThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
dvander@2726
   244
{
dvander@2726
   245
	if (!ptparams)
dvander@2726
   246
		return;
dvander@2726
   247
dvander@2726
   248
	*ptparams = m_params;
dvander@2726
   249
}
dvander@2726
   250
dvander@2726
   251
ThreadPriority WinThreader::ThreadHandle::GetPriority()
dvander@2726
   252
{
dvander@2726
   253
	return m_params.prio;
dvander@2726
   254
}
dvander@2726
   255
dvander@2726
   256
bool WinThreader::ThreadHandle::SetPriority(ThreadPriority prio)
dvander@2726
   257
{
dvander@2726
   258
	if (!m_thread)
dvander@2726
   259
		return false;
dvander@2726
   260
dvander@2726
   261
	BOOL res = FALSE;
dvander@2726
   262
dvander@2726
   263
	if (prio >= ThreadPrio_Maximum)
dvander@2726
   264
		res = SetThreadPriority(m_thread, THREAD_PRIORITY_HIGHEST);
dvander@2726
   265
	else if (prio <= ThreadPrio_Minimum)
dvander@2726
   266
		res = SetThreadPriority(m_thread, THREAD_PRIORITY_LOWEST);
dvander@2726
   267
	else if (prio == ThreadPrio_Normal)
dvander@2726
   268
		res = SetThreadPriority(m_thread, THREAD_PRIORITY_NORMAL);
dvander@2726
   269
	else if (prio == ThreadPrio_High)
dvander@2726
   270
		res = SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
dvander@2726
   271
	else if (prio == ThreadPrio_Low)
dvander@2726
   272
		res = SetThreadPriority(m_thread, THREAD_PRIORITY_BELOW_NORMAL);
dvander@2726
   273
dvander@2726
   274
	m_params.prio = prio;
dvander@2726
   275
dvander@2726
   276
	return (res != FALSE);
dvander@2726
   277
}
dvander@2726
   278
dvander@2726
   279
bool WinThreader::ThreadHandle::Unpause()
dvander@2726
   280
{
dvander@2726
   281
	if (!m_thread)
dvander@2726
   282
		return false;
dvander@2726
   283
dvander@2726
   284
	if (m_state != Thread_Paused)
dvander@2726
   285
		return false;
dvander@2726
   286
dvander@2726
   287
	m_state = Thread_Running;
dvander@2726
   288
dvander@2726
   289
	if (ResumeThread(m_thread) == -1)
dvander@2726
   290
	{
dvander@2726
   291
		m_state = Thread_Paused;
dvander@2726
   292
		return false;
dvander@2726
   293
	}
dvander@2726
   294
dvander@2726
   295
	return true;
dvander@2726
   296
}
dvander@2726
   297
dvander@2726
   298
/*****************
dvander@2726
   299
 * EVENT SIGNALS *
dvander@2726
   300
 *****************/
dvander@2726
   301
dvander@2726
   302
WinThreader::WinEvent::~WinEvent()
dvander@2726
   303
{
dvander@2726
   304
	CloseHandle(m_event);
dvander@2726
   305
}
dvander@2726
   306
dvander@2726
   307
void WinThreader::WinEvent::Wait()
dvander@2726
   308
{
dvander@2726
   309
	WaitForSingleObject(m_event, INFINITE);
dvander@2726
   310
}
dvander@2726
   311
dvander@2726
   312
void WinThreader::WinEvent::Signal()
dvander@2726
   313
{
dvander@2726
   314
	SetEvent(m_event);
dvander@2726
   315
}
dvander@2726
   316
dvander@2726
   317
void WinThreader::WinEvent::DestroyThis()
dvander@2726
   318
{
dvander@2726
   319
	delete this;
dvander@2726
   320
}