summaryrefslogtreecommitdiffstats
path: root/source/core/slang-smart-pointer.h
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2024-10-29 14:49:26 +0800
committerGitHub <noreply@github.com>2024-10-29 14:49:26 +0800
commitf65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch)
treeea1d61342cd29368e19135000ec2948813096205 /source/core/slang-smart-pointer.h
parenta729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff)
format
* format * Minor test fixes * enable checking cpp format in ci
Diffstat (limited to 'source/core/slang-smart-pointer.h')
-rw-r--r--source/core/slang-smart-pointer.h518
1 files changed, 250 insertions, 268 deletions
diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h
index a45f7a8ad..46070f0b8 100644
--- a/source/core/slang-smart-pointer.h
+++ b/source/core/slang-smart-pointer.h
@@ -6,118 +6,124 @@
#include "slang-type-traits.h"
#include "slang.h"
-#include "slang.h"
-
namespace Slang
{
- // Base class for all reference-counted objects
- class SLANG_RT_API RefObject
+// Base class for all reference-counted objects
+class SLANG_RT_API RefObject
+{
+private:
+ UInt referenceCount;
+
+public:
+ RefObject()
+ : referenceCount(0)
{
- private:
- UInt referenceCount;
+ }
- public:
- RefObject()
- : referenceCount(0)
- {}
+ RefObject(const RefObject&)
+ : referenceCount(0)
+ {
+ }
- RefObject(const RefObject &)
- : referenceCount(0)
- {}
+ RefObject& operator=(const RefObject&) { return *this; }
- RefObject& operator=(const RefObject&) { return *this; }
+ virtual ~RefObject() {}
- virtual ~RefObject()
- {}
+ UInt addReference() { return ++referenceCount; }
- UInt addReference()
- {
- return ++referenceCount;
- }
+ UInt decreaseReference() { return --referenceCount; }
- UInt decreaseReference()
+ UInt releaseReference()
+ {
+ SLANG_ASSERT(referenceCount != 0);
+ if (--referenceCount == 0)
{
- return --referenceCount;
+ delete this;
+ return 0;
}
+ return referenceCount;
+ }
- UInt releaseReference()
- {
- SLANG_ASSERT(referenceCount != 0);
- if(--referenceCount == 0)
- {
- delete this;
- return 0;
- }
- return referenceCount;
- }
+ bool isUniquelyReferenced()
+ {
+ SLANG_ASSERT(referenceCount != 0);
+ return referenceCount == 1;
+ }
- bool isUniquelyReferenced()
- {
- SLANG_ASSERT(referenceCount != 0);
- return referenceCount == 1;
- }
+ UInt debugGetReferenceCount() { return referenceCount; }
+};
- UInt debugGetReferenceCount()
- {
- return referenceCount;
- }
- };
+SLANG_FORCE_INLINE void addReference(RefObject* obj)
+{
+ if (obj)
+ obj->addReference();
+}
- SLANG_FORCE_INLINE void addReference(RefObject* obj)
+SLANG_FORCE_INLINE void releaseReference(RefObject* obj)
+{
+ if (obj)
+ obj->releaseReference();
+}
+
+// For straight dynamic cast.
+// Use instead of dynamic_cast as it allows for replacement without using Rtti in the future
+template<typename T>
+SLANG_FORCE_INLINE T* dynamicCast(RefObject* obj)
+{
+ return dynamic_cast<T*>(obj);
+}
+template<typename T>
+SLANG_FORCE_INLINE const T* dynamicCast(const RefObject* obj)
+{
+ return dynamic_cast<const T*>(obj);
+}
+
+// Like a dynamicCast, but allows a type to implement a specific implementation that is suitable for
+// it
+template<typename T>
+SLANG_FORCE_INLINE T* as(RefObject* obj)
+{
+ return dynamicCast<T>(obj);
+}
+template<typename T>
+SLANG_FORCE_INLINE const T* as(const RefObject* obj)
+{
+ return dynamicCast<T>(obj);
+}
+
+// "Smart" pointer to a reference-counted object
+template<typename T>
+struct SLANG_RT_API RefPtr
+{
+ RefPtr()
+ : pointer(nullptr)
{
- if(obj) obj->addReference();
}
- SLANG_FORCE_INLINE void releaseReference(RefObject* obj)
+ RefPtr(T* p)
+ : pointer(p)
{
- if(obj) obj->releaseReference();
+ addReference(p);
}
- // For straight dynamic cast.
- // Use instead of dynamic_cast as it allows for replacement without using Rtti in the future
- template <typename T>
- SLANG_FORCE_INLINE T* dynamicCast(RefObject* obj) { return dynamic_cast<T*>(obj); }
- template <typename T>
- SLANG_FORCE_INLINE const T* dynamicCast(const RefObject* obj) { return dynamic_cast<const T*>(obj); }
-
- // Like a dynamicCast, but allows a type to implement a specific implementation that is suitable for it
- template <typename T>
- SLANG_FORCE_INLINE T* as(RefObject* obj) { return dynamicCast<T>(obj); }
- template <typename T>
- SLANG_FORCE_INLINE const T* as(const RefObject* obj) { return dynamicCast<T>(obj); }
-
- // "Smart" pointer to a reference-counted object
- template<typename T> struct SLANG_RT_API RefPtr
+ RefPtr(RefPtr<T> const& p)
+ : pointer(p.pointer)
{
- RefPtr()
- : pointer(nullptr)
- {}
-
- RefPtr(T* p)
- : pointer(p)
- {
- addReference(p);
- }
-
- RefPtr(RefPtr<T> const& p)
- : pointer(p.pointer)
- {
- addReference(p.pointer);
- }
+ addReference(p.pointer);
+ }
- RefPtr(RefPtr<T>&& p)
- : pointer(p.pointer)
- {
- p.pointer = nullptr;
- }
+ RefPtr(RefPtr<T>&& p)
+ : pointer(p.pointer)
+ {
+ p.pointer = nullptr;
+ }
- template <typename U>
- RefPtr(RefPtr<U> const& p,
- typename EnableIf<IsConvertible<T*, U*>::Value, void>::type * = 0)
- : pointer(static_cast<U*>(p))
- {
- addReference(static_cast<U*>(p));
- }
+ template<typename U>
+ RefPtr(RefPtr<U> const& p, typename EnableIf<IsConvertible<T*, U*>::Value, void>::type* = 0)
+ : pointer(static_cast<U*>(p))
+ {
+ addReference(static_cast<U*>(p));
+ }
#if 0
void operator=(T* p)
@@ -129,226 +135,202 @@ namespace Slang
}
#endif
- void operator=(RefPtr<T> const& p)
- {
- T* old = pointer;
- addReference(p.pointer);
- pointer = p.pointer;
- releaseReference(old);
- }
+ void operator=(RefPtr<T> const& p)
+ {
+ T* old = pointer;
+ addReference(p.pointer);
+ pointer = p.pointer;
+ releaseReference(old);
+ }
- void operator=(RefPtr<T>&& p)
- {
- T* old = pointer;
- pointer = p.pointer;
- p.pointer = old;
- }
+ void operator=(RefPtr<T>&& p)
+ {
+ T* old = pointer;
+ pointer = p.pointer;
+ p.pointer = old;
+ }
- template <typename U>
- typename EnableIf<IsConvertible<T*, U*>::value, void>::type
- operator=(RefPtr<U> const& p)
- {
- T* old = pointer;
- addReference(p.pointer);
- pointer = p.pointer;
- releaseReference(old);
- }
+ template<typename U>
+ typename EnableIf<IsConvertible<T*, U*>::value, void>::type operator=(RefPtr<U> const& p)
+ {
+ T* old = pointer;
+ addReference(p.pointer);
+ pointer = p.pointer;
+ releaseReference(old);
+ }
- HashCode getHashCode() const
- {
- // Note: We need a `RefPtr<T>` to hash the same as a `T*`,
- // so that a `T*` can be used as a key in a dictionary with
- // `RefPtr<T>` keys, and vice versa.
- //
- return Slang::getHashCode(pointer);
- }
+ HashCode getHashCode() const
+ {
+ // Note: We need a `RefPtr<T>` to hash the same as a `T*`,
+ // so that a `T*` can be used as a key in a dictionary with
+ // `RefPtr<T>` keys, and vice versa.
+ //
+ return Slang::getHashCode(pointer);
+ }
- bool operator==(const T * ptr) const
- {
- return pointer == ptr;
- }
+ bool operator==(const T* ptr) const { return pointer == ptr; }
- bool operator!=(const T * ptr) const
- {
- return pointer != ptr;
- }
+ bool operator!=(const T* ptr) const { return pointer != ptr; }
- bool operator==(RefPtr<T> const& ptr) const
- {
- return pointer == ptr.pointer;
- }
+ bool operator==(RefPtr<T> const& ptr) const { return pointer == ptr.pointer; }
- bool operator!=(RefPtr<T> const& ptr) const
- {
- return pointer != ptr.pointer;
- }
+ bool operator!=(RefPtr<T> const& ptr) const { return pointer != ptr.pointer; }
- template<typename U>
- RefPtr<U> dynamicCast() const
- {
- return RefPtr<U>(Slang::dynamicCast<U>(pointer));
- }
+ template<typename U>
+ RefPtr<U> dynamicCast() const
+ {
+ return RefPtr<U>(Slang::dynamicCast<U>(pointer));
+ }
- template<typename U>
- RefPtr<U> as() const
- {
- return RefPtr<U>(Slang::as<U>(pointer));
- }
+ template<typename U>
+ RefPtr<U> as() const
+ {
+ return RefPtr<U>(Slang::as<U>(pointer));
+ }
- template <typename U>
- bool is() const { return Slang::as<U>(pointer) != nullptr; }
+ template<typename U>
+ bool is() const
+ {
+ return Slang::as<U>(pointer) != nullptr;
+ }
- ~RefPtr()
- {
- releaseReference(static_cast<Slang::RefObject*>(pointer));
- }
+ ~RefPtr() { releaseReference(static_cast<Slang::RefObject*>(pointer)); }
- T& operator*() const
- {
- return *pointer;
- }
+ T& operator*() const { return *pointer; }
- T* operator->() const
- {
- return pointer;
- }
+ T* operator->() const { return pointer; }
- T * Ptr() const
- {
- return pointer;
- }
+ T* Ptr() const { return pointer; }
- T* get() const
- {
- return pointer;
- }
+ T* get() const { return pointer; }
- operator T*() const
- {
- return pointer;
- }
+ operator T*() const { return pointer; }
- void attach(T* p)
- {
- T* old = pointer;
- pointer = p;
- releaseReference(old);
- }
+ void attach(T* p)
+ {
+ T* old = pointer;
+ pointer = p;
+ releaseReference(old);
+ }
- T* detach()
- {
- auto rs = pointer;
- pointer = nullptr;
- return rs;
- }
+ T* detach()
+ {
+ auto rs = pointer;
+ pointer = nullptr;
+ return rs;
+ }
- void swapWith(RefPtr<T>& rhs)
- {
- auto rhsPtr = rhs.pointer;
- rhs.pointer = pointer;
- pointer = rhsPtr;
- }
+ void swapWith(RefPtr<T>& rhs)
+ {
+ auto rhsPtr = rhs.pointer;
+ rhs.pointer = pointer;
+ pointer = rhsPtr;
+ }
- SLANG_FORCE_INLINE void setNull()
- {
- releaseReference(pointer);
- pointer = nullptr;
- }
+ SLANG_FORCE_INLINE void setNull()
+ {
+ releaseReference(pointer);
+ pointer = nullptr;
+ }
- /// Get ready for writing (nulls contents)
- SLANG_FORCE_INLINE T** writeRef() { *this = nullptr; return &pointer; }
+ /// Get ready for writing (nulls contents)
+ SLANG_FORCE_INLINE T** writeRef()
+ {
+ *this = nullptr;
+ return &pointer;
+ }
- /// Get for read access
- SLANG_FORCE_INLINE T*const* readRef() const { return &pointer; }
+ /// Get for read access
+ SLANG_FORCE_INLINE T* const* readRef() const { return &pointer; }
- private:
- T* pointer;
- };
+private:
+ T* pointer;
+};
- // Helper type for implementing weak pointers. The object being pointed at weakly creates a WeakSink object
- // that other objects can reference and share. When the object is destroyed it detaches the sink
- // doing so will make other users call to 'get' return null. Thus any user of the WeakSink, must check if the weakly pointed to
- // things pointer is nullptr before using.
- template <typename T>
- class WeakSink : public RefObject
+// Helper type for implementing weak pointers. The object being pointed at weakly creates a WeakSink
+// object that other objects can reference and share. When the object is destroyed it detaches the
+// sink doing so will make other users call to 'get' return null. Thus any user of the WeakSink,
+// must check if the weakly pointed to things pointer is nullptr before using.
+template<typename T>
+class WeakSink : public RefObject
+{
+public:
+ WeakSink(T* ptr)
+ : m_ptr(ptr)
{
- public:
- WeakSink(T* ptr):
- m_ptr(ptr)
- {
- }
+ }
- SLANG_FORCE_INLINE T* get() const { return m_ptr; }
- SLANG_FORCE_INLINE void detach() { m_ptr = nullptr; }
+ SLANG_FORCE_INLINE T* get() const { return m_ptr; }
+ SLANG_FORCE_INLINE void detach() { m_ptr = nullptr; }
- private:
- T* m_ptr;
- };
+private:
+ T* m_ptr;
+};
- // A pointer that can be transformed to hold either a weak reference or a strong reference.
- template<typename T>
- class TransformablePtr
- {
- private:
- T* m_weakPtr = nullptr;
- RefPtr<T> m_strongPtr;
+// A pointer that can be transformed to hold either a weak reference or a strong reference.
+template<typename T>
+class TransformablePtr
+{
+private:
+ T* m_weakPtr = nullptr;
+ RefPtr<T> m_strongPtr;
- public:
- TransformablePtr() = default;
- TransformablePtr(T* ptr) { *this = ptr; }
- TransformablePtr(RefPtr<T> ptr) { *this = ptr; }
- TransformablePtr(const TransformablePtr<T>& ptr) = default;
- TransformablePtr<T>& operator=(const TransformablePtr<T>& ptr) = default;
+public:
+ TransformablePtr() = default;
+ TransformablePtr(T* ptr) { *this = ptr; }
+ TransformablePtr(RefPtr<T> ptr) { *this = ptr; }
+ TransformablePtr(const TransformablePtr<T>& ptr) = default;
+ TransformablePtr<T>& operator=(const TransformablePtr<T>& ptr) = default;
- void promoteToStrongReference() { m_strongPtr = m_weakPtr; }
- void demoteToWeakReference() { m_strongPtr = nullptr; }
- bool isStrongReference() const { return m_strongPtr != nullptr; }
+ void promoteToStrongReference() { m_strongPtr = m_weakPtr; }
+ void demoteToWeakReference() { m_strongPtr = nullptr; }
+ bool isStrongReference() const { return m_strongPtr != nullptr; }
- T& operator*() const { return *m_weakPtr; }
+ T& operator*() const { return *m_weakPtr; }
- T* operator->() const { return m_weakPtr; }
+ T* operator->() const { return m_weakPtr; }
- T* Ptr() const { return m_weakPtr; }
- T* get() const { return m_weakPtr; }
+ T* Ptr() const { return m_weakPtr; }
+ T* get() const { return m_weakPtr; }
- operator T*() const { return m_weakPtr; }
- operator RefPtr<T>() const { return m_weakPtr; }
+ operator T*() const { return m_weakPtr; }
+ operator RefPtr<T>() const { return m_weakPtr; }
- TransformablePtr<T>& operator=(T* ptr)
- {
- m_weakPtr = ptr;
- m_strongPtr = ptr;
- return *this;
- }
- template<typename U>
- TransformablePtr<T>& operator=(const RefPtr<U>& ptr)
- {
- m_weakPtr = ptr.Ptr();
- m_strongPtr = ptr;
- return *this;
- }
-
- HashCode getHashCode() const
- {
- // Note: We need a `RefPtr<T>` to hash the same as a `T*`,
- // so that a `T*` can be used as a key in a dictionary with
- // `RefPtr<T>` keys, and vice versa.
- //
- return Slang::getHashCode(m_weakPtr);
- }
+ TransformablePtr<T>& operator=(T* ptr)
+ {
+ m_weakPtr = ptr;
+ m_strongPtr = ptr;
+ return *this;
+ }
+ template<typename U>
+ TransformablePtr<T>& operator=(const RefPtr<U>& ptr)
+ {
+ m_weakPtr = ptr.Ptr();
+ m_strongPtr = ptr;
+ return *this;
+ }
- bool operator==(const T* ptr) const { return m_weakPtr == ptr; }
+ HashCode getHashCode() const
+ {
+ // Note: We need a `RefPtr<T>` to hash the same as a `T*`,
+ // so that a `T*` can be used as a key in a dictionary with
+ // `RefPtr<T>` keys, and vice versa.
+ //
+ return Slang::getHashCode(m_weakPtr);
+ }
- bool operator!=(const T* ptr) const { return m_weakPtr != ptr; }
+ bool operator==(const T* ptr) const { return m_weakPtr == ptr; }
- bool operator==(RefPtr<T> const& ptr) const { return m_weakPtr == ptr.Ptr(); }
+ bool operator!=(const T* ptr) const { return m_weakPtr != ptr; }
- bool operator!=(RefPtr<T> const& ptr) const { return m_weakPtr != ptr.Ptr(); }
+ bool operator==(RefPtr<T> const& ptr) const { return m_weakPtr == ptr.Ptr(); }
- bool operator==(TransformablePtr<T> const& ptr) const { return m_weakPtr == ptr.m_weakPtr; }
+ bool operator!=(RefPtr<T> const& ptr) const { return m_weakPtr != ptr.Ptr(); }
- bool operator!=(TransformablePtr<T> const& ptr) const { return m_weakPtr != ptr.m_weakPtr; }
- };
-}
+ bool operator==(TransformablePtr<T> const& ptr) const { return m_weakPtr == ptr.m_weakPtr; }
+
+ bool operator!=(TransformablePtr<T> const& ptr) const { return m_weakPtr != ptr.m_weakPtr; }
+};
+} // namespace Slang
#endif