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