oculus1

view libovr/Src/Kernel/OVR_Threads.h @ 29:9a973ef0e2a3

fixed the performance issue under MacOSX by replacing glutSolidTeapot (which uses glEvalMesh) with my own teapot generator.
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Oct 2013 06:31:18 +0200
parents e2f9e4603129
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 2012 Oculus VR, Inc. All Rights reserved.
11 Use of this software is subject to the terms of the Oculus license
12 agreement provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 ************************************************************************************/
16 #ifndef OVR_Threads_h
17 #define OVR_Threads_h
19 #include "OVR_Types.h"
20 #include "OVR_Atomic.h"
21 #include "OVR_RefCount.h"
22 #include "OVR_Array.h"
24 // Defines the infinite wait delay timeout
25 #define OVR_WAIT_INFINITE 0xFFFFFFFF
27 // To be defined in the project configuration options
28 #ifdef OVR_ENABLE_THREADS
31 namespace OVR {
33 //-----------------------------------------------------------------------------------
34 // ****** Declared classes
36 // Declared with thread support only
37 class Mutex;
38 class WaitCondition;
39 class Event;
40 // Implementation forward declarations
41 class MutexImpl;
42 class WaitConditionImpl;
46 //-----------------------------------------------------------------------------------
47 // ***** Mutex
49 // Mutex class represents a system Mutex synchronization object that provides access
50 // serialization between different threads, allowing one thread mutually exclusive access
51 // to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition.
53 class Mutex
54 {
55 friend class WaitConditionImpl;
56 friend class MutexImpl;
58 MutexImpl *pImpl;
60 public:
61 // Constructor/destructor
62 Mutex(bool recursive = 1);
63 ~Mutex();
65 // Locking functions
66 void DoLock();
67 bool TryLock();
68 void Unlock();
70 // Returns 1 if the mutes is currently locked by another thread
71 // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired.
72 bool IsLockedByAnotherThread();
74 // Locker class; Used for automatic locking of a mutex withing scope
75 class Locker
76 {
77 public:
78 Mutex *pMutex;
79 Locker(Mutex *pmutex)
80 { pMutex = pmutex; pMutex->DoLock(); }
81 ~Locker()
82 { pMutex->Unlock(); }
83 };
84 };
87 //-----------------------------------------------------------------------------------
88 // ***** WaitCondition
90 /*
91 WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
92 Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
93 call Notify() or NotifyAll().
95 The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then
96 starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
97 resource, this ensures that any condition checked for while the mutex was locked does not change before
98 the wait on the condition is actually initiated.
99 */
101 class WaitCondition
102 {
103 friend class WaitConditionImpl;
104 // Internal implementation structure
105 WaitConditionImpl *pImpl;
107 public:
108 // Constructor/destructor
109 WaitCondition();
110 ~WaitCondition();
112 // Release mutex and wait for condition. The mutex is re-aquired after the wait.
113 // Delay is specified in milliseconds (1/1000 of a second).
114 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
116 // Notify a condition, releasing at one object waiting
117 void Notify();
118 // Notify a condition, releasing all objects waiting
119 void NotifyAll();
120 };
123 //-----------------------------------------------------------------------------------
124 // ***** Event
126 // Event is a wait-able synchronization object similar to Windows event.
127 // Event can be waited on until it's signaled by another thread calling
128 // either SetEvent or PulseEvent.
130 class Event
131 {
132 // Event state, its mutex and the wait condition
133 volatile bool State;
134 volatile bool Temporary;
135 mutable Mutex StateMutex;
136 WaitCondition StateWaitCondition;
138 void updateState(bool newState, bool newTemp, bool mustNotify);
140 public:
141 Event(bool setInitially = 0) : State(setInitially), Temporary(false) { }
142 ~Event() { }
144 // Wait on an event condition until it is set
145 // Delay is specified in milliseconds (1/1000 of a second).
146 bool Wait(unsigned delay = OVR_WAIT_INFINITE);
148 // Set an event, releasing objects waiting on it
149 void SetEvent()
150 { updateState(true, false, true); }
152 // Reset an event, un-signaling it
153 void ResetEvent()
154 { updateState(false, false, false); }
156 // Set and then reset an event once a waiter is released.
157 // If threads are already waiting, they will be notified and released
158 // If threads are not waiting, the event is set until the first thread comes in
159 void PulseEvent()
160 { updateState(true, true, true); }
161 };
164 //-----------------------------------------------------------------------------------
165 // ***** Thread class
167 // ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and
168 // Thread::GetThreadId.
169 typedef void* ThreadId;
172 // *** Thread flags
174 // Indicates that the thread is has been started, i.e. Start method has been called, and threads
175 // OnExit() method has not yet been called/returned.
176 #define OVR_THREAD_STARTED 0x01
177 // This flag is set once the thread has ran, and finished.
178 #define OVR_THREAD_FINISHED 0x02
179 // This flag is set temporarily if this thread was started suspended. It is used internally.
180 #define OVR_THREAD_START_SUSPENDED 0x08
181 // This flag is used to ask a thread to exit. Message driven threads will usually check this flag
182 // and finish once it is set.
183 #define OVR_THREAD_EXIT 0x10
186 class Thread : public RefCountBase<Thread>
187 { // NOTE: Waitable must be the first base since it implements RefCountImpl.
189 public:
191 // *** Callback functions, can be used instead of overriding Run
193 // Run function prototypes.
194 // Thread function and user handle passed to it, executed by the default
195 // Thread::Run implementation if not null.
196 typedef int (*ThreadFn)(Thread *pthread, void* h);
198 // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
199 ThreadFn ThreadFunction;
200 // User handle passes to a thread
201 void* UserHandle;
203 // Thread state to start a thread with
204 enum ThreadState
205 {
206 NotRunning = 0,
207 Running = 1,
208 Suspended = 2
209 };
211 // Thread priority
212 enum ThreadPriority
213 {
214 CriticalPriority,
215 HighestPriority,
216 AboveNormalPriority,
217 NormalPriority,
218 BelowNormalPriority,
219 LowestPriority,
220 IdlePriority,
221 };
223 // Thread constructor parameters
224 struct CreateParams
225 {
226 CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024,
227 int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
228 : threadFunction(func), userHandle(hand), stackSize(ssize),
229 processor(proc), initialState(state), priority(prior) {}
230 ThreadFn threadFunction; // Thread function
231 void* userHandle; // User handle passes to a thread
232 UPInt stackSize; // Thread stack size
233 int processor; // Thread hardware processor
234 ThreadState initialState; //
235 ThreadPriority priority; // Thread priority
236 };
238 // *** Constructors
240 // A default constructor always creates a thread in NotRunning state, because
241 // the derived class has not yet been initialized. The derived class can call Start explicitly.
242 // "processor" parameter specifies which hardware processor this thread will be run on.
243 // -1 means OS decides this. Implemented only on Win32
244 Thread(UPInt stackSize = 128 * 1024, int processor = -1);
245 // Constructors that initialize the thread with a pointer to function.
246 // An option to start a thread is available, but it should not be used if classes are derived from Thread.
247 // "processor" parameter specifies which hardware processor this thread will be run on.
248 // -1 means OS decides this. Implemented only on Win32
249 Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024,
250 int processor = -1, ThreadState initialState = NotRunning);
251 // Constructors that initialize the thread with a create parameters structure.
252 explicit Thread(const CreateParams& params);
254 // Destructor.
255 virtual ~Thread();
257 // Waits for all Threads to finish; should be called only from the root
258 // application thread. Once this function returns, we know that all other
259 // thread's references to Thread object have been released.
260 static void OVR_CDECL FinishAllThreads();
263 // *** Overridable Run function for thread processing
265 // - returning from this method will end the execution of the thread
266 // - return value is usually 0 for success
267 virtual int Run();
268 // Called after return/exit function
269 virtual void OnExit();
272 // *** Thread management
274 // Starts the thread if its not already running
275 // - internally sets up the threading and calls Run()
276 // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
277 // - returns the exit code
278 virtual bool Start(ThreadState initialState = Running);
280 // Quits with an exit code
281 virtual void Exit(int exitCode=0);
283 // Suspend the thread until resumed
284 // Returns 1 for success, 0 for failure.
285 bool Suspend();
286 // Resumes currently suspended thread
287 // Returns 1 for success, 0 for failure.
288 bool Resume();
290 // Static function to return a pointer to the current thread
291 //static Thread* GetThread();
294 // *** Thread status query functions
296 bool GetExitFlag() const;
297 void SetExitFlag(bool exitFlag);
299 // Determines whether the thread was running and is now finished
300 bool IsFinished() const;
301 // Determines if the thread is currently suspended
302 bool IsSuspended() const;
303 // Returns current thread state
304 ThreadState GetThreadState() const;
306 // Returns the number of available CPUs on the system
307 static int GetCPUCount();
309 // Returns the thread exit code. Exit code is initialized to 0,
310 // and set to the return value if Run function after the thread is finished.
311 inline int GetExitCode() const { return ExitCode; }
312 // Returns an OS handle
313 #if defined(OVR_OS_WIN32)
314 void* GetOSHandle() const { return ThreadHandle; }
315 #else
316 pthread_t GetOSHandle() const { return ThreadHandle; }
317 #endif
319 #if defined(OVR_OS_WIN32)
320 ThreadId GetThreadId() const { return IdValue; }
321 #else
322 ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); }
323 #endif
325 static int GetOSPriority(ThreadPriority);
326 // *** Sleep
328 // Sleep secs seconds
329 static bool Sleep(unsigned secs);
330 // Sleep msecs milliseconds
331 static bool MSleep(unsigned msecs);
334 // *** Debugging functionality
335 #if defined(OVR_OS_WIN32)
336 virtual void SetThreadName( const char* name );
337 #else
338 virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); }
339 #endif
341 private:
342 #if defined(OVR_OS_WIN32)
343 friend unsigned WINAPI Thread_Win32StartFn(void *pthread);
345 #else
346 friend void *Thread_PthreadStartFn(void * phandle);
348 static int InitAttr;
349 static pthread_attr_t Attr;
350 #endif
352 protected:
353 // Thread state flags
354 AtomicInt<UInt32> ThreadFlags;
355 AtomicInt<SInt32> SuspendCount;
356 UPInt StackSize;
358 // Hardware processor which this thread is running on.
359 int Processor;
360 ThreadPriority Priority;
362 #if defined(OVR_OS_WIN32)
363 void* ThreadHandle;
364 volatile ThreadId IdValue;
366 // System-specific cleanup function called from destructor
367 void CleanupSystemThread();
369 #else
370 pthread_t ThreadHandle;
371 #endif
373 // Exit code of the thread, as returned by Run.
374 int ExitCode;
376 // Internal run function.
377 int PRun();
378 // Finishes the thread and releases internal reference to it.
379 void FinishAndRelease();
381 void Init(const CreateParams& params);
383 // Protected copy constructor
384 Thread(const Thread &source) { OVR_UNUSED(source); }
386 };
388 // Returns the unique Id of a thread it is called on, intended for
389 // comparison purposes.
390 ThreadId GetCurrentThreadId();
393 } // OVR
395 #endif // OVR_ENABLE_THREADS
396 #endif // OVR_Threads_h