OVR_RefCount.h
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 PublicHeader:   Kernel
00004 Filename    :   OVR_RefCount.h
00005 Content     :   Reference counting implementation headers
00006 Created     :   September 19, 2012
00007 Notes       : 
00008 
00009 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00010 
00011 Use of this software is subject to the terms of the Oculus license
00012 agreement provided at the time of installation or download, or which
00013 otherwise accompanies this software in either electronic or hard copy form.
00014 
00015 ************************************************************************************/
00016 
00017 #ifndef OVR_RefCount_h
00018 #define OVR_RefCount_h
00019 
00020 #include "OVR_Types.h"
00021 #include "OVR_Allocator.h"
00022 
00023 namespace OVR {
00024 
00025 //-----------------------------------------------------------------------------------
00026 // ***** Reference Counting
00027 
00028 // There are three types of reference counting base classes:
00029 //
00030 //  RefCountBase     - Provides thread-safe reference counting (Default).
00031 //  RefCountBaseNTS  - Non Thread Safe version of reference counting.
00032 
00033 
00034 // ***** Declared classes
00035 
00036 template<class C>
00037 class   RefCountBase;
00038 template<class C>
00039 class   RefCountBaseNTS;
00040 
00041 class   RefCountImpl;
00042 class   RefCountNTSImpl;
00043 
00044 
00045 //-----------------------------------------------------------------------------------
00046 // ***** Implementation For Reference Counting
00047 
00048 // RefCountImplCore holds RefCount value and defines a few utility
00049 // functions shared by all implementations.
00050 
00051 class RefCountImplCore
00052 {
00053 protected:
00054     volatile int RefCount;
00055 
00056 public:
00057     // RefCountImpl constructor always initializes RefCount to 1 by default.
00058     OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
00059 
00060     // Need virtual destructor
00061     // This:    1. Makes sure the right destructor's called.
00062     //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
00063     virtual ~RefCountImplCore();
00064 
00065     // Debug method only.
00066     int GetRefCount() const { return RefCount;  }
00067 
00068     // This logic is used to detect invalid 'delete' calls of reference counted
00069     // objects. Direct delete calls are not allowed on them unless they come in
00070     // internally from Release.
00071 #ifdef OVR_BUILD_DEBUG    
00072     static void   OVR_CDECL  reportInvalidDelete(void *pmem);
00073     inline static void checkInvalidDelete(RefCountImplCore *pmem)
00074     {
00075         if (pmem->RefCount != 0)
00076             reportInvalidDelete(pmem);
00077     }
00078 #else
00079     inline static void checkInvalidDelete(RefCountImplCore *) { }
00080 #endif
00081 
00082     // Base class ref-count content should not be copied.
00083     void operator = (const RefCountImplCore &) { }  
00084 };
00085 
00086 class RefCountNTSImplCore
00087 {
00088 protected:
00089     mutable int RefCount;
00090 
00091 public:
00092     // RefCountImpl constructor always initializes RefCount to 1 by default.
00093     OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
00094 
00095     // Need virtual destructor
00096     // This:    1. Makes sure the right destructor's called.
00097     //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
00098     virtual ~RefCountNTSImplCore();
00099 
00100     // Debug method only.
00101     int             GetRefCount() const { return RefCount;  }
00102 
00103     // This logic is used to detect invalid 'delete' calls of reference counted
00104     // objects. Direct delete calls are not allowed on them unless they come in
00105     // internally from Release.
00106 #ifdef OVR_BUILD_DEBUG    
00107     static void   OVR_CDECL  reportInvalidDelete(void *pmem);
00108     OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
00109     {
00110         if (pmem->RefCount != 0)
00111             reportInvalidDelete(pmem);
00112     }
00113 #else
00114     OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
00115 #endif
00116 
00117     // Base class ref-count content should not be copied.
00118     void operator = (const RefCountNTSImplCore &) { }  
00119 };
00120 
00121 
00122 
00123 // RefCountImpl provides Thread-Safe implementation of reference counting, so
00124 // it should be used by default in most places.
00125 
00126 class RefCountImpl : public RefCountImplCore
00127 {
00128 public:
00129     // Thread-Safe Ref-Count Implementation.
00130     void    AddRef();
00131     void    Release();   
00132 };
00133 
00134 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
00135 // virtual AddRef and Release.
00136 
00137 class RefCountVImpl : public RefCountImplCore
00138 {
00139 public:
00140     // Thread-Safe Ref-Count Implementation.
00141     virtual void      AddRef();
00142     virtual void      Release();   
00143 };
00144 
00145 
00146 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
00147 // which is slightly more efficient since it doesn't use atomics.
00148 
00149 class RefCountNTSImpl : public RefCountNTSImplCore
00150 {
00151 public:
00152     OVR_FORCE_INLINE void    AddRef() const { RefCount++; }
00153     void    Release() const;   
00154 };
00155 
00156 
00157 
00158 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
00159 // to the reference counting implementation. Base must be one of the RefCountImpl classes.
00160 
00161 template<class Base>
00162 class RefCountBaseStatImpl : public Base
00163 {
00164 public:
00165     RefCountBaseStatImpl() { }
00166      
00167     // *** Override New and Delete
00168 
00169     // DOM-IGNORE-BEGIN
00170     // Undef new temporarily if it is being redefined
00171 #ifdef OVR_DEFINE_NEW
00172 #undef new
00173 #endif
00174 
00175 #ifdef OVR_BUILD_DEBUG
00176     // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
00177     #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)   \
00178         do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
00179 #else
00180     #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
00181 #endif
00182 
00183     // Redefine all new & delete operators.
00184     OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
00185 
00186 #ifdef OVR_DEFINE_NEW
00187 #define new OVR_DEFINE_NEW
00188 #endif
00189         // OVR_BUILD_DEFINE_NEW
00190         // DOM-IGNORE-END
00191 };
00192 
00193 
00194 
00195 //-----------------------------------------------------------------------------------
00196 // *** End user RefCountBase<> classes
00197 
00198 
00199 // RefCountBase is a base class for classes that require thread-safe reference
00200 // counting; it also overrides the new and delete operators to use MemoryHeap.
00201 //
00202 // Reference counted objects start out with RefCount value of 1. Further lifetime
00203 // management is done through the AddRef() and Release() methods, typically
00204 // hidden by Ptr<>.
00205 
00206 template<class C>
00207 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
00208 {
00209 public:    
00210     // Constructor.
00211     OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }    
00212 };
00213 
00214 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
00215 
00216 template<class C>
00217 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl>
00218 {
00219 public:    
00220     // Constructor.
00221     OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { }    
00222 };
00223 
00224 
00225 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
00226 // counting; it also overrides the new and delete operators to use MemoryHeap.
00227 // This class should only be used if all pointers to it are known to be assigned,
00228 // destroyed and manipulated within one thread.
00229 //
00230 // Reference counted objects start out with RefCount value of 1. Further lifetime
00231 // management is done through the AddRef() and Release() methods, typically
00232 // hidden by Ptr<>.
00233 
00234 template<class C>
00235 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
00236 {
00237 public:    
00238     // Constructor.
00239     OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }    
00240 };
00241 
00242 //-----------------------------------------------------------------------------------
00243 // ***** Pickable template pointer
00244 enum PickType { PickValue };
00245 
00246 template <typename T>
00247 class Pickable
00248 {
00249 public:
00250     Pickable() : pV(NULL) {}
00251     explicit Pickable(T* p) : pV(p) {}
00252     Pickable(T* p, PickType) : pV(p) 
00253     {
00254         OVR_ASSERT(pV);
00255         if (pV)
00256             pV->AddRef();
00257     }
00258     template <typename OT>
00259     Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
00260 
00261 public:
00262     Pickable& operator =(const Pickable& other)
00263     {
00264         OVR_ASSERT(pV == NULL);
00265         pV = other.pV;
00266         // Extra check.
00267         //other.pV = NULL;
00268         return *this;
00269     }
00270 
00271 public:
00272     T* GetPtr() const { return pV; }
00273     T* operator->() const
00274     {
00275         return pV;
00276     }
00277     T& operator*() const
00278     {
00279         OVR_ASSERT(pV);
00280         return *pV;
00281     }
00282 
00283 private:
00284     T* pV;
00285 };
00286 
00287 template <typename T>
00288 OVR_FORCE_INLINE
00289 Pickable<T> MakePickable(T* p)
00290 {
00291     return Pickable<T>(p);
00292 }
00293 
00294 //-----------------------------------------------------------------------------------
00295 // ***** Ref-Counted template pointer
00296 
00297 // Automatically AddRefs and Releases interfaces
00298 
00299 void* ReturnArg0(void* p);
00300 
00301 template<class C>
00302 class Ptr
00303 {
00304 #ifdef OVR_CC_ARM
00305     static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
00306 #endif
00307 
00308 protected:
00309     C   *pObject;
00310 
00311 public:
00312 
00313     // Constructors
00314     OVR_FORCE_INLINE Ptr() : pObject(0)
00315     { }
00316 #ifdef OVR_CC_ARM
00317     OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
00318 #else
00319     OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
00320 #endif
00321     { }
00322     OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
00323     {
00324         // No AddRef() on purpose.
00325     }
00326     OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
00327     {
00328         other.pObject = NULL;
00329         // No AddRef() on purpose.
00330     }
00331     OVR_FORCE_INLINE Ptr(C *pobj)
00332     {
00333         if (pobj) pobj->AddRef();   
00334         pObject = pobj;
00335     }
00336     OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
00337     {
00338         if (src.pObject) src.pObject->AddRef();     
00339         pObject = src.pObject;
00340     }
00341 
00342     template<class R>
00343     OVR_FORCE_INLINE Ptr(Ptr<R> &src)
00344     {
00345         if (src) src->AddRef();
00346         pObject = src;
00347     }
00348     template<class R>
00349     OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
00350     {
00351         // No AddRef() on purpose.
00352     }
00353 
00354     // Destructor
00355     OVR_FORCE_INLINE ~Ptr()
00356     {
00357         if (pObject) pObject->Release();        
00358     }
00359 
00360     // Compares
00361     OVR_FORCE_INLINE bool operator == (const Ptr &other) const       { return pObject == other.pObject; }
00362     OVR_FORCE_INLINE bool operator != (const Ptr &other) const       { return pObject != other.pObject; }
00363 
00364     OVR_FORCE_INLINE bool operator == (C *pother) const              { return pObject == pother; }
00365     OVR_FORCE_INLINE bool operator != (C *pother) const              { return pObject != pother; }
00366 
00367 
00368     OVR_FORCE_INLINE bool operator < (const Ptr &other) const       { return pObject < other.pObject; }
00369 
00370     // Assignment
00371     template<class R>
00372     OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
00373     {
00374         if (src) src->AddRef();
00375         if (pObject) pObject->Release();        
00376         pObject = src;
00377         return *this;
00378     }   
00379     // Specialization
00380     OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
00381     {
00382         if (src) src->AddRef();
00383         if (pObject) pObject->Release();        
00384         pObject = src;
00385         return *this;
00386     }   
00387     
00388     OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
00389     {
00390         if (psrc) psrc->AddRef();
00391         if (pObject) pObject->Release();        
00392         pObject = psrc;
00393         return *this;
00394     }   
00395     OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
00396     {       
00397         if (pObject) pObject->Release();        
00398         pObject = &src;
00399         return *this;
00400     }
00401     OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src)
00402     {
00403         return Pick(src);
00404     }
00405     template<class R>
00406     OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src)
00407     {
00408         return Pick(src);
00409     }
00410     
00411     // Set Assignment
00412     template<class R>
00413     OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
00414     {
00415         if (src) src->AddRef();
00416         if (pObject) pObject->Release();
00417         pObject = src;
00418         return *this;
00419     }
00420     // Specialization
00421     OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
00422     {
00423         if (src) src->AddRef();
00424         if (pObject) pObject->Release();
00425         pObject = src;
00426         return *this;
00427     }   
00428     
00429     OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
00430     {
00431         if (psrc) psrc->AddRef();
00432         if (pObject) pObject->Release();
00433         pObject = psrc;
00434         return *this;
00435     }   
00436     OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
00437     {       
00438         if (pObject) pObject->Release();
00439         pObject = &src;
00440         return *this;
00441     }
00442     OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src)
00443     {       
00444         return Pick(src);
00445     }
00446 
00447     // Nulls ref-counted pointer without decrement
00448     OVR_FORCE_INLINE void    NullWithoutRelease()    
00449     { 
00450         pObject = 0;    
00451     }
00452 
00453     // Clears the pointer to the object
00454     OVR_FORCE_INLINE void    Clear()
00455     {
00456         if (pObject) pObject->Release();
00457         pObject = 0;
00458     }
00459 
00460     // Obtain pointer reference directly, for D3D interfaces
00461     OVR_FORCE_INLINE C*& GetRawRef()                 { return pObject; }
00462 
00463     // Access Operators
00464     OVR_FORCE_INLINE C* GetPtr() const               { return pObject; }
00465     OVR_FORCE_INLINE C& operator * () const          { return *pObject; }
00466     OVR_FORCE_INLINE C* operator -> ()  const        { return pObject; }
00467     // Conversion                   
00468     OVR_FORCE_INLINE operator C* () const            { return pObject; }
00469 
00470     // Pickers.
00471 
00472     // Pick a value.
00473     OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other)
00474     {
00475         if (&other != this)
00476         {
00477             if (pObject) pObject->Release();
00478             pObject = other.pObject;
00479             other.pObject = 0;
00480         }
00481 
00482         return *this;
00483     }
00484 
00485     OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v)
00486     {
00487         if (v.GetPtr() != pObject)
00488         {
00489             if (pObject) pObject->Release();
00490             pObject = v.GetPtr();
00491         }
00492 
00493         return *this;
00494     }
00495 
00496     template<class R>
00497     OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v)
00498     {
00499         if (v.GetPtr() != pObject)
00500         {
00501             if (pObject) pObject->Release();
00502             pObject = v.GetPtr();
00503         }
00504 
00505         return *this;
00506     }
00507 
00508     OVR_FORCE_INLINE Ptr<C>& Pick(C* p)
00509     {
00510         if (p != pObject)
00511         {
00512             if (pObject) pObject->Release();
00513             pObject = p;
00514         }
00515 
00516         return *this;
00517     }
00518 };
00519 
00520 } // OVR
00521 
00522 #endif


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19