- added callback functionality to IThreadWorker

- added exposure of IThreader to sample sdk

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401096
This commit is contained in:
David Anderson 2007-07-12 16:57:26 +00:00
parent 8a8e6ef594
commit 529933739d
12 changed files with 119 additions and 17 deletions

View File

@ -14,9 +14,10 @@
#include "BaseWorker.h" #include "BaseWorker.h"
BaseWorker::BaseWorker() : BaseWorker::BaseWorker(IThreadWorkerCallbacks *hooks) :
m_perFrame(SM_DEFAULT_THREADS_PER_FRAME), m_perFrame(SM_DEFAULT_THREADS_PER_FRAME),
m_state(Worker_Stopped) m_state(Worker_Stopped),
m_pHooks(hooks)
{ {
} }
@ -129,14 +130,18 @@ unsigned int BaseWorker::RunFrame()
while (done < max) while (done < max)
{ {
if ((swt=PopThreadFromQueue()) == NULL) if ((swt=PopThreadFromQueue()) == NULL)
{
break; break;
}
pThread = swt->pThread; pThread = swt->pThread;
swt->m_state = Thread_Running; swt->m_state = Thread_Running;
pThread->RunThread(swt); pThread->RunThread(swt);
swt->m_state = Thread_Done; swt->m_state = Thread_Done;
pThread->OnTerminate(swt, false); pThread->OnTerminate(swt, false);
if (swt->m_params.flags & Thread_AutoRelease) if (swt->m_params.flags & Thread_AutoRelease)
{
delete swt; delete swt;
}
done++; done++;
} }
@ -157,30 +162,46 @@ bool BaseWorker::Start()
m_state = Worker_Running; m_state = Worker_Running;
if (m_pHooks)
{
m_pHooks->OnWorkerStart(this);
}
return true; return true;
} }
bool BaseWorker::Stop(bool flush_cancel) bool BaseWorker::Stop(bool flush_cancel)
{ {
if (m_state == Worker_Invalid || m_state == Worker_Stopped) if (m_state == Worker_Invalid || m_state == Worker_Stopped)
{
return false; return false;
}
if (m_state == Worker_Paused) if (m_state == Worker_Paused)
{ {
if (!Unpause()) if (!Unpause())
{
return false; return false;
}
} }
m_state = Worker_Stopped; m_state = Worker_Stopped;
Flush(flush_cancel); Flush(flush_cancel);
if (m_pHooks)
{
m_pHooks->OnWorkerStop(this);
}
return true; return true;
} }
bool BaseWorker::Pause() bool BaseWorker::Pause()
{ {
if (m_state != Worker_Running) if (m_state != Worker_Running)
{
return false; return false;
}
m_state = Worker_Paused; m_state = Worker_Paused;
@ -191,7 +212,9 @@ bool BaseWorker::Pause()
bool BaseWorker::Unpause() bool BaseWorker::Unpause()
{ {
if (m_state != Worker_Paused) if (m_state != Worker_Paused)
{
return false; return false;
}
m_state = Worker_Running; m_state = Worker_Running;

View File

@ -54,7 +54,7 @@ private:
class BaseWorker : public IThreadWorker class BaseWorker : public IThreadWorker
{ {
public: public:
BaseWorker(); BaseWorker(IThreadWorkerCallbacks *hooks);
virtual ~BaseWorker(); virtual ~BaseWorker();
public: //IWorker public: //IWorker
virtual unsigned int RunFrame(); virtual unsigned int RunFrame();
@ -81,6 +81,7 @@ protected:
SourceHook::List<SWThreadHandle *> m_ThreadQueue; SourceHook::List<SWThreadHandle *> m_ThreadQueue;
unsigned int m_perFrame; unsigned int m_perFrame;
volatile WorkerState m_state; volatile WorkerState m_state;
IThreadWorkerCallbacks *m_pHooks;
}; };
#endif //_INCLUDE_SOURCEMOD_BASEWORKER_H #endif //_INCLUDE_SOURCEMOD_BASEWORKER_H

View File

@ -25,13 +25,13 @@
#include "PosixThreads.h" #include "PosixThreads.h"
#include "ThreadWorker.h" #include "ThreadWorker.h"
IThreadWorker *PosixThreader::MakeWorker(bool threaded) IThreadWorker *PosixThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
{ {
if (threaded) if (threaded)
{ {
return new ThreadWorker(this, DEFAULT_THINK_TIME_MS); return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
} else { } else {
return new BaseWorker(); return new BaseWorker(hooks);
} }
} }

View File

@ -95,7 +95,7 @@ public:
void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min); void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
void ThreadSleep(unsigned int ms); void ThreadSleep(unsigned int ms);
IEventSignal *MakeEventSignal(); IEventSignal *MakeEventSignal();
IThreadWorker *MakeWorker(bool threaded); IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded);
void DestroyWorker(IThreadWorker *pWorker); void DestroyWorker(IThreadWorker *pWorker);
}; };

View File

@ -14,7 +14,7 @@
#include "ThreadWorker.h" #include "ThreadWorker.h"
ThreadWorker::ThreadWorker() : ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks) : BaseWorker(hooks),
m_Threader(NULL), m_Threader(NULL),
m_QueueLock(NULL), m_QueueLock(NULL),
m_StateLock(NULL), m_StateLock(NULL),
@ -26,7 +26,8 @@ ThreadWorker::ThreadWorker() :
m_state = Worker_Invalid; m_state = Worker_Invalid;
} }
ThreadWorker::ThreadWorker(IThreader *pThreader, unsigned int thinktime) : ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime) :
BaseWorker(hooks),
m_Threader(pThreader), m_Threader(pThreader),
m_QueueLock(NULL), m_QueueLock(NULL),
m_StateLock(NULL), m_StateLock(NULL),
@ -46,10 +47,14 @@ ThreadWorker::ThreadWorker(IThreader *pThreader, unsigned int thinktime) :
ThreadWorker::~ThreadWorker() ThreadWorker::~ThreadWorker()
{ {
if (m_state != Worker_Stopped || m_state != Worker_Invalid) if (m_state != Worker_Stopped || m_state != Worker_Invalid)
{
Stop(true); Stop(true);
}
if (m_ThreadQueue.size()) if (m_ThreadQueue.size())
{
Flush(true); Flush(true);
}
} }
void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel) void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
@ -62,6 +67,11 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle)
{ {
WorkerState this_state = Worker_Running; WorkerState this_state = Worker_Running;
size_t num; size_t num;
if (m_pHooks)
{
m_pHooks->OnWorkerStart(this);
}
while (true) while (true)
{ {
@ -112,7 +122,9 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle)
if (!m_FlushType) if (!m_FlushType)
{ {
while (m_ThreadQueue.size()) while (m_ThreadQueue.size())
{
RunFrame(); RunFrame();
}
} }
break; break;
} }
@ -127,14 +139,23 @@ void ThreadWorker::RunThread(IThreadHandle *pHandle)
* wait in between threads if specified * wait in between threads if specified
*/ */
if (m_think_time) if (m_think_time)
{
m_Threader->ThreadSleep(m_think_time); m_Threader->ThreadSleep(m_think_time);
}
}
if (m_pHooks)
{
m_pHooks->OnWorkerStop(this);
} }
} }
SWThreadHandle *ThreadWorker::PopThreadFromQueue() SWThreadHandle *ThreadWorker::PopThreadFromQueue()
{ {
if (m_state <= Worker_Stopped && !m_QueueLock) if (m_state <= Worker_Stopped && !m_QueueLock)
{
return NULL; return NULL;
}
SWThreadHandle *swt; SWThreadHandle *swt;
m_QueueLock->Lock(); m_QueueLock->Lock();
@ -147,7 +168,9 @@ SWThreadHandle *ThreadWorker::PopThreadFromQueue()
void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle) void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
{ {
if (m_state <= Worker_Stopped) if (m_state <= Worker_Stopped)
{
return; return;
}
m_QueueLock->Lock(); m_QueueLock->Lock();
BaseWorker::AddThreadToQueue(pHandle); BaseWorker::AddThreadToQueue(pHandle);
@ -174,7 +197,9 @@ bool ThreadWorker::Start()
if (m_state == Worker_Invalid) if (m_state == Worker_Invalid)
{ {
if (m_Threader == NULL) if (m_Threader == NULL)
{
return false; return false;
}
} else if (m_state != Worker_Stopped) { } else if (m_state != Worker_Stopped) {
return false; return false;
} }
@ -196,7 +221,9 @@ bool ThreadWorker::Start()
bool ThreadWorker::Stop(bool flush_cancel) bool ThreadWorker::Stop(bool flush_cancel)
{ {
if (m_state == Worker_Invalid || m_state == Worker_Stopped) if (m_state == Worker_Invalid || m_state == Worker_Stopped)
{
return false; return false;
}
WorkerState oldstate; WorkerState oldstate;
@ -244,7 +271,9 @@ bool ThreadWorker::Stop(bool flush_cancel)
bool ThreadWorker::Pause() bool ThreadWorker::Pause()
{ {
if (m_state != Worker_Running) if (m_state != Worker_Running)
{
return false; return false;
}
m_StateLock->Lock(); m_StateLock->Lock();
m_state = Worker_Paused; m_state = Worker_Paused;
@ -257,7 +286,9 @@ bool ThreadWorker::Pause()
bool ThreadWorker::Unpause() bool ThreadWorker::Unpause()
{ {
if (m_state != Worker_Paused) if (m_state != Worker_Paused)
{
return false; return false;
}
m_StateLock->Lock(); m_StateLock->Lock();
m_state = Worker_Running; m_state = Worker_Running;

View File

@ -22,8 +22,8 @@
class ThreadWorker : public BaseWorker, public IThread class ThreadWorker : public BaseWorker, public IThread
{ {
public: public:
ThreadWorker(); ThreadWorker(IThreadWorkerCallbacks *hooks);
ThreadWorker(IThreader *pThreader, unsigned int thinktime=DEFAULT_THINK_TIME_MS); ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime=DEFAULT_THINK_TIME_MS);
virtual ~ThreadWorker(); virtual ~ThreadWorker();
public: //IThread public: //IThread
virtual void OnTerminate(IThreadHandle *pHandle, bool cancel); virtual void OnTerminate(IThreadHandle *pHandle, bool cancel);

View File

@ -16,13 +16,13 @@
#include "WinThreads.h" #include "WinThreads.h"
#include "ThreadWorker.h" #include "ThreadWorker.h"
IThreadWorker *WinThreader::MakeWorker(bool threaded) IThreadWorker *WinThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
{ {
if (threaded) if (threaded)
{ {
return new ThreadWorker(this, DEFAULT_THINK_TIME_MS); return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
} else { } else {
return new BaseWorker(); return new BaseWorker(hooks);
} }
} }

View File

@ -84,7 +84,7 @@ public:
void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min); void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
void ThreadSleep(unsigned int ms); void ThreadSleep(unsigned int ms);
IEventSignal *MakeEventSignal(); IEventSignal *MakeEventSignal();
IThreadWorker *MakeWorker(bool threaded); IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded);
void DestroyWorker(IThreadWorker *pWorker); void DestroyWorker(IThreadWorker *pWorker);
}; };

View File

@ -27,7 +27,7 @@
#include <IShareSys.h> #include <IShareSys.h>
#define SMINTERFACE_THREADER_NAME "IThreader" #define SMINTERFACE_THREADER_NAME "IThreader"
#define SMINTERFACE_THREADER_VERSION 1 #define SMINTERFACE_THREADER_VERSION 2
namespace SourceMod namespace SourceMod
{ {
@ -351,6 +351,31 @@ namespace SourceMod
virtual WorkerState GetStatus(unsigned int *numThreads) =0; virtual WorkerState GetStatus(unsigned int *numThreads) =0;
}; };
/**
* @brief Describes thread worker callbacks.
*/
class IThreadWorkerCallbacks
{
public:
/**
* @brief Called when the worker thread is initialized.
*
* @param pWorker Pointer to the worker.
*/
virtual void OnWorkerStart(IThreadWorker *pWorker)
{
}
/**
* @brief Called when the worker thread is cleaning up.
*
* @param pWorker Pointer to the worker.
*/
virtual void OnWorkerStop(IThreadWorker *pWorker)
{
}
};
/** /**
* @brief Describes a threading system * @brief Describes a threading system
*/ */
@ -365,6 +390,14 @@ namespace SourceMod
{ {
return SMINTERFACE_THREADER_VERSION; return SMINTERFACE_THREADER_VERSION;
} }
virtual bool IsVersionCompatible(unsigned int version)
{
if (version < 2)
{
return false;
}
return SMInterface::IsVersionCompatible(version);
}
public: public:
/** /**
* @brief Creates a mutex (mutual exclusion lock). * @brief Creates a mutex (mutual exclusion lock).
@ -390,11 +423,12 @@ namespace SourceMod
/** /**
* @brief Creates a thread worker. * @brief Creates a thread worker.
* *
* @param hooks Optional pointer to callback interface.
* @param threaded If true, the worker will be threaded. * @param threaded If true, the worker will be threaded.
* If false, the worker will require manual frame execution. * If false, the worker will require manual frame execution.
* @return A new IThreadWorker pointer (must be destroyed). * @return A new IThreadWorker pointer (must be destroyed).
*/ */
virtual IThreadWorker *MakeWorker(bool threaded) =0; virtual IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded) =0;
/** /**
* @brief Destroys an IThreadWorker pointer. * @brief Destroys an IThreadWorker pointer.

View File

@ -54,5 +54,6 @@
//#define SMEXT_ENABLE_MEMUTILS //#define SMEXT_ENABLE_MEMUTILS
//#define SMEXT_ENABLE_GAMEHELPERS //#define SMEXT_ENABLE_GAMEHELPERS
//#define SMEXT_ENABLE_TIMERSYS //#define SMEXT_ENABLE_TIMERSYS
//#define SMEXT_ENABLE_THREADER
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ #endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_

View File

@ -60,6 +60,9 @@ ITimerSystem *timersys = NULL;
#if defined SMEXT_ENABLE_ADTFACTORY #if defined SMEXT_ENABLE_ADTFACTORY
IADTFactory *adtfactory = NULL; IADTFactory *adtfactory = NULL;
#endif #endif
#if defined SMEXT_ENABLE_THREADER
IThreader *threader = NULL;
#endif
/** Exports the main interface */ /** Exports the main interface */
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI() PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
@ -124,6 +127,9 @@ bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error,
#if defined SMEXT_ENABLE_ADTFACTORY #if defined SMEXT_ENABLE_ADTFACTORY
SM_GET_IFACE(ADTFACTORY, adtfactory); SM_GET_IFACE(ADTFACTORY, adtfactory);
#endif #endif
#if defined SMEXT_ENABLE_THREADER
SM_GET_IFACE(THREADER, threader);
#endif
if (SDK_OnLoad(error, maxlength, late)) if (SDK_OnLoad(error, maxlength, late))
{ {

View File

@ -54,6 +54,9 @@
#if defined SMEXT_ENABLE_ADTFACTORY #if defined SMEXT_ENABLE_ADTFACTORY
#include <IADTFactory.h> #include <IADTFactory.h>
#endif #endif
#if defined SMEXT_ENABLE_THREADER
#include <IThreader.h>
#endif
#if defined SMEXT_CONF_METAMOD #if defined SMEXT_CONF_METAMOD
#include <ISmmPlugin.h> #include <ISmmPlugin.h>
@ -231,6 +234,9 @@ extern ITimerSystem *timersys;
#if defined SMEXT_ENABLE_ADTFACTORY #if defined SMEXT_ENABLE_ADTFACTORY
extern IADTFactory *adtfactory; extern IADTFactory *adtfactory;
#endif #endif
#if defined SMEXT_ENABLE_THREADER
extern IThreader *threader;
#endif
#if defined SMEXT_CONF_METAMOD #if defined SMEXT_CONF_METAMOD
PLUGIN_GLOBALVARS(); PLUGIN_GLOBALVARS();