1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
/************************************************************************************
PublicHeader: OVR
Filename : OVR_System.h
Content : General kernel initialization/cleanup, including that
of the memory allocator.
Created : September 19, 2012
Notes :
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Licensed under the Oculus Master SDK License Version 1.0 (the "License");
you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
https://developer.oculus.com/licenses/oculusmastersdk-1.0
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************************/
#ifndef OVR_System_h
#define OVR_System_h
#include "OVR_Allocator.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;
// Allows for including this class in the shutdown list.
SystemSingletonInternal* NextShutdownSingleton;
// No copying allowed
OVR_NON_COPYABLE(SystemSingletonInternal);
public:
// Call this to register for a call to OnThreadDestroy and OnSystemDestroy before the
// Kernel is shut down. OnThreadDestroy is called before any remaining existing threads
// are exited. Registered callbacks are called in the reverse order they were registered.
// You would typically call this at the end of your SystemSingletonInternal subclass' constructor.
// The registered objects are not deleted on shutdown; they would have to do that themselves
// within
// OnSystemDestroy or via a compiler-generated static destruction.
void RegisterDestroyCallback();
void PushDestroyCallbacks() {
RegisterDestroyCallback();
} // For backward compatibility.
protected:
SystemSingletonInternal() : NextShutdownSingleton(nullptr) {}
virtual ~SystemSingletonInternal() {}
// Initializes the SystemSingletonInternal.
// You can register for an automatic call to this function by calling PushInitCallbacks.
// The registration of an automatic call to this is not required, but may be useful if
// you need to postpone your initialization until after Kernel is initialized.
// You cannot call PushInitCallbacks or PushDestroyCallbacks while within this function.
virtual void OnSystemInit() {}
// Called just before waiting for threads to exit.
// Listeners are called in the opposite order they were registered.
// This function is useful for terminating threads at the right time before the rest of the system
// is shut down.
// Note: The singleton must not delete itself here, as OnSystemDestroy will subsequently be called
// for it.
virtual void OnThreadDestroy() {}
// Shuts down the SystemSingletonInternal.
// You can register for an automatic call to this function by calling PushDestroyCallbacks.
// The registration of an automatic call to this is not required, but may be useful if
// you need to delay your shutdown until application exit time.
// You cannot call PushInitCallbacks or PushDestroyCallbacks while within this function.
// This function may delete this.
virtual void OnSystemDestroy() {}
};
// Singletons derive from this class
template <class T>
class SystemSingletonBase : public SystemSingletonInternal {
static std::atomic<T*> SingletonInstance;
static T* SlowGetInstance();
struct ZeroInitializer {
ZeroInitializer() {
SingletonInstance = nullptr;
}
};
ZeroInitializer zeroInitializer;
protected:
~SystemSingletonBase() {
// Make sure the instance gets set to zero on dtor
if (SingletonInstance.load() == this)
SingletonInstance = nullptr;
}
public:
static OVR_FORCE_INLINE T* GetInstance() {
// Fast version
// Note: The singleton instance is stored in an std::atomic<> 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>
std::atomic<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(); \
virtual ~T(); \
virtual void OnSystemDestroy() override;
// 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.load()) \
SingletonInstance = new T; \
return SingletonInstance; \
} \
}
// ***** System Core Initialization class
// System initialization must take place before any other OVR_Kernel objects are used;
// this is done my calling System::Init(). Among other things, this is necessary to
// initialize the memory allocator. Similarly, System::Destroy must be
// called before program exist for proper cleanup. Both of these tasks can be achieved by
// simply creating System object first, allowing its constructor/destructor do the work.
class System {
public:
// Returns 'true' if system was properly initialized.
static bool OVR_CDECL IsInitialized();
// Initializes System core. Users can override memory implementation by passing
// a different Allocator here.
static void OVR_CDECL Init();
// Halt all system threads (call before Destroy).
static void OVR_CDECL Stop();
// De-initializes System more, finalizing the threading system and destroying
// the global memory allocator.
static void OVR_CDECL Destroy();
// Dump any leaked allocations
static void OVR_CDECL CheckForAllocatorLeaks();
};
} // namespace OVR
#endif
|