From 6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Fri, 31 May 2019 17:20:37 -0400 Subject: 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. --- source/core/slang-smart-pointer.h | 250 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 source/core/slang-smart-pointer.h (limited to 'source/core/slang-smart-pointer.h') 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 + SLANG_FORCE_INLINE T* dynamicCast(RefObject* obj) { return dynamic_cast(obj); } + template + SLANG_FORCE_INLINE const T* dynamicCast(const RefObject* obj) { return dynamic_cast(obj); } + + // Like a dynamicCast, but allows a type to implement a specific implementation that is suitable for it + template + SLANG_FORCE_INLINE T* as(RefObject* obj) { return dynamicCast(obj); } + template + SLANG_FORCE_INLINE const T* as(const RefObject* obj) { return dynamicCast(obj); } + + // "Smart" pointer to a reference-counted object + template + struct RefPtr + { + RefPtr() + : pointer(nullptr) + {} + + RefPtr(T* p) + : pointer(p) + { + addReference(p); + } + + RefPtr(RefPtr const& p) + : pointer(p.pointer) + { + addReference(p.pointer); + } + + RefPtr(RefPtr&& p) + : pointer(p.pointer) + { + p.pointer = nullptr; + } + + template + RefPtr(RefPtr const& p, + typename EnableIf::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 const& p) + { + T* old = pointer; + addReference(p.pointer); + pointer = p.pointer; + releaseReference(old); + } + + void operator=(RefPtr&& p) + { + T* old = pointer; + pointer = p.pointer; + p.pointer = old; + } + + template + typename EnableIf::value, void>::type + operator=(RefPtr const& p) + { + T* old = pointer; + addReference(p.pointer); + pointer = p.pointer; + releaseReference(old); + } + + int GetHashCode() + { + // Note: We need a `RefPtr` to hash the same as a `T*`, + // so that a `T*` can be used as a key in a dictionary with + // `RefPtr` 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 const& ptr) const + { + return pointer == ptr.pointer; + } + + bool operator!=(RefPtr const& ptr) const + { + return pointer != ptr.pointer; + } + + template + RefPtr dynamicCast() const + { + return RefPtr(Slang::dynamicCast(pointer)); + } + + template + RefPtr as() const + { + return RefPtr(Slang::as(pointer)); + } + + template + bool is() const { return Slang::as(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 -- cgit v1.2.3