dvander@1084: /**
dvander@1084: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1226: * SourceMod
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@1084: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1084: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1226: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1226: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@1084: *
dvander@1084: * Version: $Id$
dvander@1084: */
dvander@1084:
dvander@1084: #ifndef _INCLUDE_SOURCEMOD_THREADER_H
dvander@1084: #define _INCLUDE_SOURCEMOD_THREADER_H
dvander@1084:
dvander@1084: /**
dvander@1084: * @file IThreader.h
dvander@1084: * @brief Contains platform independent routines for threading.
dvander@1084: */
dvander@1084:
dvander@1084: #include
dvander@1084:
dvander@1084: #define SMINTERFACE_THREADER_NAME "IThreader"
dvander@1090: #define SMINTERFACE_THREADER_VERSION 2
dvander@1084:
dvander@1084: namespace SourceMod
dvander@1084: {
dvander@1084: /**
dvander@1084: * @brief Thread creation flags
dvander@1084: */
dvander@1084: enum ThreadFlags
dvander@1084: {
dvander@1084: Thread_Default = 0,
dvander@1084: /**
dvander@1084: * @brief Auto-release handle on finish
dvander@1084: *
dvander@1084: * You are not guaranteed the handle for this is valid after
dvander@1084: * calling MakeThread(), so never use it until OnTerminate is called.
dvander@1084: */
dvander@1084: Thread_AutoRelease = 1,
dvander@1084: /**
dvander@1084: * @brief Thread is created "suspended", meaning it is inactive until unpaused.
dvander@1084: */
dvander@1084: Thread_CreateSuspended = 2,
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Specifies thread priority levels.
dvander@1084: */
dvander@1084: enum ThreadPriority
dvander@1084: {
dvander@1084: ThreadPrio_Minimum = -8,
dvander@1084: ThreadPrio_Low = -3,
dvander@1084: ThreadPrio_Normal = 0,
dvander@1084: ThreadPrio_High = 3,
dvander@1084: ThreadPrio_Maximum = 8,
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief The current state of a thread.
dvander@1084: */
dvander@1084: enum ThreadState
dvander@1084: {
dvander@1084: Thread_Running = 0,
dvander@1084: Thread_Paused = 1,
dvander@1084: Thread_Done = 2,
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Thread-specific parameters.
dvander@1084: */
dvander@1084: struct ThreadParams
dvander@1084: {
dvander@1084: /** Constructor */
dvander@1084: ThreadParams() :
dvander@1084: flags(Thread_Default),
dvander@1084: prio(ThreadPrio_Normal)
dvander@1084: {
dvander@1084: };
dvander@1084: ThreadFlags flags; /**< Flags to set on the thread */
dvander@1084: ThreadPriority prio; /**< Priority to set on the thread */
dvander@1084: };
dvander@1084:
dvander@1084: class IThreadCreator;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Describes a handle to a thread.
dvander@1084: */
dvander@1084: class IThreadHandle
dvander@1084: {
dvander@1084: public:
dvander@1084: /** Virtual destructor */
dvander@1084: virtual ~IThreadHandle() { };
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Pauses parent thread until this thread completes.
dvander@1084: *
dvander@1084: * @return True if successful, false otherwise.
dvander@1084: */
dvander@1084: virtual bool WaitForThread() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Destroys the thread handle. This will not necessarily cancel the thread.
dvander@1084: */
dvander@1084: virtual void DestroyThis() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Returns the parent threader.
dvander@1084: *
dvander@1084: * @return IThreadCreator that created this thread.
dvander@1084: */
dvander@1084: virtual IThreadCreator *Parent() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Returns the thread states.
dvander@1084: *
dvander@1084: * @param ptparams Pointer to a ThreadParams buffer.
dvander@1084: */
dvander@1084: virtual void GetParams(ThreadParams *ptparams) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Returns the thread priority.
dvander@1084: *
dvander@1084: * @return Thread priority.
dvander@1084: */
dvander@1084: virtual ThreadPriority GetPriority() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Sets thread priority.
dvander@1084: * NOTE: On Linux, this always returns false.
dvander@1084: *
dvander@1084: * @param prio Thread priority to set.
dvander@1084: * @return True if successful, false otherwise.
dvander@1084: */
dvander@1084: virtual bool SetPriority(ThreadPriority prio) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Returns the thread state.
dvander@1084: *
dvander@1084: * @return Current thread state.
dvander@1084: */
dvander@1084: virtual ThreadState GetState() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Attempts to unpause a paused thread.
dvander@1084: *
dvander@1084: * @return True on success, false otherwise.
dvander@1084: */
dvander@1084: virtual bool Unpause() =0;
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Handles a single thread's execution.
dvander@1084: */
dvander@1084: class IThread
dvander@1084: {
dvander@1084: public:
dvander@1084: /** Virtual destructor */
dvander@1084: virtual ~IThread() { };
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Called when the thread runs (in its own thread).
dvander@1084: *
dvander@1084: * @param pHandle Pointer to the thread's handle.
dvander@1084: */
dvander@1084: virtual void RunThread(IThreadHandle *pHandle) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Called when the thread terminates. This occurs inside the thread as well.
dvander@1084: *
dvander@1084: * @param pHandle Pointer to the thread's handle.
dvander@1084: * @param cancel True if the thread did not finish, false otherwise.
dvander@1084: */
dvander@1084: virtual void OnTerminate(IThreadHandle *pHandle, bool cancel) =0;
dvander@1084: };
dvander@1084:
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Describes a thread creator
dvander@1084: */
dvander@1084: class IThreadCreator
dvander@1084: {
dvander@1084: public:
dvander@1084: /** Virtual Destructor */
dvander@1084: virtual ~IThreadCreator() { };
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Creates a basic thread.
dvander@1084: *
dvander@1084: * @param pThread IThread pointer for callbacks.
dvander@1084: */
dvander@1084: virtual void MakeThread(IThread *pThread) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Creates a thread with specific options.
dvander@1084: *
dvander@1084: * @param pThread IThread pointer for callbacks.
dvander@1084: * @param flags Flags for the thread.
dvander@1084: * @return IThreadHandle pointer (must be released).
dvander@1084: */
dvander@1084: virtual IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Creates a thread with specific options.
dvander@1084: *
dvander@1084: * @param pThread IThread pointer for callbacks.
dvander@1084: * @param params Extended options for the thread.
dvander@1084: * @return IThreadHandle pointer (must be released).
dvander@1084: */
dvander@1084: virtual IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Returns the priority bounds.
dvander@1084: * Note: On Linux, the min and max are both Thread_Normal.
dvander@1084: *
dvander@1084: * @param max Stores the maximum priority level.
dvander@1084: * @param min Stores the minimum priority level.
dvander@1084: */
dvander@1084: virtual void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) =0;
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Describes a simple locking mutex.
dvander@1084: */
dvander@1084: class IMutex
dvander@1084: {
dvander@1084: public:
dvander@1084: /** Virtual Destructor */
dvander@1084: virtual ~IMutex() { };
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Attempts to lock, but returns instantly.
dvander@1084: *
dvander@1084: * @return True if lock was obtained, false otherwise.
dvander@1084: */
dvander@1084: virtual bool TryLock() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Attempts to lock by waiting for release.
dvander@1084: */
dvander@1084: virtual void Lock() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Unlocks the mutex.
dvander@1084: */
dvander@1084: virtual void Unlock() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Destroys the mutex handle.
dvander@1084: */
dvander@1084: virtual void DestroyThis() =0;
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Describes a simple "condition variable"/signal lock.
dvander@1084: */
dvander@1084: class IEventSignal
dvander@1084: {
dvander@1084: public:
dvander@1084: /** Virtual Destructor */
dvander@1084: virtual ~IEventSignal() { };
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Waits for a signal.
dvander@1084: */
dvander@1084: virtual void Wait() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Triggers the signal and resets the signal after triggering.
dvander@1084: */
dvander@1084: virtual void Signal() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Frees the signal handle.
dvander@1084: */
dvander@1084: virtual void DestroyThis() =0;
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Describes possible worker states
dvander@1084: */
dvander@1084: enum WorkerState
dvander@1084: {
dvander@1084: Worker_Invalid = -3,
dvander@1084: Worker_Stopped = -2,
dvander@1084: Worker_Paused = -1,
dvander@1084: Worker_Running,
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief This is a "worker pool." A single thread places tasks in a queue.
dvander@1084: * Each IThread is then a task, rather than its own separate thread.
dvander@1084: */
dvander@1084: class IThreadWorker : public IThreadCreator
dvander@1084: {
dvander@1084: public:
dvander@1084: /** Virtual Destructor */
dvander@1084: virtual ~IThreadWorker()
dvander@1084: {
dvander@1084: };
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Runs one "frame" of the worker.
dvander@1084: *
dvander@1084: * @return Number of tasks processed.
dvander@1084: */
dvander@1084: virtual unsigned int RunFrame() =0;
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Pauses the worker.
dvander@1084: *
dvander@1084: * @return True on success, false otherwise.
dvander@1084: */
dvander@1084: virtual bool Pause() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Unpauses the worker.
dvander@1084: *
dvander@1084: * @return True on success, false otherwise.
dvander@1084: */
dvander@1084: virtual bool Unpause() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Starts the worker thread.
dvander@1084: *
dvander@1084: * @return True on success, false otherwise.
dvander@1084: */
dvander@1084: virtual bool Start() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Stops the worker thread.
dvander@1084: *
dvander@1084: * @param flush If true, all remaining tasks will be cancelled.
dvander@1084: * Otherwise, the threader will wait until the queue is empty.
dvander@1084: * @return True on success, false otherwise.
dvander@1084: */
dvander@1084: virtual bool Stop(bool flush) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Returns the status of the worker.
dvander@1084: *
dvander@1084: * @param numThreads Pointer to store number of threads in the queue.
dvander@1084: * @return State of the worker.
dvander@1084: */
dvander@1084: virtual WorkerState GetStatus(unsigned int *numThreads) =0;
dvander@1084: };
dvander@1084:
dvander@1084: /**
dvander@1090: * @brief Describes thread worker callbacks.
dvander@1090: */
dvander@1090: class IThreadWorkerCallbacks
dvander@1090: {
dvander@1090: public:
dvander@1090: /**
dvander@1090: * @brief Called when the worker thread is initialized.
dvander@1090: *
dvander@1090: * @param pWorker Pointer to the worker.
dvander@1090: */
dvander@1090: virtual void OnWorkerStart(IThreadWorker *pWorker)
dvander@1090: {
dvander@1090: }
dvander@1090:
dvander@1090: /**
dvander@1090: * @brief Called when the worker thread is cleaning up.
dvander@1090: *
dvander@1090: * @param pWorker Pointer to the worker.
dvander@1090: */
dvander@1090: virtual void OnWorkerStop(IThreadWorker *pWorker)
dvander@1090: {
dvander@1090: }
dvander@1090: };
dvander@1090:
dvander@1090: /**
dvander@1084: * @brief Describes a threading system
dvander@1084: */
dvander@1084: class IThreader : public SMInterface, public IThreadCreator
dvander@1084: {
dvander@1084: public:
dvander@1084: virtual const char *GetInterfaceName()
dvander@1084: {
dvander@1084: return SMINTERFACE_THREADER_NAME;
dvander@1084: }
dvander@1084: virtual unsigned int GetInterfaceVersion()
dvander@1084: {
dvander@1084: return SMINTERFACE_THREADER_VERSION;
dvander@1084: }
dvander@1090: virtual bool IsVersionCompatible(unsigned int version)
dvander@1090: {
dvander@1090: if (version < 2)
dvander@1090: {
dvander@1090: return false;
dvander@1090: }
dvander@1090: return SMInterface::IsVersionCompatible(version);
dvander@1090: }
dvander@1084: public:
dvander@1084: /**
dvander@1084: * @brief Creates a mutex (mutual exclusion lock).
dvander@1084: *
dvander@1084: * @return A new IMutex pointer (must be destroyed).
dvander@1084: */
dvander@1084: virtual IMutex *MakeMutex() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Sleeps the calling thread for a number of milliseconds.
dvander@1084: *
dvander@1084: * @param ms Millisecond count to sleep.
dvander@1084: */
dvander@1084: virtual void ThreadSleep(unsigned int ms) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Creates a non-signalled event.
dvander@1084: *
dvander@1084: * @return A new IEventSignal pointer (must be destroyed).
dvander@1084: */
dvander@1084: virtual IEventSignal *MakeEventSignal() =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Creates a thread worker.
dvander@1084: *
dvander@1090: * @param hooks Optional pointer to callback interface.
dvander@1084: * @param threaded If true, the worker will be threaded.
dvander@1084: * If false, the worker will require manual frame execution.
dvander@1084: * @return A new IThreadWorker pointer (must be destroyed).
dvander@1084: */
dvander@1090: virtual IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded) =0;
dvander@1084:
dvander@1084: /**
dvander@1084: * @brief Destroys an IThreadWorker pointer.
dvander@1084: *
dvander@1084: * @param pWorker IThreadWorker pointer to destroy.
dvander@1084: */
dvander@1084: virtual void DestroyWorker(IThreadWorker *pWorker) =0;
dvander@1084: };
dvander@1084: };
dvander@1084:
dvander@1084: #endif //_INCLUDE_SOURCEMOD_THREADER_H