rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 PublicHeader: OVR
|
nuclear@0
|
4 Filename : OVR_System.h
|
nuclear@0
|
5 Content : General kernel initialization/cleanup, including that
|
nuclear@0
|
6 of the memory allocator.
|
nuclear@0
|
7 Created : September 19, 2012
|
nuclear@0
|
8 Notes :
|
nuclear@0
|
9
|
nuclear@0
|
10 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
11
|
nuclear@0
|
12 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
13 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
14 which is provided at the time of installation or download, or which
|
nuclear@0
|
15 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
16
|
nuclear@0
|
17 You may obtain a copy of the License at
|
nuclear@0
|
18
|
nuclear@0
|
19 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
20
|
nuclear@0
|
21 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
22 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
23 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
24 See the License for the specific language governing permissions and
|
nuclear@0
|
25 limitations under the License.
|
nuclear@0
|
26
|
nuclear@0
|
27 ************************************************************************************/
|
nuclear@0
|
28
|
nuclear@0
|
29 #ifndef OVR_System_h
|
nuclear@0
|
30 #define OVR_System_h
|
nuclear@0
|
31
|
nuclear@0
|
32 #include "OVR_Allocator.h"
|
nuclear@0
|
33 #include "OVR_Log.h"
|
nuclear@0
|
34 #include "OVR_Atomic.h"
|
nuclear@0
|
35
|
nuclear@0
|
36 namespace OVR {
|
nuclear@0
|
37
|
nuclear@0
|
38
|
nuclear@0
|
39 //-----------------------------------------------------------------------------
|
nuclear@0
|
40 // SystemSingleton
|
nuclear@0
|
41
|
nuclear@0
|
42 // Subsystems are implemented using the Singleton pattern.
|
nuclear@0
|
43 // To avoid code duplication in all the places where Singletons are defined,
|
nuclear@0
|
44 // The pattern is defined once here and used everywhere.
|
nuclear@0
|
45
|
nuclear@0
|
46 class SystemSingletonInternal
|
nuclear@0
|
47 {
|
nuclear@0
|
48 friend class System;
|
nuclear@0
|
49
|
nuclear@0
|
50 SystemSingletonInternal* NextSingleton;
|
nuclear@0
|
51
|
nuclear@0
|
52 // No copying allowed
|
nuclear@0
|
53 OVR_NON_COPYABLE(SystemSingletonInternal);
|
nuclear@0
|
54
|
nuclear@0
|
55 protected:
|
nuclear@0
|
56 SystemSingletonInternal() :
|
nuclear@0
|
57 NextSingleton(0)
|
nuclear@0
|
58 {
|
nuclear@0
|
59 }
|
nuclear@0
|
60
|
nuclear@0
|
61 virtual ~SystemSingletonInternal(){}
|
nuclear@0
|
62
|
nuclear@0
|
63 // Call this to register the destroy events
|
nuclear@0
|
64 // Destroy callbacks will be called in the reverse order they were registered
|
nuclear@0
|
65 // Note: As a rule of thumb, call this at the end of the singleton class constructor.
|
nuclear@0
|
66 void PushDestroyCallbacks();
|
nuclear@0
|
67
|
nuclear@0
|
68 // Required: Invoked when the System object is shutting down
|
nuclear@0
|
69 // Called after threads are stopped
|
nuclear@0
|
70 // Called before Log, Allocator, and Timer subsystems are stopped
|
nuclear@0
|
71 // Listeners are called in the opposite order they were registered
|
nuclear@0
|
72 virtual void OnSystemDestroy() = 0;
|
nuclear@0
|
73
|
nuclear@0
|
74 // Called just before waiting for threads to die
|
nuclear@0
|
75 // Listeners are called in the opposite order they were registered
|
nuclear@0
|
76 // Useful to start terminating threads at the right time
|
nuclear@0
|
77 // Note: The singleton must not delete itself here.
|
nuclear@0
|
78 virtual void OnThreadDestroy() {}
|
nuclear@0
|
79 };
|
nuclear@0
|
80
|
nuclear@0
|
81 // Singletons derive from this class
|
nuclear@0
|
82 template<class T>
|
nuclear@0
|
83 class SystemSingletonBase : public SystemSingletonInternal
|
nuclear@0
|
84 {
|
nuclear@0
|
85 static AtomicPtr<T> SingletonInstance;
|
nuclear@0
|
86 static T* SlowGetInstance();
|
nuclear@0
|
87
|
nuclear@0
|
88 protected:
|
nuclear@0
|
89 ~SystemSingletonBase()
|
nuclear@0
|
90 {
|
nuclear@0
|
91 // Make sure the instance gets set to zero on dtor
|
nuclear@0
|
92 if (SingletonInstance == this)
|
nuclear@0
|
93 SingletonInstance = 0;
|
nuclear@0
|
94 }
|
nuclear@0
|
95
|
nuclear@0
|
96 public:
|
nuclear@0
|
97 static OVR_FORCE_INLINE T* GetInstance()
|
nuclear@0
|
98 {
|
nuclear@0
|
99 // Fast version
|
nuclear@0
|
100 // Note: The singleton instance is stored in an AtomicPtr<> to allow it to be accessed
|
nuclear@0
|
101 // atomically from multiple threads without locks.
|
nuclear@0
|
102 T* instance = SingletonInstance;
|
nuclear@0
|
103 return instance ? instance : SlowGetInstance();
|
nuclear@0
|
104 }
|
nuclear@0
|
105 };
|
nuclear@0
|
106
|
nuclear@0
|
107 // For reference, see N3337 14.5.1.3 (Static data members of class templates):
|
nuclear@0
|
108 template<class T> OVR::AtomicPtr<T> OVR::SystemSingletonBase<T>::SingletonInstance;
|
nuclear@0
|
109
|
nuclear@0
|
110 // Place this in the singleton class in the header file
|
nuclear@0
|
111 #define OVR_DECLARE_SINGLETON(T) \
|
nuclear@0
|
112 friend class OVR::SystemSingletonBase<T>; \
|
nuclear@0
|
113 private: \
|
nuclear@0
|
114 T(); \
|
nuclear@0
|
115 virtual ~T(); \
|
nuclear@0
|
116 virtual void OnSystemDestroy();
|
nuclear@0
|
117
|
nuclear@0
|
118 // Place this in the singleton class source file
|
nuclear@0
|
119 #define OVR_DEFINE_SINGLETON(T) \
|
nuclear@0
|
120 namespace OVR { \
|
nuclear@0
|
121 template<> T* SystemSingletonBase<T>::SlowGetInstance() \
|
nuclear@0
|
122 { \
|
nuclear@0
|
123 static OVR::Lock lock; \
|
nuclear@0
|
124 OVR::Lock::Locker locker(&lock); \
|
nuclear@0
|
125 if (!SingletonInstance) SingletonInstance = new T; \
|
nuclear@0
|
126 return SingletonInstance; \
|
nuclear@0
|
127 } \
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@0
|
130
|
nuclear@0
|
131 // ***** System Core Initialization class
|
nuclear@0
|
132
|
nuclear@0
|
133 // System initialization must take place before any other OVR_Kernel objects are used;
|
nuclear@0
|
134 // this is done my calling System::Init(). Among other things, this is necessary to
|
nuclear@0
|
135 // initialize the memory allocator. Similarly, System::Destroy must be
|
nuclear@0
|
136 // called before program exist for proper cleanup. Both of these tasks can be achieved by
|
nuclear@0
|
137 // simply creating System object first, allowing its constructor/destructor do the work.
|
nuclear@0
|
138
|
nuclear@0
|
139 // TBD: Require additional System class for Oculus Rift API?
|
nuclear@0
|
140
|
nuclear@0
|
141 class System
|
nuclear@0
|
142 {
|
nuclear@0
|
143 public:
|
nuclear@0
|
144 // System constructor expects allocator to be specified, if it is being substituted.
|
nuclear@0
|
145 System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
|
nuclear@0
|
146 Allocator* palloc = DefaultAllocator::InitSystemSingleton())
|
nuclear@0
|
147 {
|
nuclear@0
|
148 Init(log, palloc);
|
nuclear@0
|
149 }
|
nuclear@0
|
150 ~System()
|
nuclear@0
|
151 {
|
nuclear@0
|
152 Destroy();
|
nuclear@0
|
153 }
|
nuclear@0
|
154
|
nuclear@0
|
155 static void OVR_CDECL DirectDisplayInitialize();
|
nuclear@0
|
156 static bool OVR_CDECL DirectDisplayEnabled();
|
nuclear@0
|
157
|
nuclear@0
|
158 // Returns 'true' if system was properly initialized.
|
nuclear@0
|
159 static bool OVR_CDECL IsInitialized();
|
nuclear@0
|
160
|
nuclear@0
|
161 // Initializes System core. Users can override memory implementation by passing
|
nuclear@0
|
162 // a different Allocator here.
|
nuclear@0
|
163 static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
|
nuclear@0
|
164 Allocator *palloc = DefaultAllocator::InitSystemSingleton());
|
nuclear@0
|
165
|
nuclear@0
|
166 // De-initializes System more, finalizing the threading system and destroying
|
nuclear@0
|
167 // the global memory allocator.
|
nuclear@0
|
168 static void OVR_CDECL Destroy();
|
nuclear@0
|
169 };
|
nuclear@0
|
170
|
nuclear@0
|
171
|
nuclear@0
|
172 } // namespace OVR
|
nuclear@0
|
173
|
nuclear@0
|
174 #endif
|