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