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