diff options
Diffstat (limited to 'source/core/smart-pointer.h')
| -rw-r--r-- | source/core/smart-pointer.h | 593 |
1 files changed, 161 insertions, 432 deletions
diff --git a/source/core/smart-pointer.h b/source/core/smart-pointer.h index d307e4e13..c31cdefe0 100644 --- a/source/core/smart-pointer.h +++ b/source/core/smart-pointer.h @@ -3,462 +3,191 @@ #include "type-traits.h" +#include <assert.h> + namespace Slang { - class RefPtrDefaultDestructor - { - public: - template<typename T> - void operator ()(T * ptr) - { - delete ptr; - } - }; - - class RefPtrArrayDestructor - { - public: - template<typename T> - void operator() (T * ptr) - { - delete [] ptr; - } - }; + // TODO: Need to centralize these typedefs + typedef uintptr_t UInt; + + // Base class for all reference-counted objects + class RefObject + { + private: + UInt referenceCount; + + public: + RefObject() + : referenceCount(0) + {} + + RefObject(const RefObject &) + : referenceCount(0) + {} + + virtual ~RefObject() + {} + + void addReference() + { + referenceCount++; + } + + void releaseReference() + { + assert(referenceCount != 0); + if(--referenceCount == 0) + { + delete this; + } + } + + bool isUniquelyReferenced() + { + assert(referenceCount != 0); + return referenceCount == 1; + } + }; + + inline void addReference(RefObject* obj) + { + if(obj) obj->addReference(); + } + + inline void releaseReference(RefObject* obj) + { + if(obj) obj->releaseReference(); + } + + // "Smart" pointer to a reference-counted object + template<typename T> + struct RefPtr + { + RefPtr() + : pointer(0) + {} + + 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 = 0; + } + + 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& ptr) + { + T* old = pointer; + addReference(p.pointer); + pointer = p.pointer; + releaseReference(old); + } - class ReferenceCounted - { - template<typename T, bool b, typename Destructor> - friend class RefPtrImpl; - private: - int _refCount = 0; - public: - ReferenceCounted() {} - ReferenceCounted(const ReferenceCounted &) + int GetHashCode() { - _refCount = 0; + return (int)(long long)(void*)pointer; } - }; - - class RefObject : public ReferenceCounted - { - public: - virtual ~RefObject() - {} - }; + bool operator==(const T * ptr) const + { + return pointer == ptr; + } - template<typename T, bool HasBuiltInCounter, typename Destructor> - class RefPtrImpl - { - }; + bool operator!=(const T * ptr) const + { + return pointer != ptr; + } - template<typename T, typename Destructor = RefPtrDefaultDestructor> - using RefPtr = RefPtrImpl<T, IsBaseOf<ReferenceCounted, T>::Value, Destructor>; - - template<typename T, typename Destructor> - class RefPtrImpl<T, 0, Destructor> - { - template<typename T1, bool b, typename Destructor1> - friend class RefPtrImpl; - private: - T * pointer; - int * refCount; - - public: - RefPtrImpl() - { - pointer = 0; - refCount = 0; - } - RefPtrImpl(T * ptr) - : pointer(0), refCount(0) + bool operator==(RefPtr<T> const& ptr) const { - this->operator=(ptr); - } - RefPtrImpl(const RefPtrImpl<T, 0, Destructor> & ptr) - : pointer(0), refCount(0) - { - this->operator=(ptr); - } - RefPtrImpl(RefPtrImpl<T, 0, Destructor> && str) - : pointer(0), refCount(0) - { - this->operator=(static_cast<RefPtrImpl<T, 0, Destructor> &&>(str)); + return pointer == ptr.pointer; } - template <typename U> - RefPtrImpl(const RefPtrImpl<U, 0, Destructor>& ptr, - typename EnableIf<IsConvertible<T*, U*>::Value, void>::type * = 0) - : pointer(0), refCount(0) + bool operator!=(RefPtr<T> const& ptr) const { - pointer = ptr.pointer; - if (ptr) - { - refCount = ptr.refCount; - (*refCount)++; - } - else - refCount = 0; + return pointer != ptr.pointer; } - template <typename U> - typename EnableIf<IsConvertible<T*, U*>::value, RefPtrImpl<T, 0, Destructor>>::type& - operator=(const RefPtrImpl<U,0,Destructor> & ptr) - { - Unreference(); - - pointer = ptr; - if (ptr) - { - refCount = ptr.refCount; - (*refCount)++; - } - else - refCount = 0; - return *this; - } + template<typename U> + RefPtr<U> As() const + { + RefPtr<U> result(dynamic_cast<U*>(pointer)); + return result; + } - RefPtrImpl<T, 0, Destructor>& operator=(const RefPtrImpl<T, 0, Destructor> & ptr) - { - Unreference(); - pointer = ptr.pointer; - if (ptr) - { - refCount = ptr.refCount; - (*refCount)++; - } - else - refCount = 0; - return *this; - } + ~RefPtr() + { + releaseReference(pointer); + } - RefPtrImpl<T, 0, Destructor>& operator=(T * ptr) - { - if (ptr != pointer) - { - Unreference(); - - pointer = ptr; - if (ptr) - { - refCount = new int; - (*refCount) = 1; - } - else - refCount = 0; - } - return *this; - } - int GetHashCode() - { - return (int)(long long)(void*)pointer; - } - bool operator == (const T * ptr) const - { - return pointer == ptr; - } - bool operator != (const T * ptr) const - { - return pointer != ptr; - } - template<typename U> - bool operator == (const RefPtr<U, Destructor> & ptr) const - { - return pointer == ptr.pointer; - } - template<typename U> - bool operator != (const RefPtr<U, Destructor> & ptr) const - { - return pointer != ptr.pointer; - } - template<typename U> - RefPtrImpl<U, 0, Destructor> As() const - { - RefPtrImpl<U, 0, Destructor> result; - if (pointer) - { - result.pointer = dynamic_cast<U*>(pointer); - if (result.pointer) - { - result.refCount = refCount; - (*refCount)++; - } - } - return result; - } + T& operator*() const + { + return *pointer; + } - T* operator +(int offset) const - { - return pointer+offset; - } - T& operator [](int idx) const - { - return *(pointer + idx); - } - RefPtrImpl<T, 0, Destructor>& operator=(RefPtrImpl<T, 0, Destructor> && ptr) - { - if(ptr.pointer != pointer) - { - Unreference(); - pointer = ptr.pointer; - refCount = ptr.refCount; - ptr.pointer = 0; - ptr.refCount = 0; - } - return *this; - } - T* Release() - { - if(pointer) - { - if((*refCount) > 1) - { - (*refCount)--; - } - else - { - delete refCount; - } - } - auto rs = pointer; - refCount = 0; - pointer = 0; - return rs; - } - ~RefPtrImpl() - { - Unreference(); - } + T* operator->() const + { + return pointer; + } - void Unreference() - { - if(pointer) - { - if((*refCount) > 1) - { - (*refCount)--; - } - else - { - Destructor destructor; - destructor(pointer); - delete refCount; - } - } - } - T & operator *() const - { - return *pointer; - } - T * operator->() const - { - return pointer; - } T * Ptr() const { return pointer; } - public: - explicit operator bool() const - { - if (pointer) - return true; - else - return false; - } - }; - - - template<typename T, typename Destructor> - class RefPtrImpl<T, 1, Destructor> - { - template<typename T1, bool b, typename Destructor1> - friend class RefPtrImpl; - - private: - T * pointer; - public: - RefPtrImpl() - { - pointer = 0; - } - RefPtrImpl(T * ptr) - : pointer(0) - { - this->operator=(ptr); - } - RefPtrImpl(const RefPtrImpl<T, 1, Destructor> & ptr) - : pointer(0) - { - this->operator=(ptr); - } - RefPtrImpl(RefPtrImpl<T, 1, Destructor> && str) - : pointer(0) - { - this->operator=(static_cast<RefPtrImpl<T, 1, Destructor> &&>(str)); - } - template <typename U> - RefPtrImpl(const RefPtrImpl<U, 1, Destructor>& ptr, - typename EnableIf<IsConvertible<T*, U*>::Value, void>::type * = 0) - : pointer(0) - { - pointer = ptr.pointer; - if (ptr) - { - ptr->_refCount++; - } - } - template <typename U> - typename EnableIf<IsConvertible<T*, U*>::value, RefPtrImpl<T, 1, Destructor>&>::type - operator=(const RefPtrImpl<U, 1, Destructor> & ptr) - { - Unreference(); - - pointer = ptr.pointer; - if (ptr) - { - ptr->_refCount++; - } - return *this; - } - RefPtrImpl<T, 1, Destructor>& operator=(T * ptr) - { - if (ptr != pointer) - { - Unreference(); - - pointer = ptr; - if (ptr) - { - ptr->_refCount++; - } - } - return *this; - } - RefPtrImpl<T, 1, Destructor>& operator=(const RefPtrImpl<T, 1, Destructor> & ptr) - { - // Note: It is possible that the object this pointer references owns - // (directly or indirectly) the storage for the argument `ptr`. If - // that is the case and the `Unreference()` call below frees this - // object, then the argument would become invalid. - // - // We copy the pointer value out of the argument first, in order - // to protected against this case. - T* ptrPointer = ptr.pointer; - if (ptrPointer != pointer) - { - if (ptrPointer) - ptrPointer->_refCount++; - Unreference(); - pointer = ptrPointer; - } - return *this; - } - int GetHashCode() - { - return (int)(long long)(void*)pointer; - } - bool operator == (const T * ptr) const - { - return pointer == ptr; - } - bool operator != (const T * ptr) const - { - return pointer != ptr; - } - template<typename U> - bool operator == (const RefPtr<U, Destructor> & ptr) const - { - return pointer == ptr.pointer; - } - template<typename U> - bool operator != (const RefPtr<U, Destructor> & ptr) const - { - return pointer != ptr.pointer; - } - template<typename U> - RefPtrImpl<U, 1, Destructor> As() const - { - RefPtrImpl<U, 1, Destructor> result; - if (pointer) - { - result.pointer = dynamic_cast<U*>(pointer); - if (result.pointer) - { - result.pointer->_refCount++; - } - } - return result; - } - T* operator +(int offset) const - { - return pointer + offset; - } - T& operator [](int idx) const - { - return *(pointer + idx); - } - RefPtrImpl<T, 1, Destructor>& operator=(RefPtrImpl<T, 1, Destructor> && ptr) - { - if (ptr.pointer != pointer) - { - Unreference(); - pointer = ptr.pointer; - ptr.pointer = nullptr; - } - return *this; - } - T* Release() - { - if (pointer) - { - pointer->_refCount--; - } - auto rs = pointer; - pointer = 0; - return rs; - } - ~RefPtrImpl() - { - Unreference(); - } + operator T*() const + { + return pointer; + } - void Unreference() - { - if (pointer) - { - if (pointer->_refCount > 1) - { - pointer->_refCount--; - } - else - { - Destructor destructor; - destructor(pointer); - } - } - } - T & operator *() const - { - return *pointer; - } - T * operator->() const - { - return pointer; - } - T * Ptr() const - { - return pointer; - } - public: - explicit operator bool() const - { - if (pointer) - return true; - else - return false; - } + private: + T* pointer; + }; } |
