OVR_Threads.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /************************************************************************************
  2. PublicHeader: None
  3. Filename : OVR_Threads.h
  4. Content : Contains thread-related (safe) functionality
  5. Created : September 19, 2012
  6. Notes :
  7. Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
  8. Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  9. you may not use the Oculus VR Rift SDK except in compliance with the License,
  10. which is provided at the time of installation or download, or which
  11. otherwise accompanies this software in either electronic or hard copy form.
  12. You may obtain a copy of the License at
  13. http://www.oculusvr.com/licenses/LICENSE-3.2
  14. Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  15. distributed under the License is distributed on an "AS IS" BASIS,
  16. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. See the License for the specific language governing permissions and
  18. limitations under the License.
  19. ************************************************************************************/
  20. #ifndef OVR_Threads_h
  21. #define OVR_Threads_h
  22. #include "OVR_Types.h"
  23. #include "OVR_Atomic.h"
  24. #include "OVR_RefCount.h"
  25. #include "OVR_Array.h"
  26. // Defines the infinite wait delay timeout
  27. #define OVR_WAIT_INFINITE 0xFFFFFFFF
  28. // To be defined in the project configuration options
  29. #ifdef OVR_ENABLE_THREADS
  30. namespace OVR {
  31. //-----------------------------------------------------------------------------------
  32. // ****** Declared classes
  33. // Declared with thread support only
  34. class Mutex;
  35. class WaitCondition;
  36. class Event;
  37. // Implementation forward declarations
  38. class MutexImpl;
  39. class WaitConditionImpl;
  40. //-----------------------------------------------------------------------------------
  41. // ***** Mutex
  42. // Mutex class represents a system Mutex synchronization object that provides access
  43. // serialization between different threads, allowing one thread mutually exclusive access
  44. // to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition.
  45. class Mutex
  46. {
  47. friend class WaitConditionImpl;
  48. friend class MutexImpl;
  49. MutexImpl *pImpl;
  50. public:
  51. // Constructor/destructor
  52. Mutex(bool recursive = 1);
  53. ~Mutex();
  54. // Locking functions
  55. void DoLock();
  56. bool TryLock();
  57. void Unlock();
  58. // Returns 1 if the mutes is currently locked by another thread
  59. // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired.
  60. bool IsLockedByAnotherThread();
  61. // Locker class; Used for automatic locking of a mutex withing scope
  62. class Locker
  63. {
  64. public:
  65. Mutex *pMutex;
  66. Locker(Mutex *pmutex)
  67. { pMutex = pmutex; pMutex->DoLock(); }
  68. ~Locker()
  69. { pMutex->Unlock(); }
  70. };
  71. };
  72. //-----------------------------------------------------------------------------------
  73. // ***** WaitCondition
  74. /*
  75. WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
  76. Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
  77. call Notify() or NotifyAll().
  78. The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then
  79. starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
  80. resource, this ensures that any condition checked for while the mutex was locked does not change before
  81. the wait on the condition is actually initiated.
  82. */
  83. class WaitCondition
  84. {
  85. friend class WaitConditionImpl;
  86. // Internal implementation structure
  87. WaitConditionImpl *pImpl;
  88. public:
  89. // Constructor/destructor
  90. WaitCondition();
  91. ~WaitCondition();
  92. // Release mutex and wait for condition. The mutex is re-aquired after the wait.
  93. // Delay is specified in milliseconds (1/1000 of a second).
  94. bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  95. // Notify a condition, releasing at one object waiting
  96. void Notify();
  97. // Notify a condition, releasing all objects waiting
  98. void NotifyAll();
  99. };
  100. //-----------------------------------------------------------------------------------
  101. // ***** Event
  102. // Event is a wait-able synchronization object similar to Windows event.
  103. // Event can be waited on until it's signaled by another thread calling
  104. // either SetEvent or PulseEvent.
  105. class Event
  106. {
  107. // Event state, its mutex and the wait condition
  108. volatile bool State;
  109. volatile bool Temporary;
  110. mutable Mutex StateMutex;
  111. WaitCondition StateWaitCondition;
  112. void updateState(bool newState, bool newTemp, bool mustNotify);
  113. public:
  114. Event(bool setInitially = 0) : State(setInitially), Temporary(false) { }
  115. ~Event() { }
  116. // Wait on an event condition until it is set
  117. // Delay is specified in milliseconds (1/1000 of a second).
  118. bool Wait(unsigned delay = OVR_WAIT_INFINITE);
  119. // Set an event, releasing objects waiting on it
  120. void SetEvent()
  121. { updateState(true, false, true); }
  122. // Reset an event, un-signaling it
  123. void ResetEvent()
  124. { updateState(false, false, false); }
  125. // Set and then reset an event once a waiter is released.
  126. // If threads are already waiting, they will be notified and released
  127. // If threads are not waiting, the event is set until the first thread comes in
  128. void PulseEvent()
  129. { updateState(true, true, true); }
  130. };
  131. //-----------------------------------------------------------------------------------
  132. // ***** Thread class
  133. // ThreadHandle is a handle to a thread, which on some platforms (e.g. Windows) is
  134. // different from ThreadId. On Unix platforms, a ThreadHandle is the same as a
  135. // ThreadId and is pthread_t.
  136. typedef void* ThreadHandle;
  137. // ThreadId uniquely identifies a thread; returned by Windows GetCurrentThreadId(),
  138. // Unix pthread_self() and Thread::GetThreadId.
  139. typedef void* ThreadId;
  140. // *** Thread flags
  141. // Indicates that the thread is has been started, i.e. Start method has been called, and threads
  142. // OnExit() method has not yet been called/returned.
  143. #define OVR_THREAD_STARTED 0x01
  144. // This flag is set once the thread has ran, and finished.
  145. #define OVR_THREAD_FINISHED 0x02
  146. // This flag is set temporarily if this thread was started suspended. It is used internally.
  147. #define OVR_THREAD_START_SUSPENDED 0x08
  148. // This flag is used to ask a thread to exit. Message driven threads will usually check this flag
  149. // and finish once it is set.
  150. #define OVR_THREAD_EXIT 0x10
  151. class Thread : public RefCountBase<Thread>
  152. { // NOTE: Waitable must be the first base since it implements RefCountImpl.
  153. public:
  154. // *** Callback functions, can be used instead of overriding Run
  155. // Run function prototypes.
  156. // Thread function and user handle passed to it, executed by the default
  157. // Thread::Run implementation if not null.
  158. typedef int (*ThreadFn)(Thread *pthread, void* h);
  159. // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
  160. ThreadFn ThreadFunction;
  161. // User handle passes to a thread
  162. void* UserHandle;
  163. // Thread state to start a thread with
  164. enum ThreadState
  165. {
  166. NotRunning = 0,
  167. Running = 1,
  168. Suspended = 2
  169. };
  170. // Thread priority
  171. enum ThreadPriority
  172. {
  173. CriticalPriority,
  174. HighestPriority,
  175. AboveNormalPriority,
  176. NormalPriority,
  177. BelowNormalPriority,
  178. LowestPriority,
  179. IdlePriority,
  180. };
  181. // Thread constructor parameters
  182. struct CreateParams
  183. {
  184. CreateParams(ThreadFn func = 0, void* hand = 0, size_t ssize = 128 * 1024,
  185. int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
  186. : threadFunction(func), userHandle(hand), stackSize(ssize),
  187. processor(proc), initialState(state), priority(prior) {}
  188. ThreadFn threadFunction; // Thread function
  189. void* userHandle; // User handle passes to a thread
  190. size_t stackSize; // Thread stack size
  191. int processor; // Thread hardware processor
  192. ThreadState initialState; //
  193. ThreadPriority priority; // Thread priority
  194. };
  195. // *** Constructors
  196. // A default constructor always creates a thread in NotRunning state, because
  197. // the derived class has not yet been initialized. The derived class can call Start explicitly.
  198. // "processor" parameter specifies which hardware processor this thread will be run on.
  199. // -1 means OS decides this. Implemented only on Win32
  200. Thread(size_t stackSize = 128 * 1024, int processor = -1);
  201. // Constructors that initialize the thread with a pointer to function.
  202. // An option to start a thread is available, but it should not be used if classes are derived from Thread.
  203. // "processor" parameter specifies which hardware processor this thread will be run on.
  204. // -1 means OS decides this. Implemented only on Win32
  205. Thread(ThreadFn threadFunction, void* userHandle = 0, size_t stackSize = 128 * 1024,
  206. int processor = -1, ThreadState initialState = NotRunning);
  207. // Constructors that initialize the thread with a create parameters structure.
  208. explicit Thread(const CreateParams& params);
  209. // Destructor.
  210. virtual ~Thread();
  211. // Waits for all Threads to finish; should be called only from the root
  212. // application thread. Once this function returns, we know that all other
  213. // thread's references to Thread object have been released.
  214. static void OVR_CDECL FinishAllThreads();
  215. // *** Overridable Run function for thread processing
  216. // - returning from this method will end the execution of the thread
  217. // - return value is usually 0 for success
  218. virtual int Run();
  219. // Called after return/exit function
  220. virtual void OnExit();
  221. // *** Thread management
  222. // Starts the thread if its not already running
  223. // - internally sets up the threading and calls Run()
  224. // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
  225. // - returns the exit code
  226. virtual bool Start(ThreadState initialState = Running);
  227. // Quits with an exit code
  228. virtual void Exit(int exitCode=0);
  229. // Suspend the thread until resumed
  230. // Returns 1 for success, 0 for failure.
  231. bool Suspend();
  232. // Resumes currently suspended thread
  233. // Returns 1 for success, 0 for failure.
  234. bool Resume();
  235. // Static function to return a pointer to the current thread
  236. //static Thread* GetThread();
  237. // *** Thread status query functions
  238. bool GetExitFlag() const;
  239. void SetExitFlag(bool exitFlag);
  240. // Determines whether the thread was running and is now finished
  241. bool IsFinished() const;
  242. // Determines if the thread is currently suspended
  243. bool IsSuspended() const;
  244. // Returns current thread state
  245. ThreadState GetThreadState() const;
  246. // Wait for thread to finish for a maxmimum number of milliseconds
  247. // For maxWaitMs = 0 it simply polls and then returns if the thread is not finished
  248. // For maxWaitMs < 0 it will wait forever
  249. bool Join(int maxWaitMs = -1) const;
  250. // Returns the number of available CPUs on the system
  251. static int GetCPUCount();
  252. // Returns the thread exit code. Exit code is initialized to 0,
  253. // and set to the return value if Run function after the thread is finished.
  254. inline int GetExitCode() const { return ExitCode; }
  255. // Returns an OS handle
  256. #if defined(OVR_OS_MS)
  257. void* GetOSHandle() const { return ThreadHandle; }
  258. #else
  259. pthread_t GetOSHandle() const { return ThreadHandle; }
  260. #endif
  261. #if defined(OVR_OS_MS)
  262. ThreadId GetThreadId() const { return IdValue; }
  263. #else
  264. ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); }
  265. #endif
  266. // Returns the platform-specific equivalent const that corresponds to the given ThreadPriority.
  267. static int GetOSPriority(ThreadPriority);
  268. static ThreadPriority GetOVRPriority(int osPriority); // May return a value outside the ThreadPriority enum range in unusual cases.
  269. // Gets this instance's priority.
  270. ThreadPriority GetPriority();
  271. // Gets the current thread's priority.
  272. static ThreadPriority GetCurrentPriority();
  273. // Sets this instance's thread's priority.
  274. // Some platforms (e.g. Unix) don't let you set thread priorities unless you have root privileges/
  275. bool SetPriority(ThreadPriority);
  276. // Sets the current thread's priority.
  277. static bool SetCurrentPriority(ThreadPriority);
  278. // *** Sleep
  279. // Sleep secs seconds
  280. static bool Sleep(unsigned secs);
  281. // Sleep msecs milliseconds
  282. static bool MSleep(unsigned msecs);
  283. // Notifies the scheduler that this thread is willing to release its processor
  284. // to other threads of equal or higher priority.
  285. static void YieldCurrentThread();
  286. // *** Debugging functionality
  287. virtual void SetThreadName(const char* name);
  288. static void SetThreadName(const char* name, ThreadId threadId);
  289. static void SetCurrentThreadName(const char* name);
  290. static void GetThreadName(char* name, size_t nameCapacity, ThreadId threadId);
  291. static void GetCurrentThreadName(char* name, size_t nameCapacity);
  292. private:
  293. #if defined(OVR_OS_WIN32)
  294. friend unsigned WINAPI Thread_Win32StartFn(void *phandle);
  295. #elif defined(OVR_OS_MS) // Any other Microsoft OS...
  296. friend DWORD WINAPI Thread_Win32StartFn(void *phandle);
  297. #else
  298. friend void *Thread_PthreadStartFn(void * phandle);
  299. static int InitAttr;
  300. static pthread_attr_t Attr;
  301. #endif
  302. protected:
  303. // Thread state flags
  304. AtomicInt<uint32_t> ThreadFlags;
  305. AtomicInt<int32_t> SuspendCount;
  306. size_t StackSize;
  307. // Hardware processor which this thread is running on.
  308. int Processor;
  309. ThreadPriority Priority;
  310. #if defined(OVR_OS_MS)
  311. void* ThreadHandle;
  312. volatile ThreadId IdValue;
  313. // System-specific cleanup function called from destructor
  314. void CleanupSystemThread();
  315. #else
  316. pthread_t ThreadHandle;
  317. #endif
  318. // Exit code of the thread, as returned by Run.
  319. int ExitCode;
  320. // Internal run function.
  321. int PRun();
  322. // Finishes the thread and releases internal reference to it.
  323. void FinishAndRelease();
  324. void Init(const CreateParams& params);
  325. // Protected copy constructor
  326. Thread(const Thread &source) : RefCountBase<Thread>() { OVR_UNUSED(source); }
  327. };
  328. // Returns the unique Id of a thread it is called on, intended for
  329. // comparison purposes.
  330. ThreadId GetCurrentThreadId();
  331. // Returns the unique Id of the current running process.
  332. #if !defined(OVR_OS_MS)
  333. #define GetCurrentProcessId getpid
  334. #endif
  335. } // OVR
  336. #endif // OVR_ENABLE_THREADS
  337. #endif // OVR_Threads_h