summaryrefslogtreecommitdiffhomepage
path: root/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_RefCount.h
diff options
context:
space:
mode:
Diffstat (limited to 'ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_RefCount.h')
-rw-r--r--ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_RefCount.h495
1 files changed, 495 insertions, 0 deletions
diff --git a/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_RefCount.h b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_RefCount.h
new file mode 100644
index 0000000..452cdf1
--- /dev/null
+++ b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_RefCount.h
@@ -0,0 +1,495 @@
+/************************************************************************************
+
+PublicHeader: Kernel
+Filename : OVR_RefCount.h
+Content : Reference counting implementation headers
+Created : September 19, 2012
+Notes :
+
+Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
+
+Licensed under the Oculus Master SDK License Version 1.0 (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
+
+https://developer.oculus.com/licenses/oculusmastersdk-1.0
+
+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_Allocator.h"
+#include "OVR_Types.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:
+ std::atomic<int> RefCount = {1};
+
+ public:
+ // RefCountImpl constructor always initializes RefCount to 1 by default.
+ OVR_FORCE_INLINE RefCountImplCore() {}
+
+ // 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;
+ }
+};
+
+// LockedPtr
+//
+// Helper class to simplify thread-safety of the TrackingManager.
+// It wraps the Ptr<> object it contains in a Lock.
+template <class T>
+class LockedPtr {
+ public:
+ LockedPtr(Lock* lock = nullptr) : TheLock(lock) {}
+
+ void Set(T* value) {
+ OVR_ASSERT(TheLock);
+ TheLock->DoLock();
+ Ptr<T> oldPtr = ThePtr; // Keep a reference to the old ptr
+ ThePtr = value; // Change/decrement the old ptr (cannot die here due to oldPtr)
+ TheLock->Unlock();
+
+ // Release the old Ptr reference here, outside of the lock
+ // so that the object will not die while TheLock is held.
+ }
+
+ template <class S>
+ void Get(Ptr<S>& outputPtr) const {
+ OVR_ASSERT(TheLock);
+ TheLock->DoLock();
+ Ptr<T> retval = ThePtr;
+ TheLock->Unlock();
+ outputPtr = retval;
+ }
+
+ protected:
+ mutable Lock* TheLock;
+ Ptr<T> ThePtr;
+};
+
+} // namespace OVR
+
+#endif