ovr_sdk
diff LibOVR/Src/Kernel/OVR_Allocator.h @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Kernel/OVR_Allocator.h Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,360 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +PublicHeader: OVR_Kernel.h 1.7 +Filename : OVR_Allocator.h 1.8 +Content : Installable memory allocator 1.9 +Created : September 19, 2012 1.10 +Notes : 1.11 + 1.12 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.13 + 1.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.16 +which is provided at the time of installation or download, or which 1.17 +otherwise accompanies this software in either electronic or hard copy form. 1.18 + 1.19 +You may obtain a copy of the License at 1.20 + 1.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.22 + 1.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.24 +distributed under the License is distributed on an "AS IS" BASIS, 1.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.26 +See the License for the specific language governing permissions and 1.27 +limitations under the License. 1.28 + 1.29 +************************************************************************************/ 1.30 + 1.31 +#ifndef OVR_Allocator_h 1.32 +#define OVR_Allocator_h 1.33 + 1.34 +#include "OVR_Types.h" 1.35 + 1.36 +//----------------------------------------------------------------------------------- 1.37 + 1.38 +// ***** Disable template-unfriendly MS VC++ warnings 1.39 +#if defined(OVR_CC_MSVC) 1.40 +// Pragma to prevent long name warnings in in VC++ 1.41 +#pragma warning(disable : 4503) 1.42 +#pragma warning(disable : 4786) 1.43 +// In MSVC 7.1, warning about placement new POD default initializer 1.44 +#pragma warning(disable : 4345) 1.45 +#endif 1.46 + 1.47 +// Un-define new so that placement constructors work 1.48 +#undef new 1.49 + 1.50 + 1.51 +//----------------------------------------------------------------------------------- 1.52 +// ***** Placement new overrides 1.53 + 1.54 +// Calls constructor on own memory created with "new(ptr) type" 1.55 +#ifndef __PLACEMENT_NEW_INLINE 1.56 +#define __PLACEMENT_NEW_INLINE 1.57 + 1.58 +# if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU) 1.59 +# include <new> 1.60 +# else 1.61 + // Useful on MSVC 1.62 + OVR_FORCE_INLINE void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } 1.63 + OVR_FORCE_INLINE void operator delete (void *, void *) { } 1.64 +# endif 1.65 + 1.66 +#endif // __PLACEMENT_NEW_INLINE 1.67 + 1.68 + 1.69 + 1.70 +//------------------------------------------------------------------------ 1.71 +// ***** Macros to redefine class new/delete operators 1.72 + 1.73 +// Types specifically declared to allow disambiguation of address in 1.74 +// class member operator new. 1.75 + 1.76 +#define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete) \ 1.77 + void* operator new(size_t sz) \ 1.78 + { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; } \ 1.79 + void* operator new(size_t sz, const char* file, int line) \ 1.80 + { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; } \ 1.81 + void operator delete(void *p) \ 1.82 + { check_delete(class_name, p); OVR_FREE(p); } \ 1.83 + void operator delete(void *p, const char*, int) \ 1.84 + { check_delete(class_name, p); OVR_FREE(p); } 1.85 + 1.86 +#define OVR_MEMORY_DEFINE_PLACEMENT_NEW \ 1.87 + void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } \ 1.88 + void operator delete (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); } 1.89 + 1.90 + 1.91 +#define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p) 1.92 + 1.93 +// Redefined all delete/new operators in a class without custom memory initialization 1.94 +#define OVR_MEMORY_REDEFINE_NEW(class_name) \ 1.95 + OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE) 1.96 + 1.97 + 1.98 +namespace OVR { 1.99 + 1.100 +//----------------------------------------------------------------------------------- 1.101 +// ***** Construct / Destruct 1.102 + 1.103 +// Construct/Destruct functions are useful when new is redefined, as they can 1.104 +// be called instead of placement new constructors. 1.105 + 1.106 + 1.107 +template <class T> 1.108 +OVR_FORCE_INLINE T* Construct(void *p) 1.109 +{ 1.110 + return ::new(p) T(); 1.111 +} 1.112 + 1.113 +template <class T> 1.114 +OVR_FORCE_INLINE T* Construct(void *p, const T& source) 1.115 +{ 1.116 + return ::new(p) T(source); 1.117 +} 1.118 + 1.119 +// Same as above, but allows for a different type of constructor. 1.120 +template <class T, class S> 1.121 +OVR_FORCE_INLINE T* ConstructAlt(void *p, const S& source) 1.122 +{ 1.123 + return ::new(p) T(source); 1.124 +} 1.125 + 1.126 +template <class T, class S1, class S2> 1.127 +OVR_FORCE_INLINE T* ConstructAlt(void *p, const S1& src1, const S2& src2) 1.128 +{ 1.129 + return ::new(p) T(src1, src2); 1.130 +} 1.131 + 1.132 +template <class T> 1.133 +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count) 1.134 +{ 1.135 + uint8_t *pdata = (uint8_t*)p; 1.136 + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) 1.137 + { 1.138 + Construct<T>(pdata); 1.139 + } 1.140 +} 1.141 + 1.142 +template <class T> 1.143 +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count, const T& source) 1.144 +{ 1.145 + uint8_t *pdata = (uint8_t*)p; 1.146 + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) 1.147 + { 1.148 + Construct<T>(pdata, source); 1.149 + } 1.150 +} 1.151 + 1.152 +template <class T> 1.153 +OVR_FORCE_INLINE void Destruct(T *pobj) 1.154 +{ 1.155 + pobj->~T(); 1.156 + OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning. 1.157 +} 1.158 + 1.159 +template <class T> 1.160 +OVR_FORCE_INLINE void DestructArray(T *pobj, size_t count) 1.161 +{ 1.162 + for (size_t i=0; i<count; ++i, ++pobj) 1.163 + pobj->~T(); 1.164 +} 1.165 + 1.166 + 1.167 +//----------------------------------------------------------------------------------- 1.168 +// ***** Allocator 1.169 + 1.170 +// Allocator defines a memory allocation interface that developers can override 1.171 +// to to provide memory for OVR; an instance of this class is typically created on 1.172 +// application startup and passed into System or OVR::System constructor. 1.173 +// 1.174 +// 1.175 +// Users implementing this interface must provide three functions: Alloc, Free, 1.176 +// and Realloc. Implementations of these functions must honor the requested alignment. 1.177 +// Although arbitrary alignment requests are possible, requested alignment will 1.178 +// typically be small, such as 16 bytes or less. 1.179 + 1.180 +class Allocator 1.181 +{ 1.182 + friend class System; 1.183 +public: 1.184 + virtual ~Allocator(){} 1.185 + 1.186 + // *** Standard Alignment Alloc/Free 1.187 + 1.188 + // Allocate memory of specified size with default alignment. 1.189 + // Alloc of size==0 will allocate a tiny block & return a valid pointer; 1.190 + // this makes it suitable for new operator. 1.191 + virtual void* Alloc(size_t size) = 0; 1.192 + // Same as Alloc, but provides an option of passing debug data. 1.193 + virtual void* AllocDebug(size_t size, const char* file, unsigned line) 1.194 + { OVR_UNUSED2(file, line); return Alloc(size); } 1.195 + 1.196 + // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to 1.197 + // new memory block, which may be the same as original pointer. Will return 0 if reallocation 1.198 + // failed, in which case previous memory is still valid. 1.199 + // Realloc to decrease size will never fail. 1.200 + // Realloc of pointer == 0 is equivalent to Alloc 1.201 + // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free(). 1.202 + virtual void* Realloc(void* p, size_t newSize) = 0; 1.203 + 1.204 + // Frees memory allocated by Alloc/Realloc. 1.205 + // Free of null pointer is valid and will do nothing. 1.206 + virtual void Free(void *p) = 0; 1.207 + 1.208 + 1.209 + // *** Standard Alignment Alloc/Free 1.210 + 1.211 + // Allocate memory of specified alignment. 1.212 + // Memory allocated with AllocAligned MUST be freed with FreeAligned. 1.213 + // Default implementation will delegate to Alloc/Free after doing rounding. 1.214 + virtual void* AllocAligned(size_t size, size_t align); 1.215 + // Frees memory allocated with AllocAligned. 1.216 + virtual void FreeAligned(void* p); 1.217 + 1.218 + // Returns the pointer to the current globally installed Allocator instance. 1.219 + // This pointer is used for most of the memory allocations. 1.220 + static Allocator* GetInstance() { return pInstance; } 1.221 + 1.222 + 1.223 +protected: 1.224 + // onSystemShutdown is called on the allocator during System::Shutdown. 1.225 + // At this point, all allocations should've been freed. 1.226 + virtual void onSystemShutdown() { } 1.227 + 1.228 +public: 1.229 + static void setInstance(Allocator* palloc) 1.230 + { 1.231 + OVR_ASSERT((pInstance == 0) || (palloc == 0)); 1.232 + pInstance = palloc; 1.233 + } 1.234 + 1.235 +private: 1.236 + 1.237 + static Allocator* pInstance; 1.238 +}; 1.239 + 1.240 + 1.241 + 1.242 +//------------------------------------------------------------------------ 1.243 +// ***** Allocator_SingletonSupport 1.244 + 1.245 +// Allocator_SingletonSupport is a Allocator wrapper class that implements 1.246 +// the InitSystemSingleton static function, used to create a global singleton 1.247 +// used for the OVR::System default argument initialization. 1.248 +// 1.249 +// End users implementing custom Allocator interface don't need to make use of this base 1.250 +// class; they can just create an instance of their own class on stack and pass it to System. 1.251 + 1.252 +template<class D> 1.253 +class Allocator_SingletonSupport : public Allocator 1.254 +{ 1.255 + struct AllocContainer 1.256 + { 1.257 + size_t Data[(sizeof(D) + sizeof(size_t)-1) / sizeof(size_t)]; 1.258 + bool Initialized; 1.259 + AllocContainer() : Initialized(0) { } 1.260 + }; 1.261 + 1.262 + AllocContainer* pContainer; 1.263 + 1.264 +public: 1.265 + Allocator_SingletonSupport() : pContainer(0) { } 1.266 + 1.267 + // Creates a singleton instance of this Allocator class used 1.268 + // on OVR_DEFAULT_ALLOCATOR during System initialization. 1.269 + static D* InitSystemSingleton() 1.270 + { 1.271 + static AllocContainer Container; 1.272 + OVR_ASSERT(Container.Initialized == false); 1.273 + 1.274 + Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data); 1.275 + presult->pContainer = &Container; 1.276 + Container.Initialized = true; 1.277 + return (D*)presult; 1.278 + } 1.279 + 1.280 +protected: 1.281 + virtual void onSystemShutdown() 1.282 + { 1.283 + Allocator::onSystemShutdown(); 1.284 + if (pContainer) 1.285 + { 1.286 + pContainer->Initialized = false; 1.287 + Destruct((D*)this); 1.288 + pContainer = 0; 1.289 + } 1.290 + } 1.291 +}; 1.292 + 1.293 +//------------------------------------------------------------------------ 1.294 +// ***** Default Allocator 1.295 + 1.296 +// This allocator is created and used if no other allocator is installed. 1.297 +// Default allocator delegates to system malloc. 1.298 + 1.299 +class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator> 1.300 +{ 1.301 +public: 1.302 + virtual void* Alloc(size_t size); 1.303 + virtual void* AllocDebug(size_t size, const char* file, unsigned line); 1.304 + virtual void* Realloc(void* p, size_t newSize); 1.305 + virtual void Free(void *p); 1.306 +}; 1.307 + 1.308 + 1.309 +//------------------------------------------------------------------------ 1.310 +// ***** Memory Allocation Macros 1.311 + 1.312 +// These macros should be used for global allocation. In the future, these 1.313 +// macros will allows allocation to be extended with debug file/line information 1.314 +// if necessary. 1.315 + 1.316 +#define OVR_REALLOC(p,s) OVR::Allocator::GetInstance()->Realloc((p),(s)) 1.317 +#define OVR_FREE(p) OVR::Allocator::GetInstance()->Free((p)) 1.318 +#define OVR_ALLOC_ALIGNED(s,a) OVR::Allocator::GetInstance()->AllocAligned((s),(a)) 1.319 +#define OVR_FREE_ALIGNED(p) OVR::Allocator::GetInstance()->FreeAligned((p)) 1.320 + 1.321 +#ifdef OVR_BUILD_DEBUG 1.322 +#define OVR_ALLOC(s) OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__) 1.323 +#define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->AllocDebug((s), f, l) 1.324 +#else 1.325 +#define OVR_ALLOC(s) OVR::Allocator::GetInstance()->Alloc((s)) 1.326 +#define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->Alloc((s)) 1.327 +#endif 1.328 + 1.329 +//------------------------------------------------------------------------ 1.330 + 1.331 +// Base class that overrides the new and delete operators. 1.332 +// Deriving from this class, even as a multiple base, incurs no space overhead. 1.333 +class NewOverrideBase 1.334 +{ 1.335 +public: 1.336 + 1.337 + // Redefine all new & delete operators. 1.338 + OVR_MEMORY_REDEFINE_NEW(NewOverrideBase) 1.339 +}; 1.340 + 1.341 + 1.342 +//------------------------------------------------------------------------ 1.343 +// ***** Mapped memory allocation 1.344 +// 1.345 +// Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix. 1.346 +// These are useful for when you need system-supplied memory pages. 1.347 +// These are also useful for when you need to allocate memory in a way 1.348 +// that doesn't affect the application heap. 1.349 + 1.350 +void* MMapAlloc(size_t size); 1.351 +void MMapFree(void* memory, size_t size); 1.352 + 1.353 + 1.354 +} // OVR 1.355 + 1.356 + 1.357 +// Redefine operator 'new' if necessary. 1.358 +#if defined(OVR_DEFINE_NEW) 1.359 +#define new OVR_DEFINE_NEW 1.360 +#endif 1.361 + 1.362 + 1.363 +#endif // OVR_Memory