oculus1

diff libovr/Src/Kernel/OVR_RefCount.h @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libovr/Src/Kernel/OVR_RefCount.h	Sat Sep 14 16:14:59 2013 +0300
     1.3 @@ -0,0 +1,1 @@
     1.4 +/************************************************************************************
     1.5 
     1.6 PublicHeader:   Kernel
     1.7 Filename    :   OVR_RefCount.h
     1.8 Content     :   Reference counting implementation headers
     1.9 Created     :   September 19, 2012
    1.10 Notes       : 
    1.11 
    1.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    1.13 
    1.14 Use of this software is subject to the terms of the Oculus license
    1.15 agreement provided at the time of installation or download, or which
    1.16 otherwise accompanies this software in either electronic or hard copy form.
    1.17 
    1.18 ************************************************************************************/
    1.19 
    1.20 #ifndef OVR_RefCount_h
    1.21 #define OVR_RefCount_h
    1.22 
    1.23 #include "OVR_Types.h"
    1.24 #include "OVR_Allocator.h"
    1.25 
    1.26 namespace OVR {
    1.27 
    1.28 //-----------------------------------------------------------------------------------
    1.29 // ***** Reference Counting
    1.30 
    1.31 // There are three types of reference counting base classes:
    1.32 //
    1.33 //  RefCountBase     - Provides thread-safe reference counting (Default).
    1.34 //  RefCountBaseNTS  - Non Thread Safe version of reference counting.
    1.35 
    1.36 
    1.37 // ***** Declared classes
    1.38 
    1.39 template<class C>
    1.40 class   RefCountBase;
    1.41 template<class C>
    1.42 class   RefCountBaseNTS;
    1.43 
    1.44 class   RefCountImpl;
    1.45 class   RefCountNTSImpl;
    1.46 
    1.47 
    1.48 //-----------------------------------------------------------------------------------
    1.49 // ***** Implementation For Reference Counting
    1.50 
    1.51 // RefCountImplCore holds RefCount value and defines a few utility
    1.52 // functions shared by all implementations.
    1.53 
    1.54 class RefCountImplCore
    1.55 {
    1.56 protected:
    1.57     volatile int RefCount;
    1.58 
    1.59 public:
    1.60     // RefCountImpl constructor always initializes RefCount to 1 by default.
    1.61     OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
    1.62 
    1.63     // Need virtual destructor
    1.64     // This:    1. Makes sure the right destructor's called.
    1.65     //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
    1.66     virtual ~RefCountImplCore();
    1.67 
    1.68     // Debug method only.
    1.69     int GetRefCount() const { return RefCount;  }
    1.70 
    1.71     // This logic is used to detect invalid 'delete' calls of reference counted
    1.72     // objects. Direct delete calls are not allowed on them unless they come in
    1.73     // internally from Release.
    1.74 #ifdef OVR_BUILD_DEBUG    
    1.75     static void   OVR_CDECL  reportInvalidDelete(void *pmem);
    1.76     inline static void checkInvalidDelete(RefCountImplCore *pmem)
    1.77     {
    1.78         if (pmem->RefCount != 0)
    1.79             reportInvalidDelete(pmem);
    1.80     }
    1.81 #else
    1.82     inline static void checkInvalidDelete(RefCountImplCore *) { }
    1.83 #endif
    1.84 
    1.85     // Base class ref-count content should not be copied.
    1.86     void operator = (const RefCountImplCore &) { }  
    1.87 };
    1.88 
    1.89 class RefCountNTSImplCore
    1.90 {
    1.91 protected:
    1.92     mutable int RefCount;
    1.93 
    1.94 public:
    1.95     // RefCountImpl constructor always initializes RefCount to 1 by default.
    1.96     OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
    1.97 
    1.98     // Need virtual destructor
    1.99     // This:    1. Makes sure the right destructor's called.
   1.100     //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
   1.101     virtual ~RefCountNTSImplCore();
   1.102 
   1.103     // Debug method only.
   1.104     int             GetRefCount() const { return RefCount;  }
   1.105 
   1.106     // This logic is used to detect invalid 'delete' calls of reference counted
   1.107     // objects. Direct delete calls are not allowed on them unless they come in
   1.108     // internally from Release.
   1.109 #ifdef OVR_BUILD_DEBUG    
   1.110     static void   OVR_CDECL  reportInvalidDelete(void *pmem);
   1.111     OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
   1.112     {
   1.113         if (pmem->RefCount != 0)
   1.114             reportInvalidDelete(pmem);
   1.115     }
   1.116 #else
   1.117     OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
   1.118 #endif
   1.119 
   1.120     // Base class ref-count content should not be copied.
   1.121     void operator = (const RefCountNTSImplCore &) { }  
   1.122 };
   1.123 
   1.124 
   1.125 
   1.126 // RefCountImpl provides Thread-Safe implementation of reference counting, so
   1.127 // it should be used by default in most places.
   1.128 
   1.129 class RefCountImpl : public RefCountImplCore
   1.130 {
   1.131 public:
   1.132     // Thread-Safe Ref-Count Implementation.
   1.133     void    AddRef();
   1.134     void    Release();   
   1.135 };
   1.136 
   1.137 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
   1.138 // virtual AddRef and Release.
   1.139 
   1.140 class RefCountVImpl : public RefCountImplCore
   1.141 {
   1.142 public:
   1.143     // Thread-Safe Ref-Count Implementation.
   1.144     virtual void      AddRef();
   1.145     virtual void      Release();   
   1.146 };
   1.147 
   1.148 
   1.149 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
   1.150 // which is slightly more efficient since it doesn't use atomics.
   1.151 
   1.152 class RefCountNTSImpl : public RefCountNTSImplCore
   1.153 {
   1.154 public:
   1.155     OVR_FORCE_INLINE void    AddRef() const { RefCount++; }
   1.156     void    Release() const;   
   1.157 };
   1.158 
   1.159 
   1.160 
   1.161 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
   1.162 // to the reference counting implementation. Base must be one of the RefCountImpl classes.
   1.163 
   1.164 template<class Base>
   1.165 class RefCountBaseStatImpl : public Base
   1.166 {
   1.167 public:
   1.168     RefCountBaseStatImpl() { }
   1.169      
   1.170     // *** Override New and Delete
   1.171 
   1.172     // DOM-IGNORE-BEGIN
   1.173     // Undef new temporarily if it is being redefined
   1.174 #ifdef OVR_DEFINE_NEW
   1.175 #undef new
   1.176 #endif
   1.177 
   1.178 #ifdef OVR_BUILD_DEBUG
   1.179     // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
   1.180     #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)   \
   1.181         do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
   1.182 #else
   1.183     #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
   1.184 #endif
   1.185 
   1.186     // Redefine all new & delete operators.
   1.187     OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
   1.188 
   1.189 #ifdef OVR_DEFINE_NEW
   1.190 #define new OVR_DEFINE_NEW
   1.191 #endif
   1.192         // OVR_BUILD_DEFINE_NEW
   1.193         // DOM-IGNORE-END
   1.194 };
   1.195 
   1.196 
   1.197 
   1.198 //-----------------------------------------------------------------------------------
   1.199 // *** End user RefCountBase<> classes
   1.200 
   1.201 
   1.202 // RefCountBase is a base class for classes that require thread-safe reference
   1.203 // counting; it also overrides the new and delete operators to use MemoryHeap.
   1.204 //
   1.205 // Reference counted objects start out with RefCount value of 1. Further lifetime
   1.206 // management is done through the AddRef() and Release() methods, typically
   1.207 // hidden by Ptr<>.
   1.208 
   1.209 template<class C>
   1.210 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
   1.211 {
   1.212 public:    
   1.213     // Constructor.
   1.214     OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }    
   1.215 };
   1.216 
   1.217 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
   1.218 
   1.219 template<class C>
   1.220 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl>
   1.221 {
   1.222 public:    
   1.223     // Constructor.
   1.224     OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { }    
   1.225 };
   1.226 
   1.227 
   1.228 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
   1.229 // counting; it also overrides the new and delete operators to use MemoryHeap.
   1.230 // This class should only be used if all pointers to it are known to be assigned,
   1.231 // destroyed and manipulated within one thread.
   1.232 //
   1.233 // Reference counted objects start out with RefCount value of 1. Further lifetime
   1.234 // management is done through the AddRef() and Release() methods, typically
   1.235 // hidden by Ptr<>.
   1.236 
   1.237 template<class C>
   1.238 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
   1.239 {
   1.240 public:    
   1.241     // Constructor.
   1.242     OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }    
   1.243 };
   1.244 
   1.245 //-----------------------------------------------------------------------------------
   1.246 // ***** Pickable template pointer
   1.247 enum PickType { PickValue };
   1.248 
   1.249 template <typename T>
   1.250 class Pickable
   1.251 {
   1.252 public:
   1.253     Pickable() : pV(NULL) {}
   1.254     explicit Pickable(T* p) : pV(p) {}
   1.255     Pickable(T* p, PickType) : pV(p) 
   1.256     {
   1.257         OVR_ASSERT(pV);
   1.258         if (pV)
   1.259             pV->AddRef();
   1.260     }
   1.261     template <typename OT>
   1.262     Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
   1.263 
   1.264 public:
   1.265     Pickable& operator =(const Pickable& other)
   1.266     {
   1.267         OVR_ASSERT(pV == NULL);
   1.268         pV = other.pV;
   1.269         // Extra check.
   1.270         //other.pV = NULL;
   1.271         return *this;
   1.272     }
   1.273 
   1.274 public:
   1.275     T* GetPtr() const { return pV; }
   1.276     T* operator->() const
   1.277     {
   1.278         return pV;
   1.279     }
   1.280     T& operator*() const
   1.281     {
   1.282         OVR_ASSERT(pV);
   1.283         return *pV;
   1.284     }
   1.285 
   1.286 private:
   1.287     T* pV;
   1.288 };
   1.289 
   1.290 template <typename T>
   1.291 OVR_FORCE_INLINE
   1.292 Pickable<T> MakePickable(T* p)
   1.293 {
   1.294     return Pickable<T>(p);
   1.295 }
   1.296 
   1.297 //-----------------------------------------------------------------------------------
   1.298 // ***** Ref-Counted template pointer
   1.299 
   1.300 // Automatically AddRefs and Releases interfaces
   1.301 
   1.302 void* ReturnArg0(void* p);
   1.303 
   1.304 template<class C>
   1.305 class Ptr
   1.306 {
   1.307 #ifdef OVR_CC_ARM
   1.308     static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
   1.309 #endif
   1.310 
   1.311 protected:
   1.312     C   *pObject;
   1.313 
   1.314 public:
   1.315 
   1.316     // Constructors
   1.317     OVR_FORCE_INLINE Ptr() : pObject(0)
   1.318     { }
   1.319 #ifdef OVR_CC_ARM
   1.320     OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
   1.321 #else
   1.322     OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
   1.323 #endif
   1.324     { }
   1.325     OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
   1.326     {
   1.327         // No AddRef() on purpose.
   1.328     }
   1.329     OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
   1.330     {
   1.331         other.pObject = NULL;
   1.332         // No AddRef() on purpose.
   1.333     }
   1.334     OVR_FORCE_INLINE Ptr(C *pobj)
   1.335     {
   1.336         if (pobj) pobj->AddRef();   
   1.337         pObject = pobj;
   1.338     }
   1.339     OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
   1.340     {
   1.341         if (src.pObject) src.pObject->AddRef();     
   1.342         pObject = src.pObject;
   1.343     }
   1.344 
   1.345     template<class R>
   1.346     OVR_FORCE_INLINE Ptr(Ptr<R> &src)
   1.347     {
   1.348         if (src) src->AddRef();
   1.349         pObject = src;
   1.350     }
   1.351     template<class R>
   1.352     OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
   1.353     {
   1.354         // No AddRef() on purpose.
   1.355     }
   1.356 
   1.357     // Destructor
   1.358     OVR_FORCE_INLINE ~Ptr()
   1.359     {
   1.360         if (pObject) pObject->Release();        
   1.361     }
   1.362 
   1.363     // Compares
   1.364     OVR_FORCE_INLINE bool operator == (const Ptr &other) const       { return pObject == other.pObject; }
   1.365     OVR_FORCE_INLINE bool operator != (const Ptr &other) const       { return pObject != other.pObject; }
   1.366 
   1.367     OVR_FORCE_INLINE bool operator == (C *pother) const              { return pObject == pother; }
   1.368     OVR_FORCE_INLINE bool operator != (C *pother) const              { return pObject != pother; }
   1.369 
   1.370 
   1.371     OVR_FORCE_INLINE bool operator < (const Ptr &other) const       { return pObject < other.pObject; }
   1.372 
   1.373     // Assignment
   1.374     template<class R>
   1.375     OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
   1.376     {
   1.377         if (src) src->AddRef();
   1.378         if (pObject) pObject->Release();        
   1.379         pObject = src;
   1.380         return *this;
   1.381     }   
   1.382     // Specialization
   1.383     OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
   1.384     {
   1.385         if (src) src->AddRef();
   1.386         if (pObject) pObject->Release();        
   1.387         pObject = src;
   1.388         return *this;
   1.389     }   
   1.390     
   1.391     OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
   1.392     {
   1.393         if (psrc) psrc->AddRef();
   1.394         if (pObject) pObject->Release();        
   1.395         pObject = psrc;
   1.396         return *this;
   1.397     }   
   1.398     OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
   1.399     {       
   1.400         if (pObject) pObject->Release();        
   1.401         pObject = &src;
   1.402         return *this;
   1.403     }
   1.404     OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src)
   1.405     {
   1.406         return Pick(src);
   1.407     }
   1.408     template<class R>
   1.409     OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src)
   1.410     {
   1.411         return Pick(src);
   1.412     }
   1.413     
   1.414     // Set Assignment
   1.415     template<class R>
   1.416     OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
   1.417     {
   1.418         if (src) src->AddRef();
   1.419         if (pObject) pObject->Release();
   1.420         pObject = src;
   1.421         return *this;
   1.422     }
   1.423     // Specialization
   1.424     OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
   1.425     {
   1.426         if (src) src->AddRef();
   1.427         if (pObject) pObject->Release();
   1.428         pObject = src;
   1.429         return *this;
   1.430     }   
   1.431     
   1.432     OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
   1.433     {
   1.434         if (psrc) psrc->AddRef();
   1.435         if (pObject) pObject->Release();
   1.436         pObject = psrc;
   1.437         return *this;
   1.438     }   
   1.439     OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
   1.440     {       
   1.441         if (pObject) pObject->Release();
   1.442         pObject = &src;
   1.443         return *this;
   1.444     }
   1.445     OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src)
   1.446     {       
   1.447         return Pick(src);
   1.448     }
   1.449 
   1.450     // Nulls ref-counted pointer without decrement
   1.451     OVR_FORCE_INLINE void    NullWithoutRelease()    
   1.452     { 
   1.453         pObject = 0;    
   1.454     }
   1.455 
   1.456     // Clears the pointer to the object
   1.457     OVR_FORCE_INLINE void    Clear()
   1.458     {
   1.459         if (pObject) pObject->Release();
   1.460         pObject = 0;
   1.461     }
   1.462 
   1.463     // Obtain pointer reference directly, for D3D interfaces
   1.464     OVR_FORCE_INLINE C*& GetRawRef()                 { return pObject; }
   1.465 
   1.466     // Access Operators
   1.467     OVR_FORCE_INLINE C* GetPtr() const               { return pObject; }
   1.468     OVR_FORCE_INLINE C& operator * () const          { return *pObject; }
   1.469     OVR_FORCE_INLINE C* operator -> ()  const        { return pObject; }
   1.470     // Conversion                   
   1.471     OVR_FORCE_INLINE operator C* () const            { return pObject; }
   1.472 
   1.473     // Pickers.
   1.474 
   1.475     // Pick a value.
   1.476     OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other)
   1.477     {
   1.478         if (&other != this)
   1.479         {
   1.480             if (pObject) pObject->Release();
   1.481             pObject = other.pObject;
   1.482             other.pObject = 0;
   1.483         }
   1.484 
   1.485         return *this;
   1.486     }
   1.487 
   1.488     OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v)
   1.489     {
   1.490         if (v.GetPtr() != pObject)
   1.491         {
   1.492             if (pObject) pObject->Release();
   1.493             pObject = v.GetPtr();
   1.494         }
   1.495 
   1.496         return *this;
   1.497     }
   1.498 
   1.499     template<class R>
   1.500     OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v)
   1.501     {
   1.502         if (v.GetPtr() != pObject)
   1.503         {
   1.504             if (pObject) pObject->Release();
   1.505             pObject = v.GetPtr();
   1.506         }
   1.507 
   1.508         return *this;
   1.509     }
   1.510 
   1.511     OVR_FORCE_INLINE Ptr<C>& Pick(C* p)
   1.512     {
   1.513         if (p != pObject)
   1.514         {
   1.515             if (pObject) pObject->Release();
   1.516             pObject = p;
   1.517         }
   1.518 
   1.519         return *this;
   1.520     }
   1.521 };
   1.522 
   1.523 } // OVR
   1.524 
   1.525 #endif
   1.526 \ No newline at end of file