/* ZThread.hpp Author : James Russell Created: 07/04/09 Purpose : Wrapper class to allow easy thread creation. By making a class that is a subclass of ZThread and defining the run() method, a thread 'object' can be created that allows for greater consistency and when dealing with thread resources. License: TODO */ #ifndef _ZTHREAD_H #define _ZTHREAD_H #include #include #include #include class ZThread; typedef void (*ZThreadCallbackFunc)(ZThread* executor, void* arg); /* Macro that creates an anonymous request object for marshalling code into a thread request. Example: TODO @param zthread - the zthread object that should execute the request @param argument - the void* argument to pass in (accessible as Arg) @param wait - a boolean indicating if we should wait or not @param code - the actual code that should be executed as part of the request (wrap in parenthesis) */ #define ZTHREAD_EXECUTE(zthread, argument, wait, code) \ { \ class Z##__FUNCTION__##__LINE__##ThreadRequest : public ZThreadRequest \ { \ protected: \ void *Arg; \ public: \ Z##__FUNCTION__##__LINE__##ThreadRequest() : ZThreadRequest(), Arg(argument) { } \ \ virtual void Execute(ZThread *_threadObj) \ { \ code \ } \ }; \ \ zthread->AddThreadRequest(ZPtr(znew Z##__FUNCTION__##__LINE__##ThreadRequest), wait); \ } //Forward declaration of ZThread class ZThread; //Possible return values from ZThread run typedef enum ZThreadReturn { ZTR_TERMINATE, //Indicates the thread should terminate after returning from run ZTR_LOOP, //Indicates the thread should loop after returning from run ZTR_PAUSE, //Indicates the thread should pause after returning from run ZTR_SIZE } ZThreadReturn; /* A ZThread 'Request' object. Used for thread marshaling. */ class ZThreadRequest { friend class ZThread; private: //Completion Event ZEvent CompletedEvent; //Indicates this 'ThreadRequest' should persist until removed bool Persist; //Indicates to the ZThread that this request should stop running immediately //This value is checked before execution bool Stop; public: /* Default Constructor. @param _persist - boolean indicating this thread request should execute continuously until the ZThread object is deleted */ ZThreadRequest(bool _persist = false) : CompletedEvent(), Persist(_persist), Stop(false) { } /* Destructor. Destroys the concurrency event. */ virtual ~ZThreadRequest() { } /* virtual public ZThreadRequest::Execute Virtual method, which defines the thread request to be executed. The function will be executed from within the ZThread object's thread context. If this method is not overridden and Func is not NULL, Func is called with the provided argument. @param _threadObj - the ZThread object executing this request @return (void) */ virtual void Execute(ZThread *_threadObj) = 0; /* public ZThreadRequest::StopExecution Stops execution of the thread request, provided it has not executed yet. @return (void) */ void StopExecution() { this->Stop = true; } /* public ZThreadRequest::Wait Blocks until after the thread request has been executed. @return (void) */ void Wait() { CompletedEvent.Wait(); } }; /* ZThread object class. Should be subclassed to make a threadable 'object'. */ class ZThread { private: DISABLE_COPY_AND_ASSIGN(ZThread); public: /* Default Constructor. @param _threadName - the name of this thread */ ZThread(ZString _threadName = ""); /* Destructor for the ZThread Object. When the ZThread object is deleted, the destructor will wait on the thread to terminate and return resources to the system. */ virtual ~ZThread(); /* public ZThread::AddThreadRequest() Adds a callback that will be executed when the thread loops. @param _request - the thread request to add to the thread's context @return (void) */ void AddThreadRequest(ZPtr _request, bool _wait = false); /* public ZThread::AddCallbackRequest() Adds a callback to be executed by the thread. It can be executed synchronously or asynchronously. @param function - The function to execute @param arg - The argument @param async - If true, this returns immediately, otherwise it waits for the function to execute. @return (void) */ void AddCallbackRequest(ZThreadCallbackFunc function, void* arg, bool async); /* public ZThread::GetThreadID Gets the thread ID of the thread object. @return (uint32_t) - int that is the thread id of the thread object */ uint32_t GetThreadId(); /* public ZThread::GetThreadName Gets the thread name of the ZThread object. The name of a thread is either a string value of the thread id or a name that was set by the ZThread object. @return (ZString) - string representing the 'name' of this thread */ ZString GetThreadName(); /* public ZThread::PauseThread Tells the user thread to pause. @return (void) */ void PauseThread(); /* public ZThread::RestartThread Restarts a paused thread. @return (void) */ void RestartThread(); /* public ZThread::ThreadRunning Indicates if a ZThread object is executing it's run method or is paused. @return (bool) - boolean indicating thread is running or is paused */ bool ThreadRunning(); /* public ZThread::ThreadInitialized Returns true if the ZThread object has called it's initThread() method and returned. @return (bool) - boolean indicating the thread is initialized */ bool ThreadInitialized(); /* public ZThread::ShutdownThread Tells the user thread to shutdown. Blocks until it happens. @return (void) */ void ShutdownThread(); /* public ZThread::StartThread When StartThread is called on a class that extends ZThread, a thread will be created that will call the run() function implemented by the subclass. @return (bool) - boolean indicating the thread has started successfully */ bool StartThread(); /* public ZThread::WaitInitialized Caller waits until the ZThread has initialized. @return (void) @context (all) */ void WaitInitialized(); /* public ZThread::WaitShutdown Caller waits until the ZThread has shutdown. @return (void) @context (all) */ void WaitShutdown(); protected: //Thread 'name' of this thread ZString ThreadName; //Boolean field which, when set to true, indicates the thread should terminate. bool bShouldShutdown; //Boolean field which, when set to true, indicates the thread should pause. bool bShouldPause; /* This is a wrapper around the user run() method, which calls that method in a loop, executing thread requests and setting the condition variables appropriately. */ void Run(); /* Executes the thread requests that may be pending at the time it is called by the subclass. */ void ExecuteThreadRequests(); /* Initialization method which is called when the thread starts. Does not have to be overridden, but any thread specific initialization that must be done in the thread context of the ZThread object needs to be defined here. */ virtual void initThread() { } /* Shutdown method which is called when the thread terminates. Does not have to be overridden, but any thread specific shutdown requirements that must be done in the thread context of the ZThread object needs to be defined here. */ virtual void shutdownThread() { } /* This method must be implemented by the ZThread subclass. This is the 'main' function of execution for the newly created thread. @param _dt - the time (in ms) since last time run was called @return - a ZTHREAD_RETURN value indicating whether the thread should run once (ZTR_TERMINATE), loop (ZTR_RETURN), or pause (ZTR_PAUSE). */ virtual ZThreadReturn run(uint64_t _dt) = 0; bool IsCallerTheThread(); private: struct ZThreadCallbackRequest { ZThreadCallbackFunc callback; void* arg; SST_Event doneEvent; }; //Thread context of this thread ZThreadContext ThreadContext; //The mutex for use by this thread object for handling thread marshaling. ZMutex ThreadLock; //The event signaled when the thread has finished initializing ZEvent InitEvent; //Previous tick count for this thread object uint64_t PreviousTickCount; //Current tick count for this thread object uint64_t CurrentTickCount; //Boolean field which, when set to true, indicates the thread is initialized and running. bool bIsRunning; //Boolean field which, when set to true, indicates the thread has called and returned from initThread() bool bIsInitialized; //List of callbacks that will occur when the ZThread object runs. ZList< ZPtr > ZTRCallbacks; // ZTR callbacks ZList< ZThreadCallbackRequest > Callbacks; // Simple (non-object) callbacks /* Proxy method called by StartThread() which will call initThread and Run on the ZThread Object. @param _runnable - a pointer to the ZThread object to run @return - integer condition (not used) */ static int InitThread(void *_runnable); }; #endif