diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-05-31 17:20:37 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-31 17:20:37 -0400 |
| commit | 6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f (patch) | |
| tree | 5a23cb47782e9e2a77762c90dd35da1005eba8d0 /source/core/slang-smart-pointer.h | |
| parent | b81ff3ef968d1cc4e954b31a1812b3c391d17b02 (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.h | 250 |
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 |
