ovr_sdk
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Kernel/OVR_Threads.h Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,434 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +PublicHeader: None 1.7 +Filename : OVR_Threads.h 1.8 +Content : Contains thread-related (safe) functionality 1.9 +Created : September 19, 2012 1.10 +Notes : 1.11 + 1.12 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.13 + 1.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.16 +which is provided at the time of installation or download, or which 1.17 +otherwise accompanies this software in either electronic or hard copy form. 1.18 + 1.19 +You may obtain a copy of the License at 1.20 + 1.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.22 + 1.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.24 +distributed under the License is distributed on an "AS IS" BASIS, 1.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.26 +See the License for the specific language governing permissions and 1.27 +limitations under the License. 1.28 + 1.29 +************************************************************************************/ 1.30 +#ifndef OVR_Threads_h 1.31 +#define OVR_Threads_h 1.32 + 1.33 +#include "OVR_Types.h" 1.34 +#include "OVR_Atomic.h" 1.35 +#include "OVR_RefCount.h" 1.36 +#include "OVR_Array.h" 1.37 + 1.38 +// Defines the infinite wait delay timeout 1.39 +#define OVR_WAIT_INFINITE 0xFFFFFFFF 1.40 + 1.41 +// To be defined in the project configuration options 1.42 +#ifdef OVR_ENABLE_THREADS 1.43 + 1.44 + 1.45 +namespace OVR { 1.46 + 1.47 +//----------------------------------------------------------------------------------- 1.48 +// ****** Declared classes 1.49 + 1.50 +// Declared with thread support only 1.51 +class Mutex; 1.52 +class WaitCondition; 1.53 +class Event; 1.54 +// Implementation forward declarations 1.55 +class MutexImpl; 1.56 +class WaitConditionImpl; 1.57 + 1.58 + 1.59 + 1.60 +//----------------------------------------------------------------------------------- 1.61 +// ***** Mutex 1.62 + 1.63 +// Mutex class represents a system Mutex synchronization object that provides access 1.64 +// serialization between different threads, allowing one thread mutually exclusive access 1.65 +// to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition. 1.66 + 1.67 +class Mutex 1.68 +{ 1.69 + friend class WaitConditionImpl; 1.70 + friend class MutexImpl; 1.71 + 1.72 + MutexImpl *pImpl; 1.73 + 1.74 +public: 1.75 + // Constructor/destructor 1.76 + Mutex(bool recursive = 1); 1.77 + ~Mutex(); 1.78 + 1.79 + // Locking functions 1.80 + void DoLock(); 1.81 + bool TryLock(); 1.82 + void Unlock(); 1.83 + 1.84 + // Returns 1 if the mutes is currently locked by another thread 1.85 + // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 1.86 + bool IsLockedByAnotherThread(); 1.87 + 1.88 + // Locker class; Used for automatic locking of a mutex withing scope 1.89 + class Locker 1.90 + { 1.91 + public: 1.92 + Mutex *pMutex; 1.93 + Locker(Mutex *pmutex) 1.94 + { pMutex = pmutex; pMutex->DoLock(); } 1.95 + ~Locker() 1.96 + { pMutex->Unlock(); } 1.97 + }; 1.98 +}; 1.99 + 1.100 + 1.101 +//----------------------------------------------------------------------------------- 1.102 +// ***** WaitCondition 1.103 + 1.104 +/* 1.105 + WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor. 1.106 + Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that 1.107 + call Notify() or NotifyAll(). 1.108 + 1.109 + The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 1.110 + starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same 1.111 + resource, this ensures that any condition checked for while the mutex was locked does not change before 1.112 + the wait on the condition is actually initiated. 1.113 +*/ 1.114 + 1.115 +class WaitCondition 1.116 +{ 1.117 + friend class WaitConditionImpl; 1.118 + // Internal implementation structure 1.119 + WaitConditionImpl *pImpl; 1.120 + 1.121 +public: 1.122 + // Constructor/destructor 1.123 + WaitCondition(); 1.124 + ~WaitCondition(); 1.125 + 1.126 + // Release mutex and wait for condition. The mutex is re-aquired after the wait. 1.127 + // Delay is specified in milliseconds (1/1000 of a second). 1.128 + bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 1.129 + 1.130 + // Notify a condition, releasing at one object waiting 1.131 + void Notify(); 1.132 + // Notify a condition, releasing all objects waiting 1.133 + void NotifyAll(); 1.134 +}; 1.135 + 1.136 + 1.137 +//----------------------------------------------------------------------------------- 1.138 +// ***** Event 1.139 + 1.140 +// Event is a wait-able synchronization object similar to Windows event. 1.141 +// Event can be waited on until it's signaled by another thread calling 1.142 +// either SetEvent or PulseEvent. 1.143 + 1.144 +class Event 1.145 +{ 1.146 + // Event state, its mutex and the wait condition 1.147 + volatile bool State; 1.148 + volatile bool Temporary; 1.149 + mutable Mutex StateMutex; 1.150 + WaitCondition StateWaitCondition; 1.151 + 1.152 + void updateState(bool newState, bool newTemp, bool mustNotify); 1.153 + 1.154 +public: 1.155 + Event(bool setInitially = 0) : State(setInitially), Temporary(false) { } 1.156 + ~Event() { } 1.157 + 1.158 + // Wait on an event condition until it is set 1.159 + // Delay is specified in milliseconds (1/1000 of a second). 1.160 + bool Wait(unsigned delay = OVR_WAIT_INFINITE); 1.161 + 1.162 + // Set an event, releasing objects waiting on it 1.163 + void SetEvent() 1.164 + { updateState(true, false, true); } 1.165 + 1.166 + // Reset an event, un-signaling it 1.167 + void ResetEvent() 1.168 + { updateState(false, false, false); } 1.169 + 1.170 + // Set and then reset an event once a waiter is released. 1.171 + // If threads are already waiting, they will be notified and released 1.172 + // If threads are not waiting, the event is set until the first thread comes in 1.173 + void PulseEvent() 1.174 + { updateState(true, true, true); } 1.175 +}; 1.176 + 1.177 + 1.178 +//----------------------------------------------------------------------------------- 1.179 +// ***** Thread class 1.180 + 1.181 +// ThreadHandle is a handle to a thread, which on some platforms (e.g. Windows) is 1.182 +// different from ThreadId. On Unix platforms, a ThreadHandle is the same as a 1.183 +// ThreadId and is pthread_t. 1.184 +typedef void* ThreadHandle; 1.185 + 1.186 +// ThreadId uniquely identifies a thread; returned by Windows GetCurrentThreadId(), 1.187 +// Unix pthread_self() and Thread::GetThreadId. 1.188 +typedef void* ThreadId; 1.189 + 1.190 + 1.191 +// *** Thread flags 1.192 + 1.193 +// Indicates that the thread is has been started, i.e. Start method has been called, and threads 1.194 +// OnExit() method has not yet been called/returned. 1.195 +#define OVR_THREAD_STARTED 0x01 1.196 +// This flag is set once the thread has ran, and finished. 1.197 +#define OVR_THREAD_FINISHED 0x02 1.198 +// This flag is set temporarily if this thread was started suspended. It is used internally. 1.199 +#define OVR_THREAD_START_SUSPENDED 0x08 1.200 +// This flag is used to ask a thread to exit. Message driven threads will usually check this flag 1.201 +// and finish once it is set. 1.202 +#define OVR_THREAD_EXIT 0x10 1.203 + 1.204 + 1.205 +class Thread : public RefCountBase<Thread> 1.206 +{ // NOTE: Waitable must be the first base since it implements RefCountImpl. 1.207 +public: 1.208 + // *** Callback functions, can be used instead of overriding Run 1.209 + 1.210 + // Run function prototypes. 1.211 + // Thread function and user handle passed to it, executed by the default 1.212 + // Thread::Run implementation if not null. 1.213 + typedef int (*ThreadFn)(Thread *pthread, void* h); 1.214 + 1.215 + // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried 1.216 + ThreadFn ThreadFunction; 1.217 + // User handle passes to a thread 1.218 + void* UserHandle; 1.219 + 1.220 + // Thread state to start a thread with 1.221 + enum ThreadState 1.222 + { 1.223 + NotRunning = 0, 1.224 + Running = 1, 1.225 + Suspended = 2 1.226 + }; 1.227 + 1.228 + // Thread priority 1.229 + enum ThreadPriority 1.230 + { 1.231 + CriticalPriority, 1.232 + HighestPriority, 1.233 + AboveNormalPriority, 1.234 + NormalPriority, 1.235 + BelowNormalPriority, 1.236 + LowestPriority, 1.237 + IdlePriority, 1.238 + }; 1.239 + 1.240 + // Thread constructor parameters 1.241 + struct CreateParams 1.242 + { 1.243 + CreateParams(ThreadFn func = 0, void* hand = 0, size_t ssize = 128 * 1024, 1.244 + int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority) 1.245 + : threadFunction(func), userHandle(hand), stackSize(ssize), 1.246 + processor(proc), initialState(state), priority(prior) {} 1.247 + ThreadFn threadFunction; // Thread function 1.248 + void* userHandle; // User handle passes to a thread 1.249 + size_t stackSize; // Thread stack size 1.250 + int processor; // Thread hardware processor 1.251 + ThreadState initialState; // 1.252 + ThreadPriority priority; // Thread priority 1.253 + }; 1.254 + 1.255 + 1.256 + // *** Constructors 1.257 + 1.258 + // A default constructor always creates a thread in NotRunning state, because 1.259 + // the derived class has not yet been initialized. The derived class can call Start explicitly. 1.260 + // "processor" parameter specifies which hardware processor this thread will be run on. 1.261 + // -1 means OS decides this. Implemented only on Win32 1.262 + Thread(size_t stackSize = 128 * 1024, int processor = -1); 1.263 + // Constructors that initialize the thread with a pointer to function. 1.264 + // An option to start a thread is available, but it should not be used if classes are derived from Thread. 1.265 + // "processor" parameter specifies which hardware processor this thread will be run on. 1.266 + // -1 means OS decides this. Implemented only on Win32 1.267 + Thread(ThreadFn threadFunction, void* userHandle = 0, size_t stackSize = 128 * 1024, 1.268 + int processor = -1, ThreadState initialState = NotRunning); 1.269 + // Constructors that initialize the thread with a create parameters structure. 1.270 + explicit Thread(const CreateParams& params); 1.271 + 1.272 + // Destructor. 1.273 + virtual ~Thread(); 1.274 + 1.275 + // Waits for all Threads to finish; should be called only from the root 1.276 + // application thread. Once this function returns, we know that all other 1.277 + // thread's references to Thread object have been released. 1.278 + static void OVR_CDECL FinishAllThreads(); 1.279 + 1.280 + 1.281 + // *** Overridable Run function for thread processing 1.282 + 1.283 + // - returning from this method will end the execution of the thread 1.284 + // - return value is usually 0 for success 1.285 + virtual int Run(); 1.286 + // Called after return/exit function 1.287 + virtual void OnExit(); 1.288 + 1.289 + 1.290 + // *** Thread management 1.291 + 1.292 + // Starts the thread if its not already running 1.293 + // - internally sets up the threading and calls Run() 1.294 + // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing 1.295 + // - returns the exit code 1.296 + virtual bool Start(ThreadState initialState = Running); 1.297 + 1.298 + // Quits with an exit code 1.299 + virtual void Exit(int exitCode=0); 1.300 + 1.301 + // Suspend the thread until resumed 1.302 + // Returns 1 for success, 0 for failure. 1.303 + bool Suspend(); 1.304 + // Resumes currently suspended thread 1.305 + // Returns 1 for success, 0 for failure. 1.306 + bool Resume(); 1.307 + 1.308 + // Static function to return a pointer to the current thread 1.309 + //static Thread* GetThread(); 1.310 + 1.311 + 1.312 + // *** Thread status query functions 1.313 + 1.314 + bool GetExitFlag() const; 1.315 + void SetExitFlag(bool exitFlag); 1.316 + 1.317 + // Determines whether the thread was running and is now finished 1.318 + bool IsFinished() const; 1.319 + // Determines if the thread is currently suspended 1.320 + bool IsSuspended() const; 1.321 + // Returns current thread state 1.322 + ThreadState GetThreadState() const; 1.323 + 1.324 + // Wait for thread to finish for a maxmimum number of milliseconds 1.325 + // For maxWaitMs = 0 it simply polls and then returns if the thread is not finished 1.326 + // For maxWaitMs < 0 it will wait forever 1.327 + bool Join(int maxWaitMs = -1) const; 1.328 + 1.329 + // Returns the number of available CPUs on the system 1.330 + static int GetCPUCount(); 1.331 + 1.332 + // Returns the thread exit code. Exit code is initialized to 0, 1.333 + // and set to the return value if Run function after the thread is finished. 1.334 + inline int GetExitCode() const { return ExitCode; } 1.335 + // Returns an OS handle 1.336 +#if defined(OVR_OS_MS) 1.337 + void* GetOSHandle() const { return ThreadHandle; } 1.338 +#else 1.339 + pthread_t GetOSHandle() const { return ThreadHandle; } 1.340 +#endif 1.341 + 1.342 +#if defined(OVR_OS_MS) 1.343 + ThreadId GetThreadId() const { return IdValue; } 1.344 +#else 1.345 + ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } 1.346 +#endif 1.347 + 1.348 + // Returns the platform-specific equivalent const that corresponds to the given ThreadPriority. 1.349 + static int GetOSPriority(ThreadPriority); 1.350 + static ThreadPriority GetOVRPriority(int osPriority); // May return a value outside the ThreadPriority enum range in unusual cases. 1.351 + 1.352 + // Gets this instance's priority. 1.353 + ThreadPriority GetPriority(); 1.354 + 1.355 + // Gets the current thread's priority. 1.356 + static ThreadPriority GetCurrentPriority(); 1.357 + 1.358 + // Sets this instance's thread's priority. 1.359 + // Some platforms (e.g. Unix) don't let you set thread priorities unless you have root privileges/ 1.360 + bool SetPriority(ThreadPriority); 1.361 + 1.362 + // Sets the current thread's priority. 1.363 + static bool SetCurrentPriority(ThreadPriority); 1.364 + 1.365 + // *** Sleep 1.366 + 1.367 + // Sleep secs seconds 1.368 + static bool Sleep(unsigned secs); 1.369 + // Sleep msecs milliseconds 1.370 + static bool MSleep(unsigned msecs); 1.371 + 1.372 + 1.373 + // *** Debugging functionality 1.374 + virtual void SetThreadName(const char* name); 1.375 + static void SetThreadName(const char* name, ThreadId threadId); 1.376 + static void SetCurrentThreadName(const char* name); 1.377 + 1.378 + static void GetThreadName(char* name, size_t nameCapacity, ThreadId threadId); 1.379 + static void GetCurrentThreadName(char* name, size_t nameCapacity); 1.380 + 1.381 +private: 1.382 +#if defined(OVR_OS_WIN32) 1.383 + friend unsigned WINAPI Thread_Win32StartFn(void *phandle); 1.384 +#elif defined(OVR_OS_MS) // Any other Microsoft OS... 1.385 + friend DWORD WINAPI Thread_Win32StartFn(void *phandle); 1.386 +#else 1.387 + friend void *Thread_PthreadStartFn(void * phandle); 1.388 + 1.389 + static int InitAttr; 1.390 + static pthread_attr_t Attr; 1.391 +#endif 1.392 + 1.393 +protected: 1.394 + // Thread state flags 1.395 + AtomicInt<uint32_t> ThreadFlags; 1.396 + AtomicInt<int32_t> SuspendCount; 1.397 + size_t StackSize; 1.398 + 1.399 + // Hardware processor which this thread is running on. 1.400 + int Processor; 1.401 + ThreadPriority Priority; 1.402 + 1.403 +#if defined(OVR_OS_MS) 1.404 + void* ThreadHandle; 1.405 + volatile ThreadId IdValue; 1.406 + 1.407 + // System-specific cleanup function called from destructor 1.408 + void CleanupSystemThread(); 1.409 + 1.410 +#else 1.411 + pthread_t ThreadHandle; 1.412 +#endif 1.413 + 1.414 + // Exit code of the thread, as returned by Run. 1.415 + int ExitCode; 1.416 + 1.417 + // Internal run function. 1.418 + int PRun(); 1.419 + // Finishes the thread and releases internal reference to it. 1.420 + void FinishAndRelease(); 1.421 + 1.422 + void Init(const CreateParams& params); 1.423 + 1.424 + // Protected copy constructor 1.425 + Thread(const Thread &source) : RefCountBase<Thread>() { OVR_UNUSED(source); } 1.426 + 1.427 +}; 1.428 + 1.429 +// Returns the unique Id of a thread it is called on, intended for 1.430 +// comparison purposes. 1.431 +ThreadId GetCurrentThreadId(); 1.432 + 1.433 + 1.434 +} // OVR 1.435 + 1.436 +#endif // OVR_ENABLE_THREADS 1.437 +#endif // OVR_Threads_h