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