summaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Kernel/OVR_System.h
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/Kernel/OVR_System.h')
-rw-r--r--LibOVR/Src/Kernel/OVR_System.h102
1 files changed, 97 insertions, 5 deletions
diff --git a/LibOVR/Src/Kernel/OVR_System.h b/LibOVR/Src/Kernel/OVR_System.h
index 253fe19..a85cd49 100644
--- a/LibOVR/Src/Kernel/OVR_System.h
+++ b/LibOVR/Src/Kernel/OVR_System.h
@@ -31,9 +31,102 @@ limitations under the License.
#include "OVR_Allocator.h"
#include "OVR_Log.h"
+#include "OVR_Atomic.h"
namespace OVR {
+
+//-----------------------------------------------------------------------------
+// SystemSingleton
+
+// Subsystems are implemented using the Singleton pattern.
+// To avoid code duplication in all the places where Singletons are defined,
+// The pattern is defined once here and used everywhere.
+
+class SystemSingletonInternal
+{
+ friend class System;
+
+ SystemSingletonInternal* NextSingleton;
+
+ // No copying allowed
+ SystemSingletonInternal(const SystemSingletonInternal&) {}
+ void operator=(const SystemSingletonInternal&) {}
+
+protected:
+ SystemSingletonInternal() :
+ NextSingleton(0)
+ {
+ }
+
+ // Call this to register the destroy events
+ // Destroy callbacks will be called in the reverse order they were registered
+ // Note: As a rule of thumb, call this at the end of the singleton class constructor.
+ void PushDestroyCallbacks();
+
+ // Required: Invoked when the System object is shutting down
+ // Called after threads are stopped
+ // Called before Log, Allocator, and Timer subsystems are stopped
+ // Listeners are called in the opposite order they were registered
+ virtual void OnSystemDestroy() = 0;
+
+ // Called just before waiting for threads to die
+ // Listeners are called in the opposite order they were registered
+ // Useful to start terminating threads at the right time
+ // Note: The singleton must not delete itself here.
+ virtual void OnThreadDestroy() {}
+};
+
+// Singletons derive from this class
+template<class T>
+class SystemSingletonBase : public SystemSingletonInternal
+{
+ static AtomicPtr<T> SingletonInstance;
+ static T* SlowGetInstance();
+
+protected:
+ ~SystemSingletonBase()
+ {
+ // Make sure the instance gets set to zero on dtor
+ if (SingletonInstance == this)
+ SingletonInstance = 0;
+ }
+
+public:
+ static OVR_FORCE_INLINE T* GetInstance()
+ {
+ // Fast version
+ // Note: The singleton instance is stored in an AtomicPtr<> to allow it to be accessed
+ // atomically from multiple threads without locks.
+ T* instance = SingletonInstance;
+ return instance ? instance : SlowGetInstance();
+ }
+};
+
+// For reference, see N3337 14.5.1.3 (Static data members of class templates):
+template<class T> OVR::AtomicPtr<T> OVR::SystemSingletonBase<T>::SingletonInstance;
+
+// Place this in the singleton class in the header file
+#define OVR_DECLARE_SINGLETON(T) \
+ friend class OVR::SystemSingletonBase<T>; \
+private: \
+ T(); \
+ ~T(); \
+ virtual void OnSystemDestroy();
+
+// Place this in the singleton class source file
+#define OVR_DEFINE_SINGLETON(T) \
+ namespace OVR { \
+ template<> T* SystemSingletonBase<T>::SlowGetInstance() \
+ { \
+ static OVR::Lock lock; \
+ OVR::Lock::Locker locker(&lock); \
+ if (!SingletonInstance) SingletonInstance = new T; \
+ return SingletonInstance; \
+ } \
+ }
+
+
// ***** System Core Initialization class
// System initialization must take place before any other OVR_Kernel objects are used;
@@ -47,14 +140,12 @@ namespace OVR {
class System
{
public:
-
// System constructor expects allocator to be specified, if it is being substituted.
System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
Allocator* palloc = DefaultAllocator::InitSystemSingleton())
{
Init(log, palloc);
}
-
~System()
{
Destroy();
@@ -68,11 +159,12 @@ public:
static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
Allocator *palloc = DefaultAllocator::InitSystemSingleton());
- // De-initializes System more, finalizing the threading system and destroying
+ // De-initializes System more, finalizing the threading system and destroying
// the global memory allocator.
- static void OVR_CDECL Destroy();
+ static void OVR_CDECL Destroy();
};
-} // OVR
+
+} // namespace OVR
#endif