aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVRKernel/Src/Kernel/OVR_RefCount.h
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVRKernel/Src/Kernel/OVR_RefCount.h')
-rw-r--r--LibOVRKernel/Src/Kernel/OVR_RefCount.h512
1 files changed, 512 insertions, 0 deletions
diff --git a/LibOVRKernel/Src/Kernel/OVR_RefCount.h b/LibOVRKernel/Src/Kernel/OVR_RefCount.h
new file mode 100644
index 0000000..68c2633
--- /dev/null
+++ b/LibOVRKernel/Src/Kernel/OVR_RefCount.h
@@ -0,0 +1,512 @@
+/************************************************************************************
+
+PublicHeader: Kernel
+Filename : OVR_RefCount.h
+Content : Reference counting implementation headers
+Created : September 19, 2012
+Notes :
+
+Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
+which is provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.2
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_RefCount_h
+#define OVR_RefCount_h
+
+#include "OVR_Types.h"
+#include "OVR_Allocator.h"
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Reference Counting
+
+// There are three types of reference counting base classes:
+//
+// RefCountBase - Provides thread-safe reference counting (Default).
+// RefCountBaseNTS - Non Thread Safe version of reference counting.
+
+
+// ***** Declared classes
+
+template<class C>
+class RefCountBase;
+template<class C>
+class RefCountBaseNTS;
+
+class RefCountImpl;
+class RefCountNTSImpl;
+
+
+//-----------------------------------------------------------------------------------
+// ***** Implementation For Reference Counting
+
+// RefCountImplCore holds RefCount value and defines a few utility
+// functions shared by all implementations.
+
+class RefCountImplCore
+{
+protected:
+ volatile int RefCount;
+
+public:
+ // RefCountImpl constructor always initializes RefCount to 1 by default.
+ OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
+
+ // Need virtual destructor
+ // This: 1. Makes sure the right destructor's called.
+ // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
+ virtual ~RefCountImplCore();
+
+ // Debug method only.
+ int GetRefCount() const { return RefCount; }
+
+ // This logic is used to detect invalid 'delete' calls of reference counted
+ // objects. Direct delete calls are not allowed on them unless they come in
+ // internally from Release.
+#ifdef OVR_BUILD_DEBUG
+ static void OVR_CDECL reportInvalidDelete(void *pmem);
+ inline static void checkInvalidDelete(RefCountImplCore *pmem)
+ {
+ if (pmem->RefCount != 0)
+ reportInvalidDelete(pmem);
+ }
+#else
+ inline static void checkInvalidDelete(RefCountImplCore *) { }
+#endif
+
+ // Base class ref-count content should not be copied.
+ void operator = (const RefCountImplCore &) { }
+};
+
+class RefCountNTSImplCore
+{
+protected:
+ mutable int RefCount;
+
+public:
+ // RefCountImpl constructor always initializes RefCount to 1 by default.
+ OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
+
+ // Need virtual destructor
+ // This: 1. Makes sure the right destructor's called.
+ // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
+ virtual ~RefCountNTSImplCore();
+
+ // Debug method only.
+ int GetRefCount() const
+ {
+ return RefCount;
+ }
+
+ // This logic is used to detect invalid 'delete' calls of reference counted
+ // objects. Direct delete calls are not allowed on them unless they come in
+ // internally from Release.
+#ifdef OVR_BUILD_DEBUG
+ static void OVR_CDECL reportInvalidDelete(void *pmem);
+ OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
+ {
+ if (pmem->RefCount != 0)
+ reportInvalidDelete(pmem);
+ }
+#else
+ OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
+#endif
+
+ // Base class ref-count content should not be copied.
+ void operator = (const RefCountNTSImplCore &) { }
+};
+
+
+
+// RefCountImpl provides Thread-Safe implementation of reference counting, so
+// it should be used by default in most places.
+
+class RefCountImpl : public RefCountImplCore
+{
+public:
+ // Thread-Safe Ref-Count Implementation.
+ void AddRef();
+ void Release();
+};
+
+// RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
+// virtual AddRef and Release.
+
+class RefCountVImpl : virtual public RefCountImplCore
+{
+public:
+ // Thread-Safe Ref-Count Implementation.
+ virtual void AddRef();
+ virtual void Release();
+};
+
+
+// RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
+// which is slightly more efficient since it doesn't use atomics.
+
+class RefCountNTSImpl : public RefCountNTSImplCore
+{
+public:
+ OVR_FORCE_INLINE void AddRef() const
+ {
+ RefCount++;
+ }
+
+ void Release() const;
+};
+
+
+
+// RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
+// to the reference counting implementation. Base must be one of the RefCountImpl classes.
+
+template<class Base>
+class RefCountBaseStatImpl : public Base
+{
+public:
+ RefCountBaseStatImpl() { }
+
+ // *** Override New and Delete
+
+ // DOM-IGNORE-BEGIN
+ // Undef new temporarily if it is being redefined
+#ifdef OVR_DEFINE_NEW
+#undef new
+#endif
+
+#ifdef OVR_BUILD_DEBUG
+ // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
+ #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \
+ do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
+#else
+ #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
+#endif
+
+ // Redefine all new & delete operators.
+ OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
+
+#undef OVR_REFCOUNTALLOC_CHECK_DELETE
+
+#ifdef OVR_DEFINE_NEW
+#define new OVR_DEFINE_NEW
+#endif
+ // OVR_BUILD_DEFINE_NEW
+ // DOM-IGNORE-END
+};
+
+
+template<class Base>
+class RefCountBaseStatVImpl : virtual public Base
+{
+public:
+ RefCountBaseStatVImpl() { }
+
+ // *** Override New and Delete
+
+ // DOM-IGNORE-BEGIN
+ // Undef new temporarily if it is being redefined
+#ifdef OVR_DEFINE_NEW
+#undef new
+#endif
+
+#define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
+
+ // Redefine all new & delete operators.
+ OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
+
+#undef OVR_REFCOUNTALLOC_CHECK_DELETE
+
+#ifdef OVR_DEFINE_NEW
+#define new OVR_DEFINE_NEW
+#endif
+ // OVR_BUILD_DEFINE_NEW
+ // DOM-IGNORE-END
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// *** End user RefCountBase<> classes
+
+
+// RefCountBase is a base class for classes that require thread-safe reference
+// counting; it also overrides the new and delete operators to use MemoryHeap.
+//
+// Reference counted objects start out with RefCount value of 1. Further lifetime
+// management is done through the AddRef() and Release() methods, typically
+// hidden by Ptr<>.
+
+template<class C>
+class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
+{
+public:
+ // Constructor.
+ OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }
+};
+
+// RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
+
+template<class C>
+class RefCountBaseV : virtual public RefCountBaseStatVImpl<RefCountVImpl>
+{
+public:
+ // Constructor.
+ OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatVImpl<RefCountVImpl>() { }
+};
+
+
+// RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
+// counting; it also overrides the new and delete operators to use MemoryHeap.
+// This class should only be used if all pointers to it are known to be assigned,
+// destroyed and manipulated within one thread.
+//
+// Reference counted objects start out with RefCount value of 1. Further lifetime
+// management is done through the AddRef() and Release() methods, typically
+// hidden by Ptr<>.
+
+template<class C>
+class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
+{
+public:
+ // Constructor.
+ OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }
+};
+
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Ref-Counted template pointer
+//
+// Automatically AddRefs and Releases interfaces
+//
+// Note: Some of the member functions take C& as opposed to C* arguments:
+// Ptr(C&)
+// const Ptr<C>& operator= (C&)
+// Ptr<C>& SetPtr(C&)
+// These functions do not AddRef the assigned C& value, unlike the C* assignment
+// functions. Thus the purpose of these functions is for the Ptr instance to
+// assume ownership of a C reference count. Example usage:
+// Ptr<Widget> w = *new Widget; // Calls the Ptr(C&) constructor. Note that the Widget constructor sets initial refcount to 1.
+//
+
+template<class C>
+class Ptr
+{
+protected:
+ C *pObject;
+
+public:
+
+ // Constructors
+ OVR_FORCE_INLINE Ptr()
+ : pObject(0)
+ { }
+
+ // This constructor adopts the object's existing reference count rather than increment it.
+ OVR_FORCE_INLINE Ptr(C &robj)
+ : pObject(&robj)
+ { }
+
+ OVR_FORCE_INLINE Ptr(C *pobj)
+ {
+ if (pobj)
+ pobj->AddRef();
+ pObject = pobj;
+ }
+
+ OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
+ {
+ if (src.pObject)
+ src.pObject->AddRef();
+ pObject = src.pObject;
+ }
+
+ template<class R>
+ OVR_FORCE_INLINE Ptr(Ptr<R> &src)
+ {
+ if (src)
+ src->AddRef();
+ pObject = src;
+ }
+
+ // Destructor
+ OVR_FORCE_INLINE ~Ptr()
+ {
+ if (pObject)
+ pObject->Release();
+ }
+
+ // Compares
+ OVR_FORCE_INLINE bool operator == (const Ptr &other) const
+ {
+ return pObject == other.pObject;
+ }
+
+ OVR_FORCE_INLINE bool operator != (const Ptr &other) const
+ {
+ return pObject != other.pObject;
+ }
+
+ OVR_FORCE_INLINE bool operator == (C *pother) const
+ {
+ return pObject == pother;
+ }
+
+ OVR_FORCE_INLINE bool operator != (C *pother) const
+ {
+ return pObject != pother;
+ }
+
+ OVR_FORCE_INLINE bool operator < (const Ptr &other) const
+ {
+ return pObject < other.pObject;
+ }
+
+ // Assignment
+ template<class R>
+ OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
+ {
+ // By design we don't check for src == pObject, as we don't expect that to be the case the large majority of the time.
+ if (src)
+ src->AddRef();
+ if (pObject)
+ pObject->Release();
+ pObject = src;
+ return *this;
+ }
+
+ // Specialization
+ OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
+ {
+ if (src)
+ src->AddRef();
+ if (pObject)
+ pObject->Release();
+ pObject = src;
+ return *this;
+ }
+
+ OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
+ {
+ if (psrc)
+ psrc->AddRef();
+ if (pObject)
+ pObject->Release();
+ pObject = psrc;
+ return *this;
+ }
+
+ // This operator adopts the object's existing reference count rather than increment it.
+ OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
+ {
+ if (pObject)
+ pObject->Release();
+ pObject = &src;
+ return *this;
+ }
+
+ // Set Assignment
+ template<class R>
+ OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
+ {
+ if (src)
+ src->AddRef();
+ if (pObject)
+ pObject->Release();
+ pObject = src;
+ return *this;
+ }
+ // Specialization
+ OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
+ {
+ if (src)
+ src->AddRef();
+ if (pObject)
+ pObject->Release();
+ pObject = src;
+ return *this;
+ }
+
+ OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
+ {
+ if (psrc)
+ psrc->AddRef();
+ if (pObject)
+ pObject->Release();
+ pObject = psrc;
+ return *this;
+ }
+
+ // This function adopts the object's existing reference count rather than increment it.
+ OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
+ {
+ if (pObject)
+ pObject->Release();
+ pObject = &src;
+ return *this;
+ }
+
+ // Nulls ref-counted pointer without decrement
+ OVR_FORCE_INLINE void NullWithoutRelease()
+ {
+ pObject = 0;
+ }
+
+ // Clears the pointer to the object
+ OVR_FORCE_INLINE void Clear()
+ {
+ if (pObject)
+ pObject->Release();
+ pObject = 0;
+ }
+
+ // Obtain pointer reference directly, for D3D interfaces
+ OVR_FORCE_INLINE C*& GetRawRef()
+ {
+ return pObject;
+ }
+
+ // Access Operators
+ OVR_FORCE_INLINE C* GetPtr() const
+ {
+ return pObject;
+ }
+
+ OVR_FORCE_INLINE C& operator * () const
+ {
+ return *pObject;
+ }
+
+ OVR_FORCE_INLINE C* operator -> () const
+ {
+ return pObject;
+ }
+
+ // Conversion
+ OVR_FORCE_INLINE operator C* () const
+ {
+ return pObject;
+ }
+
+};
+
+} // OVR
+
+#endif