core/thread/BaseWorker.cpp
author David Anderson <dvander@alliedmods.net>
Thu Jul 12 16:57:26 2007 +0000 (2007-07-12)
changeset 1090 5c54e353c019
parent 1084 241c1b9b4048
child 1231 17badaf66ce4
permissions -rw-r--r--
- added callback functionality to IThreadWorker
- added exposure of IThreader to sample sdk
dvander@1084
     1
/**
dvander@1084
     2
 * vim: set ts=4 :
dvander@1084
     3
 * ===============================================================
dvander@1084
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1084
     5
 * ===============================================================
dvander@1084
     6
 *
dvander@1084
     7
 * This file is not open source and may not be copied without explicit
dvander@1084
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@1084
     9
 * in whole or significant part.
dvander@1084
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@1084
    11
 *
dvander@1084
    12
 * Version: $Id$
dvander@1084
    13
 */
dvander@1084
    14
dvander@1084
    15
#include "BaseWorker.h"
dvander@1084
    16
dvander@1090
    17
BaseWorker::BaseWorker(IThreadWorkerCallbacks *hooks) : 
dvander@1084
    18
	m_perFrame(SM_DEFAULT_THREADS_PER_FRAME),
dvander@1090
    19
	m_state(Worker_Stopped),
dvander@1090
    20
	m_pHooks(hooks)
dvander@1084
    21
{
dvander@1084
    22
}
dvander@1084
    23
dvander@1084
    24
BaseWorker::~BaseWorker()
dvander@1084
    25
{
dvander@1084
    26
	if (m_state != Worker_Stopped || m_state != Worker_Invalid)
dvander@1084
    27
		Stop(true);
dvander@1084
    28
dvander@1084
    29
	if (m_ThreadQueue.size())
dvander@1084
    30
		Flush(true);
dvander@1084
    31
}
dvander@1084
    32
dvander@1084
    33
void BaseWorker::MakeThread(IThread *pThread)
dvander@1084
    34
{
dvander@1084
    35
	ThreadParams pt;
dvander@1084
    36
dvander@1084
    37
	pt.flags = Thread_AutoRelease;
dvander@1084
    38
	pt.prio = ThreadPrio_Normal;
dvander@1084
    39
dvander@1084
    40
	MakeThread(pThread, &pt);
dvander@1084
    41
}
dvander@1084
    42
dvander@1084
    43
IThreadHandle *BaseWorker::MakeThread(IThread *pThread, ThreadFlags flags)
dvander@1084
    44
{
dvander@1084
    45
	ThreadParams pt;
dvander@1084
    46
dvander@1084
    47
	pt.flags = flags;
dvander@1084
    48
	pt.prio = ThreadPrio_Normal;
dvander@1084
    49
dvander@1084
    50
	return MakeThread(pThread, &pt);
dvander@1084
    51
}
dvander@1084
    52
dvander@1084
    53
IThreadHandle *BaseWorker::MakeThread(IThread *pThread, const ThreadParams *params)
dvander@1084
    54
{
dvander@1084
    55
	if (m_state != Worker_Running)
dvander@1084
    56
		return NULL;
dvander@1084
    57
dvander@1084
    58
	SWThreadHandle *swt = new SWThreadHandle(this, params, pThread);
dvander@1084
    59
dvander@1084
    60
	AddThreadToQueue(swt);
dvander@1084
    61
dvander@1084
    62
	return swt;
dvander@1084
    63
}
dvander@1084
    64
dvander@1084
    65
void BaseWorker::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
dvander@1084
    66
{
dvander@1084
    67
	max = ThreadPrio_Normal;
dvander@1084
    68
	min = ThreadPrio_Normal;
dvander@1084
    69
}
dvander@1084
    70
dvander@1084
    71
unsigned int BaseWorker::Flush(bool flush_cancel)
dvander@1084
    72
{
dvander@1084
    73
	SWThreadHandle *swt;
dvander@1084
    74
	unsigned int num = 0;
dvander@1084
    75
dvander@1084
    76
	while ((swt=PopThreadFromQueue()) != NULL)
dvander@1084
    77
	{
dvander@1084
    78
		swt->m_state = Thread_Done;
dvander@1084
    79
		if (!flush_cancel)
dvander@1084
    80
			swt->pThread->RunThread(swt);
dvander@1084
    81
		swt->pThread->OnTerminate(swt, flush_cancel);
dvander@1084
    82
		if (swt->m_params.flags & Thread_AutoRelease)
dvander@1084
    83
			delete swt;
dvander@1084
    84
		num++;
dvander@1084
    85
	}
dvander@1084
    86
dvander@1084
    87
	return num;
dvander@1084
    88
}
dvander@1084
    89
dvander@1084
    90
SWThreadHandle *BaseWorker::PopThreadFromQueue()
dvander@1084
    91
{
dvander@1084
    92
	if (!m_ThreadQueue.size())
dvander@1084
    93
		return NULL;
dvander@1084
    94
dvander@1084
    95
	SourceHook::List<SWThreadHandle *>::iterator begin;
dvander@1084
    96
	SWThreadHandle *swt;
dvander@1084
    97
dvander@1084
    98
	begin = m_ThreadQueue.begin();
dvander@1084
    99
	swt = (*begin);
dvander@1084
   100
	m_ThreadQueue.erase(begin);
dvander@1084
   101
dvander@1084
   102
	return swt;
dvander@1084
   103
}
dvander@1084
   104
dvander@1084
   105
void BaseWorker::AddThreadToQueue(SWThreadHandle *pHandle)
dvander@1084
   106
{
dvander@1084
   107
	m_ThreadQueue.push_back(pHandle);
dvander@1084
   108
}
dvander@1084
   109
dvander@1084
   110
unsigned int BaseWorker::GetMaxThreadsPerFrame()
dvander@1084
   111
{
dvander@1084
   112
	return m_perFrame;
dvander@1084
   113
}
dvander@1084
   114
dvander@1084
   115
WorkerState BaseWorker::GetStatus(unsigned int *threads)
dvander@1084
   116
{
dvander@1084
   117
	if (threads)
dvander@1084
   118
		*threads = m_perFrame;
dvander@1084
   119
dvander@1084
   120
	return m_state;
dvander@1084
   121
}
dvander@1084
   122
dvander@1084
   123
unsigned int BaseWorker::RunFrame()
dvander@1084
   124
{
dvander@1084
   125
	unsigned int done = 0;
dvander@1084
   126
	unsigned int max = GetMaxThreadsPerFrame();
dvander@1084
   127
	SWThreadHandle *swt = NULL;
dvander@1084
   128
	IThread *pThread = NULL;
dvander@1084
   129
dvander@1084
   130
	while (done < max)
dvander@1084
   131
	{
dvander@1084
   132
		if ((swt=PopThreadFromQueue()) == NULL)
dvander@1090
   133
		{
dvander@1084
   134
			break;
dvander@1090
   135
		}
dvander@1084
   136
		pThread = swt->pThread;
dvander@1084
   137
		swt->m_state = Thread_Running;
dvander@1084
   138
		pThread->RunThread(swt);
dvander@1084
   139
		swt->m_state = Thread_Done;
dvander@1084
   140
		pThread->OnTerminate(swt, false);
dvander@1084
   141
		if (swt->m_params.flags & Thread_AutoRelease)
dvander@1090
   142
		{
dvander@1084
   143
			delete swt;
dvander@1090
   144
		}
dvander@1084
   145
		done++;
dvander@1084
   146
	}
dvander@1084
   147
dvander@1084
   148
	return done;
dvander@1084
   149
}
dvander@1084
   150
dvander@1084
   151
void BaseWorker::SetMaxThreadsPerFrame(unsigned int threads)
dvander@1084
   152
{
dvander@1084
   153
	m_perFrame = threads;
dvander@1084
   154
}
dvander@1084
   155
dvander@1084
   156
bool BaseWorker::Start()
dvander@1084
   157
{
dvander@1084
   158
	if (m_state != Worker_Invalid && m_state != Worker_Stopped)
dvander@1084
   159
	{
dvander@1084
   160
		return false;
dvander@1084
   161
	}
dvander@1084
   162
dvander@1084
   163
	m_state = Worker_Running;
dvander@1084
   164
dvander@1090
   165
	if (m_pHooks)
dvander@1090
   166
	{
dvander@1090
   167
		m_pHooks->OnWorkerStart(this);
dvander@1090
   168
	}
dvander@1090
   169
dvander@1084
   170
    return true;
dvander@1084
   171
}
dvander@1084
   172
dvander@1084
   173
bool BaseWorker::Stop(bool flush_cancel)
dvander@1084
   174
{
dvander@1084
   175
	if (m_state == Worker_Invalid || m_state == Worker_Stopped)
dvander@1090
   176
	{
dvander@1084
   177
		return false;
dvander@1090
   178
	}
dvander@1084
   179
dvander@1084
   180
	if (m_state == Worker_Paused)
dvander@1084
   181
	{
dvander@1084
   182
		if (!Unpause())
dvander@1090
   183
		{
dvander@1084
   184
			return false;
dvander@1090
   185
		}
dvander@1084
   186
	}
dvander@1084
   187
dvander@1084
   188
	m_state = Worker_Stopped;
dvander@1084
   189
	Flush(flush_cancel);
dvander@1084
   190
dvander@1090
   191
	if (m_pHooks)
dvander@1090
   192
	{
dvander@1090
   193
		m_pHooks->OnWorkerStop(this);
dvander@1090
   194
	}
dvander@1090
   195
dvander@1084
   196
	return true;
dvander@1084
   197
}
dvander@1084
   198
dvander@1084
   199
bool BaseWorker::Pause()
dvander@1084
   200
{
dvander@1084
   201
	if (m_state != Worker_Running)
dvander@1090
   202
	{
dvander@1084
   203
		return false;
dvander@1090
   204
	}
dvander@1084
   205
dvander@1084
   206
	m_state = Worker_Paused;
dvander@1084
   207
dvander@1084
   208
	return true;
dvander@1084
   209
}
dvander@1084
   210
dvander@1084
   211
dvander@1084
   212
bool BaseWorker::Unpause()
dvander@1084
   213
{
dvander@1084
   214
	if (m_state != Worker_Paused)
dvander@1090
   215
	{
dvander@1084
   216
		return false;
dvander@1090
   217
	}
dvander@1084
   218
dvander@1084
   219
	m_state = Worker_Running;
dvander@1084
   220
dvander@1084
   221
	return true;
dvander@1084
   222
}
dvander@1084
   223
dvander@1084
   224
/***********************
dvander@1084
   225
 * THREAD HANDLE STUFF *
dvander@1084
   226
 ***********************/
dvander@1084
   227
dvander@1084
   228
void SWThreadHandle::DestroyThis()
dvander@1084
   229
{
dvander@1084
   230
	delete this;
dvander@1084
   231
}
dvander@1084
   232
dvander@1084
   233
void SWThreadHandle::GetParams(ThreadParams *p)
dvander@1084
   234
{
dvander@1084
   235
	*p = m_params;
dvander@1084
   236
}
dvander@1084
   237
dvander@1084
   238
ThreadPriority SWThreadHandle::GetPriority()
dvander@1084
   239
{
dvander@1084
   240
	return m_params.prio;
dvander@1084
   241
}
dvander@1084
   242
dvander@1084
   243
ThreadState SWThreadHandle::GetState()
dvander@1084
   244
{
dvander@1084
   245
	return m_state;
dvander@1084
   246
}
dvander@1084
   247
dvander@1084
   248
IThreadCreator *SWThreadHandle::Parent()
dvander@1084
   249
{
dvander@1084
   250
	return m_parent;
dvander@1084
   251
}
dvander@1084
   252
dvander@1084
   253
bool SWThreadHandle::SetPriority(ThreadPriority prio)
dvander@1084
   254
{
dvander@1084
   255
	if (m_params.prio != ThreadPrio_Normal)
dvander@1084
   256
		return false;
dvander@1084
   257
dvander@1084
   258
	m_params.prio = prio;
dvander@1084
   259
dvander@1084
   260
	return true;
dvander@1084
   261
}
dvander@1084
   262
dvander@1084
   263
bool SWThreadHandle::Unpause()
dvander@1084
   264
{
dvander@1084
   265
	if (m_state != Thread_Paused)
dvander@1084
   266
		return false;
dvander@1084
   267
dvander@1084
   268
	m_state = Thread_Running;
dvander@1084
   269
dvander@1084
   270
	return true;
dvander@1084
   271
}
dvander@1084
   272
dvander@1084
   273
bool SWThreadHandle::WaitForThread()
dvander@1084
   274
{
dvander@1084
   275
	return false;
dvander@1084
   276
}
dvander@1084
   277
dvander@1084
   278
SWThreadHandle::SWThreadHandle(IThreadCreator *parent, const ThreadParams *p, IThread *thread) : 
dvander@1084
   279
	m_state(Thread_Paused), m_params(*p), m_parent(parent), pThread(thread)
dvander@1084
   280
{
dvander@1084
   281
}
dvander@1084
   282
dvander@1084
   283
IThread *SWThreadHandle::GetThread()
dvander@1084
   284
{
dvander@1084
   285
	return pThread;
dvander@1084
   286
}