summaryrefslogtreecommitdiffstats
path: root/source/core/slang-smart-pointer.h
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-05-31 17:20:37 -0400
committerGitHub <noreply@github.com>2019-05-31 17:20:37 -0400
commit6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f (patch)
tree5a23cb47782e9e2a77762c90dd35da1005eba8d0 /source/core/slang-smart-pointer.h
parentb81ff3ef968d1cc4e954b31a1812b3c391d17b02 (diff)
Use slang- prefix on slang compiler and core source (#973)
* Prefixing source files in source/slang with slang- * Prefix source in source/slang with slang- prefix. * Rename core source files with slang- prefix. * Update project files. * Fix problems from automatic merge.
Diffstat (limited to 'source/core/slang-smart-pointer.h')
-rw-r--r--source/core/slang-smart-pointer.h250
1 files changed, 250 insertions, 0 deletions
diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h
new file mode 100644
index 000000000..bae30de37
--- /dev/null
+++ b/source/core/slang-smart-pointer.h
@@ -0,0 +1,250 @@
+#ifndef SLANG_CORE_SMART_POINTER_H
+#define SLANG_CORE_SMART_POINTER_H
+
+#include "slang-common.h"
+#include "slang-hash.h"
+#include "slang-type-traits.h"
+
+#include "../../slang.h"
+
+namespace Slang
+{
+ // Base class for all reference-counted objects
+ class RefObject
+ {
+ private:
+ UInt referenceCount;
+
+ public:
+ RefObject()
+ : referenceCount(0)
+ {}
+
+ RefObject(const RefObject &)
+ : referenceCount(0)
+ {}
+
+ virtual ~RefObject()
+ {}
+
+ UInt addReference()
+ {
+ return ++referenceCount;
+ }
+
+ UInt decreaseReference()
+ {
+ 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;
+ }
+
+ UInt debugGetReferenceCount()
+ {
+ return referenceCount;
+ }
+ };
+
+ SLANG_FORCE_INLINE void addReference(RefObject* obj)
+ {
+ if(obj) obj->addReference();
+ }
+
+ 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 RefPtr
+ {
+ RefPtr()
+ : pointer(nullptr)
+ {}
+
+ RefPtr(T* p)
+ : pointer(p)
+ {
+ addReference(p);
+ }
+
+ RefPtr(RefPtr<T> const& p)
+ : pointer(p.pointer)
+ {
+ addReference(p.pointer);
+ }
+
+ 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((U*) p)
+ {
+ addReference((U*) p);
+ }
+
+#if 0
+ void operator=(T* p)
+ {
+ T* old = pointer;
+ addReference(p);
+ pointer = p;
+ releaseReference(old);
+ }
+#endif
+
+ 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;
+ }
+
+ 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);
+ }
+
+ int GetHashCode()
+ {
+ // 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==(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> as() const
+ {
+ return RefPtr<U>(Slang::as<U>(pointer));
+ }
+
+ template <typename U>
+ bool is() const { return Slang::as<U>(pointer) != nullptr; }
+
+ ~RefPtr()
+ {
+ releaseReference((Slang::RefObject*) pointer);
+ }
+
+ T& operator*() const
+ {
+ return *pointer;
+ }
+
+ T* operator->() const
+ {
+ return pointer;
+ }
+
+ T * Ptr() const
+ {
+ return pointer;
+ }
+
+ operator T*() const
+ {
+ return pointer;
+ }
+
+ void attach(T* p)
+ {
+ T* old = pointer;
+ pointer = p;
+ releaseReference(old);
+ }
+
+ T* detach()
+ {
+ auto rs = pointer;
+ pointer = nullptr;
+ return rs;
+ }
+
+ /// 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; }
+
+ private:
+ T* pointer;
+
+ };
+}
+
+#endif