aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Kernel/OVR_Threads.h
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/Kernel/OVR_Threads.h')
-rw-r--r--LibOVR/Src/Kernel/OVR_Threads.h396
1 files changed, 396 insertions, 0 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Threads.h b/LibOVR/Src/Kernel/OVR_Threads.h
new file mode 100644
index 0000000..9c29fe0
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Threads.h
@@ -0,0 +1,396 @@
+/************************************************************************************
+
+PublicHeader: None
+Filename : OVR_Threads.h
+Content : Contains thread-related (safe) functionality
+Created : September 19, 2012
+Notes :
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+************************************************************************************/
+#ifndef OVR_Threads_h
+#define OVR_Threads_h
+
+#include "OVR_Types.h"
+#include "OVR_Atomic.h"
+#include "OVR_RefCount.h"
+#include "OVR_Array.h"
+
+// Defines the infinite wait delay timeout
+#define OVR_WAIT_INFINITE 0xFFFFFFFF
+
+// To be defined in the project configuration options
+#ifdef OVR_ENABLE_THREADS
+
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ****** Declared classes
+
+// Declared with thread support only
+class Mutex;
+class WaitCondition;
+class Event;
+// Implementation forward declarations
+class MutexImpl;
+class WaitConditionImpl;
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Mutex
+
+// Mutex class represents a system Mutex synchronization object that provides access
+// serialization between different threads, allowing one thread mutually exclusive access
+// to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition.
+
+class Mutex
+{
+ friend class WaitConditionImpl;
+ friend class MutexImpl;
+
+ MutexImpl *pImpl;
+
+public:
+ // Constructor/destructor
+ Mutex(bool recursive = 1);
+ ~Mutex();
+
+ // Locking functions
+ void DoLock();
+ bool TryLock();
+ void Unlock();
+
+ // Returns 1 if the mutes is currently locked by another thread
+ // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired.
+ bool IsLockedByAnotherThread();
+
+ // Locker class; Used for automatic locking of a mutex withing scope
+ class Locker
+ {
+ public:
+ Mutex *pMutex;
+ Locker(Mutex *pmutex)
+ { pMutex = pmutex; pMutex->DoLock(); }
+ ~Locker()
+ { pMutex->Unlock(); }
+ };
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** WaitCondition
+
+/*
+ WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
+ Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
+ call Notify() or NotifyAll().
+
+ The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then
+ starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
+ resource, this ensures that any condition checked for while the mutex was locked does not change before
+ the wait on the condition is actually initiated.
+*/
+
+class WaitCondition
+{
+ friend class WaitConditionImpl;
+ // Internal implementation structure
+ WaitConditionImpl *pImpl;
+
+public:
+ // Constructor/destructor
+ WaitCondition();
+ ~WaitCondition();
+
+ // Release mutex and wait for condition. The mutex is re-aquired after the wait.
+ // Delay is specified in milliseconds (1/1000 of a second).
+ bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
+
+ // Notify a condition, releasing at one object waiting
+ void Notify();
+ // Notify a condition, releasing all objects waiting
+ void NotifyAll();
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Event
+
+// Event is a wait-able synchronization object similar to Windows event.
+// Event can be waited on until it's signaled by another thread calling
+// either SetEvent or PulseEvent.
+
+class Event
+{
+ // Event state, its mutex and the wait condition
+ volatile bool State;
+ volatile bool Temporary;
+ mutable Mutex StateMutex;
+ WaitCondition StateWaitCondition;
+
+ void updateState(bool newState, bool newTemp, bool mustNotify);
+
+public:
+ Event(bool setInitially = 0) : State(setInitially), Temporary(false) { }
+ ~Event() { }
+
+ // Wait on an event condition until it is set
+ // Delay is specified in milliseconds (1/1000 of a second).
+ bool Wait(unsigned delay = OVR_WAIT_INFINITE);
+
+ // Set an event, releasing objects waiting on it
+ void SetEvent()
+ { updateState(true, false, true); }
+
+ // Reset an event, un-signaling it
+ void ResetEvent()
+ { updateState(false, false, false); }
+
+ // Set and then reset an event once a waiter is released.
+ // If threads are already waiting, they will be notified and released
+ // If threads are not waiting, the event is set until the first thread comes in
+ void PulseEvent()
+ { updateState(true, true, true); }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Thread class
+
+// ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and
+// Thread::GetThreadId.
+typedef void* ThreadId;
+
+
+// *** Thread flags
+
+// Indicates that the thread is has been started, i.e. Start method has been called, and threads
+// OnExit() method has not yet been called/returned.
+#define OVR_THREAD_STARTED 0x01
+// This flag is set once the thread has ran, and finished.
+#define OVR_THREAD_FINISHED 0x02
+// This flag is set temporarily if this thread was started suspended. It is used internally.
+#define OVR_THREAD_START_SUSPENDED 0x08
+// This flag is used to ask a thread to exit. Message driven threads will usually check this flag
+// and finish once it is set.
+#define OVR_THREAD_EXIT 0x10
+
+
+class Thread : public RefCountBase<Thread>
+{ // NOTE: Waitable must be the first base since it implements RefCountImpl.
+
+public:
+
+ // *** Callback functions, can be used instead of overriding Run
+
+ // Run function prototypes.
+ // Thread function and user handle passed to it, executed by the default
+ // Thread::Run implementation if not null.
+ typedef int (*ThreadFn)(Thread *pthread, void* h);
+
+ // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
+ ThreadFn ThreadFunction;
+ // User handle passes to a thread
+ void* UserHandle;
+
+ // Thread state to start a thread with
+ enum ThreadState
+ {
+ NotRunning = 0,
+ Running = 1,
+ Suspended = 2
+ };
+
+ // Thread priority
+ enum ThreadPriority
+ {
+ CriticalPriority,
+ HighestPriority,
+ AboveNormalPriority,
+ NormalPriority,
+ BelowNormalPriority,
+ LowestPriority,
+ IdlePriority,
+ };
+
+ // Thread constructor parameters
+ struct CreateParams
+ {
+ CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024,
+ int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
+ : threadFunction(func), userHandle(hand), stackSize(ssize),
+ processor(proc), initialState(state), priority(prior) {}
+ ThreadFn threadFunction; // Thread function
+ void* userHandle; // User handle passes to a thread
+ UPInt stackSize; // Thread stack size
+ int processor; // Thread hardware processor
+ ThreadState initialState; //
+ ThreadPriority priority; // Thread priority
+ };
+
+ // *** Constructors
+
+ // A default constructor always creates a thread in NotRunning state, because
+ // the derived class has not yet been initialized. The derived class can call Start explicitly.
+ // "processor" parameter specifies which hardware processor this thread will be run on.
+ // -1 means OS decides this. Implemented only on Win32
+ Thread(UPInt stackSize = 128 * 1024, int processor = -1);
+ // Constructors that initialize the thread with a pointer to function.
+ // An option to start a thread is available, but it should not be used if classes are derived from Thread.
+ // "processor" parameter specifies which hardware processor this thread will be run on.
+ // -1 means OS decides this. Implemented only on Win32
+ Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024,
+ int processor = -1, ThreadState initialState = NotRunning);
+ // Constructors that initialize the thread with a create parameters structure.
+ explicit Thread(const CreateParams& params);
+
+ // Destructor.
+ virtual ~Thread();
+
+ // Waits for all Threads to finish; should be called only from the root
+ // application thread. Once this function returns, we know that all other
+ // thread's references to Thread object have been released.
+ static void OVR_CDECL FinishAllThreads();
+
+
+ // *** Overridable Run function for thread processing
+
+ // - returning from this method will end the execution of the thread
+ // - return value is usually 0 for success
+ virtual int Run();
+ // Called after return/exit function
+ virtual void OnExit();
+
+
+ // *** Thread management
+
+ // Starts the thread if its not already running
+ // - internally sets up the threading and calls Run()
+ // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
+ // - returns the exit code
+ virtual bool Start(ThreadState initialState = Running);
+
+ // Quits with an exit code
+ virtual void Exit(int exitCode=0);
+
+ // Suspend the thread until resumed
+ // Returns 1 for success, 0 for failure.
+ bool Suspend();
+ // Resumes currently suspended thread
+ // Returns 1 for success, 0 for failure.
+ bool Resume();
+
+ // Static function to return a pointer to the current thread
+ //static Thread* GetThread();
+
+
+ // *** Thread status query functions
+
+ bool GetExitFlag() const;
+ void SetExitFlag(bool exitFlag);
+
+ // Determines whether the thread was running and is now finished
+ bool IsFinished() const;
+ // Determines if the thread is currently suspended
+ bool IsSuspended() const;
+ // Returns current thread state
+ ThreadState GetThreadState() const;
+
+ // Returns the number of available CPUs on the system
+ static int GetCPUCount();
+
+ // Returns the thread exit code. Exit code is initialized to 0,
+ // and set to the return value if Run function after the thread is finished.
+ inline int GetExitCode() const { return ExitCode; }
+ // Returns an OS handle
+#if defined(OVR_OS_WIN32)
+ void* GetOSHandle() const { return ThreadHandle; }
+#else
+ pthread_t GetOSHandle() const { return ThreadHandle; }
+#endif
+
+#if defined(OVR_OS_WIN32)
+ ThreadId GetThreadId() const { return IdValue; }
+#else
+ ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); }
+#endif
+
+ static int GetOSPriority(ThreadPriority);
+ // *** Sleep
+
+ // Sleep secs seconds
+ static bool Sleep(unsigned secs);
+ // Sleep msecs milliseconds
+ static bool MSleep(unsigned msecs);
+
+
+ // *** Debugging functionality
+#if defined(OVR_OS_WIN32)
+ virtual void SetThreadName( const char* name );
+#else
+ virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); }
+#endif
+
+private:
+#if defined(OVR_OS_WIN32)
+ friend unsigned WINAPI Thread_Win32StartFn(void *pthread);
+
+#else
+ friend void *Thread_PthreadStartFn(void * phandle);
+
+ static int InitAttr;
+ static pthread_attr_t Attr;
+#endif
+
+protected:
+ // Thread state flags
+ AtomicInt<UInt32> ThreadFlags;
+ AtomicInt<SInt32> SuspendCount;
+ UPInt StackSize;
+
+ // Hardware processor which this thread is running on.
+ int Processor;
+ ThreadPriority Priority;
+
+#if defined(OVR_OS_WIN32)
+ void* ThreadHandle;
+ volatile ThreadId IdValue;
+
+ // System-specific cleanup function called from destructor
+ void CleanupSystemThread();
+
+#else
+ pthread_t ThreadHandle;
+#endif
+
+ // Exit code of the thread, as returned by Run.
+ int ExitCode;
+
+ // Internal run function.
+ int PRun();
+ // Finishes the thread and releases internal reference to it.
+ void FinishAndRelease();
+
+ void Init(const CreateParams& params);
+
+ // Protected copy constructor
+ Thread(const Thread &source) { OVR_UNUSED(source); }
+
+};
+
+// Returns the unique Id of a thread it is called on, intended for
+// comparison purposes.
+ThreadId GetCurrentThreadId();
+
+
+} // OVR
+
+#endif // OVR_ENABLE_THREADS
+#endif // OVR_Threads_h