rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 PublicHeader: OVR_Kernel.h
|
nuclear@0
|
4 Filename : OVR_Allocator.h
|
nuclear@0
|
5 Content : Installable memory allocator
|
nuclear@0
|
6 Created : September 19, 2012
|
nuclear@0
|
7 Notes :
|
nuclear@0
|
8
|
nuclear@0
|
9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
10
|
nuclear@0
|
11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
13 which is provided at the time of installation or download, or which
|
nuclear@0
|
14 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
15
|
nuclear@0
|
16 You may obtain a copy of the License at
|
nuclear@0
|
17
|
nuclear@0
|
18 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
19
|
nuclear@0
|
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
21 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
23 See the License for the specific language governing permissions and
|
nuclear@0
|
24 limitations under the License.
|
nuclear@0
|
25
|
nuclear@0
|
26 ************************************************************************************/
|
nuclear@0
|
27
|
nuclear@0
|
28 #ifndef OVR_Allocator_h
|
nuclear@0
|
29 #define OVR_Allocator_h
|
nuclear@0
|
30
|
nuclear@0
|
31 #include "OVR_Types.h"
|
nuclear@0
|
32
|
nuclear@0
|
33 //-----------------------------------------------------------------------------------
|
nuclear@0
|
34
|
nuclear@0
|
35 // ***** Disable template-unfriendly MS VC++ warnings
|
nuclear@0
|
36 #if defined(OVR_CC_MSVC)
|
nuclear@0
|
37 // Pragma to prevent long name warnings in in VC++
|
nuclear@0
|
38 #pragma warning(disable : 4503)
|
nuclear@0
|
39 #pragma warning(disable : 4786)
|
nuclear@0
|
40 // In MSVC 7.1, warning about placement new POD default initializer
|
nuclear@0
|
41 #pragma warning(disable : 4345)
|
nuclear@0
|
42 #endif
|
nuclear@0
|
43
|
nuclear@0
|
44 // Un-define new so that placement constructors work
|
nuclear@0
|
45 #undef new
|
nuclear@0
|
46
|
nuclear@0
|
47
|
nuclear@0
|
48 //-----------------------------------------------------------------------------------
|
nuclear@0
|
49 // ***** Placement new overrides
|
nuclear@0
|
50
|
nuclear@0
|
51 // Calls constructor on own memory created with "new(ptr) type"
|
nuclear@0
|
52 #ifndef __PLACEMENT_NEW_INLINE
|
nuclear@0
|
53 #define __PLACEMENT_NEW_INLINE
|
nuclear@0
|
54
|
nuclear@0
|
55 # if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU)
|
nuclear@0
|
56 # include <new>
|
nuclear@0
|
57 # else
|
nuclear@0
|
58 // Useful on MSVC
|
nuclear@0
|
59 OVR_FORCE_INLINE void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; }
|
nuclear@0
|
60 OVR_FORCE_INLINE void operator delete (void *, void *) { }
|
nuclear@0
|
61 # endif
|
nuclear@0
|
62
|
nuclear@0
|
63 #endif // __PLACEMENT_NEW_INLINE
|
nuclear@0
|
64
|
nuclear@0
|
65
|
nuclear@0
|
66
|
nuclear@0
|
67 //------------------------------------------------------------------------
|
nuclear@0
|
68 // ***** Macros to redefine class new/delete operators
|
nuclear@0
|
69
|
nuclear@0
|
70 // Types specifically declared to allow disambiguation of address in
|
nuclear@0
|
71 // class member operator new.
|
nuclear@0
|
72
|
nuclear@0
|
73 #define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete) \
|
nuclear@0
|
74 void* operator new(size_t sz) \
|
nuclear@0
|
75 { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; } \
|
nuclear@0
|
76 void* operator new(size_t sz, const char* file, int line) \
|
nuclear@0
|
77 { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; } \
|
nuclear@0
|
78 void operator delete(void *p) \
|
nuclear@0
|
79 { check_delete(class_name, p); OVR_FREE(p); } \
|
nuclear@0
|
80 void operator delete(void *p, const char*, int) \
|
nuclear@0
|
81 { check_delete(class_name, p); OVR_FREE(p); }
|
nuclear@0
|
82
|
nuclear@0
|
83 #define OVR_MEMORY_DEFINE_PLACEMENT_NEW \
|
nuclear@0
|
84 void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } \
|
nuclear@0
|
85 void operator delete (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); }
|
nuclear@0
|
86
|
nuclear@0
|
87
|
nuclear@0
|
88 #define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p)
|
nuclear@0
|
89
|
nuclear@0
|
90 // Redefined all delete/new operators in a class without custom memory initialization
|
nuclear@0
|
91 #define OVR_MEMORY_REDEFINE_NEW(class_name) \
|
nuclear@0
|
92 OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE)
|
nuclear@0
|
93
|
nuclear@0
|
94
|
nuclear@0
|
95 namespace OVR {
|
nuclear@0
|
96
|
nuclear@0
|
97 //-----------------------------------------------------------------------------------
|
nuclear@0
|
98 // ***** Construct / Destruct
|
nuclear@0
|
99
|
nuclear@0
|
100 // Construct/Destruct functions are useful when new is redefined, as they can
|
nuclear@0
|
101 // be called instead of placement new constructors.
|
nuclear@0
|
102
|
nuclear@0
|
103
|
nuclear@0
|
104 template <class T>
|
nuclear@0
|
105 OVR_FORCE_INLINE T* Construct(void *p)
|
nuclear@0
|
106 {
|
nuclear@0
|
107 return ::new(p) T();
|
nuclear@0
|
108 }
|
nuclear@0
|
109
|
nuclear@0
|
110 template <class T>
|
nuclear@0
|
111 OVR_FORCE_INLINE T* Construct(void *p, const T& source)
|
nuclear@0
|
112 {
|
nuclear@0
|
113 return ::new(p) T(source);
|
nuclear@0
|
114 }
|
nuclear@0
|
115
|
nuclear@0
|
116 // Same as above, but allows for a different type of constructor.
|
nuclear@0
|
117 template <class T, class S>
|
nuclear@0
|
118 OVR_FORCE_INLINE T* ConstructAlt(void *p, const S& source)
|
nuclear@0
|
119 {
|
nuclear@0
|
120 return ::new(p) T(source);
|
nuclear@0
|
121 }
|
nuclear@0
|
122
|
nuclear@0
|
123 template <class T, class S1, class S2>
|
nuclear@0
|
124 OVR_FORCE_INLINE T* ConstructAlt(void *p, const S1& src1, const S2& src2)
|
nuclear@0
|
125 {
|
nuclear@0
|
126 return ::new(p) T(src1, src2);
|
nuclear@0
|
127 }
|
nuclear@0
|
128
|
nuclear@0
|
129 template <class T>
|
nuclear@0
|
130 OVR_FORCE_INLINE void ConstructArray(void *p, size_t count)
|
nuclear@0
|
131 {
|
nuclear@0
|
132 uint8_t *pdata = (uint8_t*)p;
|
nuclear@0
|
133 for (size_t i=0; i< count; ++i, pdata += sizeof(T))
|
nuclear@0
|
134 {
|
nuclear@0
|
135 Construct<T>(pdata);
|
nuclear@0
|
136 }
|
nuclear@0
|
137 }
|
nuclear@0
|
138
|
nuclear@0
|
139 template <class T>
|
nuclear@0
|
140 OVR_FORCE_INLINE void ConstructArray(void *p, size_t count, const T& source)
|
nuclear@0
|
141 {
|
nuclear@0
|
142 uint8_t *pdata = (uint8_t*)p;
|
nuclear@0
|
143 for (size_t i=0; i< count; ++i, pdata += sizeof(T))
|
nuclear@0
|
144 {
|
nuclear@0
|
145 Construct<T>(pdata, source);
|
nuclear@0
|
146 }
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 template <class T>
|
nuclear@0
|
150 OVR_FORCE_INLINE void Destruct(T *pobj)
|
nuclear@0
|
151 {
|
nuclear@0
|
152 pobj->~T();
|
nuclear@0
|
153 OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning.
|
nuclear@0
|
154 }
|
nuclear@0
|
155
|
nuclear@0
|
156 template <class T>
|
nuclear@0
|
157 OVR_FORCE_INLINE void DestructArray(T *pobj, size_t count)
|
nuclear@0
|
158 {
|
nuclear@0
|
159 for (size_t i=0; i<count; ++i, ++pobj)
|
nuclear@0
|
160 pobj->~T();
|
nuclear@0
|
161 }
|
nuclear@0
|
162
|
nuclear@0
|
163
|
nuclear@0
|
164 //-----------------------------------------------------------------------------------
|
nuclear@0
|
165 // ***** Allocator
|
nuclear@0
|
166
|
nuclear@0
|
167 // Allocator defines a memory allocation interface that developers can override
|
nuclear@0
|
168 // to to provide memory for OVR; an instance of this class is typically created on
|
nuclear@0
|
169 // application startup and passed into System or OVR::System constructor.
|
nuclear@0
|
170 //
|
nuclear@0
|
171 //
|
nuclear@0
|
172 // Users implementing this interface must provide three functions: Alloc, Free,
|
nuclear@0
|
173 // and Realloc. Implementations of these functions must honor the requested alignment.
|
nuclear@0
|
174 // Although arbitrary alignment requests are possible, requested alignment will
|
nuclear@0
|
175 // typically be small, such as 16 bytes or less.
|
nuclear@0
|
176
|
nuclear@0
|
177 class Allocator
|
nuclear@0
|
178 {
|
nuclear@0
|
179 friend class System;
|
nuclear@0
|
180 public:
|
nuclear@0
|
181 virtual ~Allocator(){}
|
nuclear@0
|
182
|
nuclear@0
|
183 // *** Standard Alignment Alloc/Free
|
nuclear@0
|
184
|
nuclear@0
|
185 // Allocate memory of specified size with default alignment.
|
nuclear@0
|
186 // Alloc of size==0 will allocate a tiny block & return a valid pointer;
|
nuclear@0
|
187 // this makes it suitable for new operator.
|
nuclear@0
|
188 virtual void* Alloc(size_t size) = 0;
|
nuclear@0
|
189 // Same as Alloc, but provides an option of passing debug data.
|
nuclear@0
|
190 virtual void* AllocDebug(size_t size, const char* file, unsigned line)
|
nuclear@0
|
191 { OVR_UNUSED2(file, line); return Alloc(size); }
|
nuclear@0
|
192
|
nuclear@0
|
193 // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to
|
nuclear@0
|
194 // new memory block, which may be the same as original pointer. Will return 0 if reallocation
|
nuclear@0
|
195 // failed, in which case previous memory is still valid.
|
nuclear@0
|
196 // Realloc to decrease size will never fail.
|
nuclear@0
|
197 // Realloc of pointer == 0 is equivalent to Alloc
|
nuclear@0
|
198 // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free().
|
nuclear@0
|
199 virtual void* Realloc(void* p, size_t newSize) = 0;
|
nuclear@0
|
200
|
nuclear@0
|
201 // Frees memory allocated by Alloc/Realloc.
|
nuclear@0
|
202 // Free of null pointer is valid and will do nothing.
|
nuclear@0
|
203 virtual void Free(void *p) = 0;
|
nuclear@0
|
204
|
nuclear@0
|
205
|
nuclear@0
|
206 // *** Standard Alignment Alloc/Free
|
nuclear@0
|
207
|
nuclear@0
|
208 // Allocate memory of specified alignment.
|
nuclear@0
|
209 // Memory allocated with AllocAligned MUST be freed with FreeAligned.
|
nuclear@0
|
210 // Default implementation will delegate to Alloc/Free after doing rounding.
|
nuclear@0
|
211 virtual void* AllocAligned(size_t size, size_t align);
|
nuclear@0
|
212 // Frees memory allocated with AllocAligned.
|
nuclear@0
|
213 virtual void FreeAligned(void* p);
|
nuclear@0
|
214
|
nuclear@0
|
215 // Returns the pointer to the current globally installed Allocator instance.
|
nuclear@0
|
216 // This pointer is used for most of the memory allocations.
|
nuclear@0
|
217 static Allocator* GetInstance() { return pInstance; }
|
nuclear@0
|
218
|
nuclear@0
|
219
|
nuclear@0
|
220 protected:
|
nuclear@0
|
221 // onSystemShutdown is called on the allocator during System::Shutdown.
|
nuclear@0
|
222 // At this point, all allocations should've been freed.
|
nuclear@0
|
223 virtual void onSystemShutdown() { }
|
nuclear@0
|
224
|
nuclear@0
|
225 public:
|
nuclear@0
|
226 static void setInstance(Allocator* palloc)
|
nuclear@0
|
227 {
|
nuclear@0
|
228 OVR_ASSERT((pInstance == 0) || (palloc == 0));
|
nuclear@0
|
229 pInstance = palloc;
|
nuclear@0
|
230 }
|
nuclear@0
|
231
|
nuclear@0
|
232 private:
|
nuclear@0
|
233
|
nuclear@0
|
234 static Allocator* pInstance;
|
nuclear@0
|
235 };
|
nuclear@0
|
236
|
nuclear@0
|
237
|
nuclear@0
|
238
|
nuclear@0
|
239 //------------------------------------------------------------------------
|
nuclear@0
|
240 // ***** Allocator_SingletonSupport
|
nuclear@0
|
241
|
nuclear@0
|
242 // Allocator_SingletonSupport is a Allocator wrapper class that implements
|
nuclear@0
|
243 // the InitSystemSingleton static function, used to create a global singleton
|
nuclear@0
|
244 // used for the OVR::System default argument initialization.
|
nuclear@0
|
245 //
|
nuclear@0
|
246 // End users implementing custom Allocator interface don't need to make use of this base
|
nuclear@0
|
247 // class; they can just create an instance of their own class on stack and pass it to System.
|
nuclear@0
|
248
|
nuclear@0
|
249 template<class D>
|
nuclear@0
|
250 class Allocator_SingletonSupport : public Allocator
|
nuclear@0
|
251 {
|
nuclear@0
|
252 struct AllocContainer
|
nuclear@0
|
253 {
|
nuclear@0
|
254 size_t Data[(sizeof(D) + sizeof(size_t)-1) / sizeof(size_t)];
|
nuclear@0
|
255 bool Initialized;
|
nuclear@0
|
256 AllocContainer() : Initialized(0) { }
|
nuclear@0
|
257 };
|
nuclear@0
|
258
|
nuclear@0
|
259 AllocContainer* pContainer;
|
nuclear@0
|
260
|
nuclear@0
|
261 public:
|
nuclear@0
|
262 Allocator_SingletonSupport() : pContainer(0) { }
|
nuclear@0
|
263
|
nuclear@0
|
264 // Creates a singleton instance of this Allocator class used
|
nuclear@0
|
265 // on OVR_DEFAULT_ALLOCATOR during System initialization.
|
nuclear@0
|
266 static D* InitSystemSingleton()
|
nuclear@0
|
267 {
|
nuclear@0
|
268 static AllocContainer Container;
|
nuclear@0
|
269 OVR_ASSERT(Container.Initialized == false);
|
nuclear@0
|
270
|
nuclear@0
|
271 Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data);
|
nuclear@0
|
272 presult->pContainer = &Container;
|
nuclear@0
|
273 Container.Initialized = true;
|
nuclear@0
|
274 return (D*)presult;
|
nuclear@0
|
275 }
|
nuclear@0
|
276
|
nuclear@0
|
277 protected:
|
nuclear@0
|
278 virtual void onSystemShutdown()
|
nuclear@0
|
279 {
|
nuclear@0
|
280 Allocator::onSystemShutdown();
|
nuclear@0
|
281 if (pContainer)
|
nuclear@0
|
282 {
|
nuclear@0
|
283 pContainer->Initialized = false;
|
nuclear@0
|
284 Destruct((D*)this);
|
nuclear@0
|
285 pContainer = 0;
|
nuclear@0
|
286 }
|
nuclear@0
|
287 }
|
nuclear@0
|
288 };
|
nuclear@0
|
289
|
nuclear@0
|
290 //------------------------------------------------------------------------
|
nuclear@0
|
291 // ***** Default Allocator
|
nuclear@0
|
292
|
nuclear@0
|
293 // This allocator is created and used if no other allocator is installed.
|
nuclear@0
|
294 // Default allocator delegates to system malloc.
|
nuclear@0
|
295
|
nuclear@0
|
296 class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator>
|
nuclear@0
|
297 {
|
nuclear@0
|
298 public:
|
nuclear@0
|
299 virtual void* Alloc(size_t size);
|
nuclear@0
|
300 virtual void* AllocDebug(size_t size, const char* file, unsigned line);
|
nuclear@0
|
301 virtual void* Realloc(void* p, size_t newSize);
|
nuclear@0
|
302 virtual void Free(void *p);
|
nuclear@0
|
303 };
|
nuclear@0
|
304
|
nuclear@0
|
305
|
nuclear@0
|
306 //------------------------------------------------------------------------
|
nuclear@0
|
307 // ***** Memory Allocation Macros
|
nuclear@0
|
308
|
nuclear@0
|
309 // These macros should be used for global allocation. In the future, these
|
nuclear@0
|
310 // macros will allows allocation to be extended with debug file/line information
|
nuclear@0
|
311 // if necessary.
|
nuclear@0
|
312
|
nuclear@0
|
313 #define OVR_REALLOC(p,s) OVR::Allocator::GetInstance()->Realloc((p),(s))
|
nuclear@0
|
314 #define OVR_FREE(p) OVR::Allocator::GetInstance()->Free((p))
|
nuclear@0
|
315 #define OVR_ALLOC_ALIGNED(s,a) OVR::Allocator::GetInstance()->AllocAligned((s),(a))
|
nuclear@0
|
316 #define OVR_FREE_ALIGNED(p) OVR::Allocator::GetInstance()->FreeAligned((p))
|
nuclear@0
|
317
|
nuclear@0
|
318 #ifdef OVR_BUILD_DEBUG
|
nuclear@0
|
319 #define OVR_ALLOC(s) OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__)
|
nuclear@0
|
320 #define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->AllocDebug((s), f, l)
|
nuclear@0
|
321 #else
|
nuclear@0
|
322 #define OVR_ALLOC(s) OVR::Allocator::GetInstance()->Alloc((s))
|
nuclear@0
|
323 #define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->Alloc((s))
|
nuclear@0
|
324 #endif
|
nuclear@0
|
325
|
nuclear@0
|
326 //------------------------------------------------------------------------
|
nuclear@0
|
327
|
nuclear@0
|
328 // Base class that overrides the new and delete operators.
|
nuclear@0
|
329 // Deriving from this class, even as a multiple base, incurs no space overhead.
|
nuclear@0
|
330 class NewOverrideBase
|
nuclear@0
|
331 {
|
nuclear@0
|
332 public:
|
nuclear@0
|
333
|
nuclear@0
|
334 // Redefine all new & delete operators.
|
nuclear@0
|
335 OVR_MEMORY_REDEFINE_NEW(NewOverrideBase)
|
nuclear@0
|
336 };
|
nuclear@0
|
337
|
nuclear@0
|
338
|
nuclear@0
|
339 //------------------------------------------------------------------------
|
nuclear@0
|
340 // ***** Mapped memory allocation
|
nuclear@0
|
341 //
|
nuclear@0
|
342 // Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix.
|
nuclear@0
|
343 // These are useful for when you need system-supplied memory pages.
|
nuclear@0
|
344 // These are also useful for when you need to allocate memory in a way
|
nuclear@0
|
345 // that doesn't affect the application heap.
|
nuclear@0
|
346
|
nuclear@0
|
347 void* MMapAlloc(size_t size);
|
nuclear@0
|
348 void MMapFree(void* memory, size_t size);
|
nuclear@0
|
349
|
nuclear@0
|
350
|
nuclear@0
|
351 } // OVR
|
nuclear@0
|
352
|
nuclear@0
|
353
|
nuclear@0
|
354 // Redefine operator 'new' if necessary.
|
nuclear@0
|
355 #if defined(OVR_DEFINE_NEW)
|
nuclear@0
|
356 #define new OVR_DEFINE_NEW
|
nuclear@0
|
357 #endif
|
nuclear@0
|
358
|
nuclear@0
|
359
|
nuclear@0
|
360 #endif // OVR_Memory
|