00001 /************************************************************************************ 00002 00003 PublicHeader: None 00004 Filename : OVR_Threads.h 00005 Content : Contains thread-related (safe) functionality 00006 Created : September 19, 2012 00007 Notes : 00008 00009 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 00010 00011 Use of this software is subject to the terms of the Oculus license 00012 agreement provided at the time of installation or download, or which 00013 otherwise accompanies this software in either electronic or hard copy form. 00014 00015 ************************************************************************************/ 00016 #ifndef OVR_Threads_h 00017 #define OVR_Threads_h 00018 00019 #include "OVR_Types.h" 00020 #include "OVR_Atomic.h" 00021 #include "OVR_RefCount.h" 00022 #include "OVR_Array.h" 00023 00024 // Defines the infinite wait delay timeout 00025 #define OVR_WAIT_INFINITE 0xFFFFFFFF 00026 00027 // To be defined in the project configuration options 00028 #ifdef OVR_ENABLE_THREADS 00029 00030 00031 namespace OVR { 00032 00033 //----------------------------------------------------------------------------------- 00034 // ****** Declared classes 00035 00036 // Declared with thread support only 00037 class Mutex; 00038 class WaitCondition; 00039 class Event; 00040 // Implementation forward declarations 00041 class MutexImpl; 00042 class WaitConditionImpl; 00043 00044 00045 00046 //----------------------------------------------------------------------------------- 00047 // ***** Mutex 00048 00049 // Mutex class represents a system Mutex synchronization object that provides access 00050 // serialization between different threads, allowing one thread mutually exclusive access 00051 // to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition. 00052 00053 class Mutex 00054 { 00055 friend class WaitConditionImpl; 00056 friend class MutexImpl; 00057 00058 MutexImpl *pImpl; 00059 00060 public: 00061 // Constructor/destructor 00062 Mutex(bool recursive = 1); 00063 ~Mutex(); 00064 00065 // Locking functions 00066 void DoLock(); 00067 bool TryLock(); 00068 void Unlock(); 00069 00070 // Returns 1 if the mutes is currently locked by another thread 00071 // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 00072 bool IsLockedByAnotherThread(); 00073 00074 // Locker class; Used for automatic locking of a mutex withing scope 00075 class Locker 00076 { 00077 public: 00078 Mutex *pMutex; 00079 Locker(Mutex *pmutex) 00080 { pMutex = pmutex; pMutex->DoLock(); } 00081 ~Locker() 00082 { pMutex->Unlock(); } 00083 }; 00084 }; 00085 00086 00087 //----------------------------------------------------------------------------------- 00088 // ***** WaitCondition 00089 00090 /* 00091 WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor. 00092 Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that 00093 call Notify() or NotifyAll(). 00094 00095 The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 00096 starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same 00097 resource, this ensures that any condition checked for while the mutex was locked does not change before 00098 the wait on the condition is actually initiated. 00099 */ 00100 00101 class WaitCondition 00102 { 00103 friend class WaitConditionImpl; 00104 // Internal implementation structure 00105 WaitConditionImpl *pImpl; 00106 00107 public: 00108 // Constructor/destructor 00109 WaitCondition(); 00110 ~WaitCondition(); 00111 00112 // Release mutex and wait for condition. The mutex is re-aquired after the wait. 00113 // Delay is specified in milliseconds (1/1000 of a second). 00114 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 00115 00116 // Notify a condition, releasing at one object waiting 00117 void Notify(); 00118 // Notify a condition, releasing all objects waiting 00119 void NotifyAll(); 00120 }; 00121 00122 00123 //----------------------------------------------------------------------------------- 00124 // ***** Event 00125 00126 // Event is a wait-able synchronization object similar to Windows event. 00127 // Event can be waited on until it's signaled by another thread calling 00128 // either SetEvent or PulseEvent. 00129 00130 class Event 00131 { 00132 // Event state, its mutex and the wait condition 00133 volatile bool State; 00134 volatile bool Temporary; 00135 mutable Mutex StateMutex; 00136 WaitCondition StateWaitCondition; 00137 00138 void updateState(bool newState, bool newTemp, bool mustNotify); 00139 00140 public: 00141 Event(bool setInitially = 0) : State(setInitially), Temporary(false) { } 00142 ~Event() { } 00143 00144 // Wait on an event condition until it is set 00145 // Delay is specified in milliseconds (1/1000 of a second). 00146 bool Wait(unsigned delay = OVR_WAIT_INFINITE); 00147 00148 // Set an event, releasing objects waiting on it 00149 void SetEvent() 00150 { updateState(true, false, true); } 00151 00152 // Reset an event, un-signaling it 00153 void ResetEvent() 00154 { updateState(false, false, false); } 00155 00156 // Set and then reset an event once a waiter is released. 00157 // If threads are already waiting, they will be notified and released 00158 // If threads are not waiting, the event is set until the first thread comes in 00159 void PulseEvent() 00160 { updateState(true, true, true); } 00161 }; 00162 00163 00164 //----------------------------------------------------------------------------------- 00165 // ***** Thread class 00166 00167 // ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and 00168 // Thread::GetThreadId. 00169 typedef void* ThreadId; 00170 00171 00172 // *** Thread flags 00173 00174 // Indicates that the thread is has been started, i.e. Start method has been called, and threads 00175 // OnExit() method has not yet been called/returned. 00176 #define OVR_THREAD_STARTED 0x01 00177 // This flag is set once the thread has ran, and finished. 00178 #define OVR_THREAD_FINISHED 0x02 00179 // This flag is set temporarily if this thread was started suspended. It is used internally. 00180 #define OVR_THREAD_START_SUSPENDED 0x08 00181 // This flag is used to ask a thread to exit. Message driven threads will usually check this flag 00182 // and finish once it is set. 00183 #define OVR_THREAD_EXIT 0x10 00184 00185 00186 class Thread : public RefCountBase<Thread> 00187 { // NOTE: Waitable must be the first base since it implements RefCountImpl. 00188 00189 public: 00190 00191 // *** Callback functions, can be used instead of overriding Run 00192 00193 // Run function prototypes. 00194 // Thread function and user handle passed to it, executed by the default 00195 // Thread::Run implementation if not null. 00196 typedef int (*ThreadFn)(Thread *pthread, void* h); 00197 00198 // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried 00199 ThreadFn ThreadFunction; 00200 // User handle passes to a thread 00201 void* UserHandle; 00202 00203 // Thread state to start a thread with 00204 enum ThreadState 00205 { 00206 NotRunning = 0, 00207 Running = 1, 00208 Suspended = 2 00209 }; 00210 00211 // Thread priority 00212 enum ThreadPriority 00213 { 00214 CriticalPriority, 00215 HighestPriority, 00216 AboveNormalPriority, 00217 NormalPriority, 00218 BelowNormalPriority, 00219 LowestPriority, 00220 IdlePriority, 00221 }; 00222 00223 // Thread constructor parameters 00224 struct CreateParams 00225 { 00226 CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, 00227 int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority) 00228 : threadFunction(func), userHandle(hand), stackSize(ssize), 00229 processor(proc), initialState(state), priority(prior) {} 00230 ThreadFn threadFunction; // Thread function 00231 void* userHandle; // User handle passes to a thread 00232 UPInt stackSize; // Thread stack size 00233 int processor; // Thread hardware processor 00234 ThreadState initialState; // 00235 ThreadPriority priority; // Thread priority 00236 }; 00237 00238 // *** Constructors 00239 00240 // A default constructor always creates a thread in NotRunning state, because 00241 // the derived class has not yet been initialized. The derived class can call Start explicitly. 00242 // "processor" parameter specifies which hardware processor this thread will be run on. 00243 // -1 means OS decides this. Implemented only on Win32 00244 Thread(UPInt stackSize = 128 * 1024, int processor = -1); 00245 // Constructors that initialize the thread with a pointer to function. 00246 // An option to start a thread is available, but it should not be used if classes are derived from Thread. 00247 // "processor" parameter specifies which hardware processor this thread will be run on. 00248 // -1 means OS decides this. Implemented only on Win32 00249 Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024, 00250 int processor = -1, ThreadState initialState = NotRunning); 00251 // Constructors that initialize the thread with a create parameters structure. 00252 explicit Thread(const CreateParams& params); 00253 00254 // Destructor. 00255 virtual ~Thread(); 00256 00257 // Waits for all Threads to finish; should be called only from the root 00258 // application thread. Once this function returns, we know that all other 00259 // thread's references to Thread object have been released. 00260 static void OVR_CDECL FinishAllThreads(); 00261 00262 00263 // *** Overridable Run function for thread processing 00264 00265 // - returning from this method will end the execution of the thread 00266 // - return value is usually 0 for success 00267 virtual int Run(); 00268 // Called after return/exit function 00269 virtual void OnExit(); 00270 00271 00272 // *** Thread management 00273 00274 // Starts the thread if its not already running 00275 // - internally sets up the threading and calls Run() 00276 // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing 00277 // - returns the exit code 00278 virtual bool Start(ThreadState initialState = Running); 00279 00280 // Quits with an exit code 00281 virtual void Exit(int exitCode=0); 00282 00283 // Suspend the thread until resumed 00284 // Returns 1 for success, 0 for failure. 00285 bool Suspend(); 00286 // Resumes currently suspended thread 00287 // Returns 1 for success, 0 for failure. 00288 bool Resume(); 00289 00290 // Static function to return a pointer to the current thread 00291 //static Thread* GetThread(); 00292 00293 00294 // *** Thread status query functions 00295 00296 bool GetExitFlag() const; 00297 void SetExitFlag(bool exitFlag); 00298 00299 // Determines whether the thread was running and is now finished 00300 bool IsFinished() const; 00301 // Determines if the thread is currently suspended 00302 bool IsSuspended() const; 00303 // Returns current thread state 00304 ThreadState GetThreadState() const; 00305 00306 // Returns the number of available CPUs on the system 00307 static int GetCPUCount(); 00308 00309 // Returns the thread exit code. Exit code is initialized to 0, 00310 // and set to the return value if Run function after the thread is finished. 00311 inline int GetExitCode() const { return ExitCode; } 00312 // Returns an OS handle 00313 #if defined(OVR_OS_WIN32) 00314 void* GetOSHandle() const { return ThreadHandle; } 00315 #else 00316 pthread_t GetOSHandle() const { return ThreadHandle; } 00317 #endif 00318 00319 #if defined(OVR_OS_WIN32) 00320 ThreadId GetThreadId() const { return IdValue; } 00321 #else 00322 ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } 00323 #endif 00324 00325 static int GetOSPriority(ThreadPriority); 00326 // *** Sleep 00327 00328 // Sleep secs seconds 00329 static bool Sleep(unsigned secs); 00330 // Sleep msecs milliseconds 00331 static bool MSleep(unsigned msecs); 00332 00333 00334 // *** Debugging functionality 00335 #if defined(OVR_OS_WIN32) 00336 virtual void SetThreadName( const char* name ); 00337 #else 00338 virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); } 00339 #endif 00340 00341 private: 00342 #if defined(OVR_OS_WIN32) 00343 friend unsigned WINAPI Thread_Win32StartFn(void *pthread); 00344 00345 #else 00346 friend void *Thread_PthreadStartFn(void * phandle); 00347 00348 static int InitAttr; 00349 static pthread_attr_t Attr; 00350 #endif 00351 00352 protected: 00353 // Thread state flags 00354 AtomicInt<UInt32> ThreadFlags; 00355 AtomicInt<SInt32> SuspendCount; 00356 UPInt StackSize; 00357 00358 // Hardware processor which this thread is running on. 00359 int Processor; 00360 ThreadPriority Priority; 00361 00362 #if defined(OVR_OS_WIN32) 00363 void* ThreadHandle; 00364 volatile ThreadId IdValue; 00365 00366 // System-specific cleanup function called from destructor 00367 void CleanupSystemThread(); 00368 00369 #else 00370 pthread_t ThreadHandle; 00371 #endif 00372 00373 // Exit code of the thread, as returned by Run. 00374 int ExitCode; 00375 00376 // Internal run function. 00377 int PRun(); 00378 // Finishes the thread and releases internal reference to it. 00379 void FinishAndRelease(); 00380 00381 void Init(const CreateParams& params); 00382 00383 // Protected copy constructor 00384 Thread(const Thread &source) { OVR_UNUSED(source); } 00385 00386 }; 00387 00388 // Returns the unique Id of a thread it is called on, intended for 00389 // comparison purposes. 00390 ThreadId GetCurrentThreadId(); 00391 00392 00393 } // OVR 00394 00395 #endif // OVR_ENABLE_THREADS 00396 #endif // OVR_Threads_h