From fcf83dbf9effab3bd98bad2b83b2468b7eb05cfd Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Fri, 9 Jun 2017 11:34:21 -0700 Subject: Initial import of code. --- source/core/smart-pointer.h | 468 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 source/core/smart-pointer.h (limited to 'source/core/smart-pointer.h') diff --git a/source/core/smart-pointer.h b/source/core/smart-pointer.h new file mode 100644 index 000000000..f1fece2e5 --- /dev/null +++ b/source/core/smart-pointer.h @@ -0,0 +1,468 @@ +#ifndef FUNDAMENTAL_LIB_SMART_POINTER_H +#define FUNDAMENTAL_LIB_SMART_POINTER_H + +#include "type-traits.h" + +namespace CoreLib +{ + namespace Basic + { + class RefPtrDefaultDestructor + { + public: + template + void operator ()(T * ptr) + { + delete ptr; + } + }; + + class RefPtrArrayDestructor + { + public: + template + void operator() (T * ptr) + { + delete [] ptr; + } + }; + + class ReferenceCounted + { + template + friend class RefPtrImpl; + private: + int _refCount = 0; + public: + ReferenceCounted() {} + ReferenceCounted(const ReferenceCounted &) + { + _refCount = 0; + } + }; + + + class RefObject : public ReferenceCounted + { + public: + virtual ~RefObject() + {} + }; + + template + class RefPtrImpl + { + }; + + template + using RefPtr = RefPtrImpl::Value, Destructor>; + + template + class RefPtrImpl + { + template + friend class RefPtrImpl; + private: + T * pointer; + int * refCount; + + public: + RefPtrImpl() + { + pointer = 0; + refCount = 0; + } + RefPtrImpl(T * ptr) + : pointer(0), refCount(0) + { + this->operator=(ptr); + } + RefPtrImpl(const RefPtrImpl & ptr) + : pointer(0), refCount(0) + { + this->operator=(ptr); + } + RefPtrImpl(RefPtrImpl && str) + : pointer(0), refCount(0) + { + this->operator=(static_cast &&>(str)); + } + + template + RefPtrImpl(const RefPtrImpl& ptr, + typename EnableIf::Value, void>::type * = 0) + : pointer(0), refCount(0) + { + pointer = ptr.pointer; + if (ptr) + { + refCount = ptr.refCount; + (*refCount)++; + } + else + refCount = 0; + } + + template + typename EnableIf::value, RefPtrImpl>::type& + operator=(const RefPtrImpl & ptr) + { + Unreference(); + + pointer = ptr; + if (ptr) + { + refCount = ptr.refCount; + (*refCount)++; + } + else + refCount = 0; + return *this; + } + + RefPtrImpl& operator=(const RefPtrImpl & ptr) + { + Unreference(); + pointer = ptr.pointer; + if (ptr) + { + refCount = ptr.refCount; + (*refCount)++; + } + else + refCount = 0; + return *this; + } + + RefPtrImpl& 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 + bool operator == (const RefPtr & ptr) const + { + return pointer == ptr.pointer; + } + template + bool operator != (const RefPtr & ptr) const + { + return pointer != ptr.pointer; + } + template + RefPtrImpl As() const + { + RefPtrImpl result; + if (pointer) + { + result.pointer = dynamic_cast(pointer); + if (result.pointer) + { + result.refCount = refCount; + (*refCount)++; + } + } + return result; + } + + T* operator +(int offset) const + { + return pointer+offset; + } + T& operator [](int idx) const + { + return *(pointer + idx); + } + RefPtrImpl& operator=(RefPtrImpl && 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(); + } + + 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 + class RefPtrImpl + { + template + friend class RefPtrImpl; + + private: + T * pointer; + public: + RefPtrImpl() + { + pointer = 0; + } + RefPtrImpl(T * ptr) + : pointer(0) + { + this->operator=(ptr); + } + RefPtrImpl(const RefPtrImpl & ptr) + : pointer(0) + { + this->operator=(ptr); + } + RefPtrImpl(RefPtrImpl && str) + : pointer(0) + { + this->operator=(static_cast &&>(str)); + } + template + RefPtrImpl(const RefPtrImpl& ptr, + typename EnableIf::Value, void>::type * = 0) + : pointer(0) + { + pointer = ptr.pointer; + if (ptr) + { + ptr->_refCount++; + } + } + + template + typename EnableIf::value, RefPtrImpl&>::type + operator=(const RefPtrImpl & ptr) + { + Unreference(); + + pointer = ptr.pointer; + if (ptr) + { + ptr->_refCount++; + } + return *this; + } + RefPtrImpl& operator=(T * ptr) + { + if (ptr != pointer) + { + Unreference(); + + pointer = ptr; + if (ptr) + { + ptr->_refCount++; + } + } + return *this; + } + RefPtrImpl& operator=(const RefPtrImpl & 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 + bool operator == (const RefPtr & ptr) const + { + return pointer == ptr.pointer; + } + template + bool operator != (const RefPtr & ptr) const + { + return pointer != ptr.pointer; + } + template + RefPtrImpl As() const + { + RefPtrImpl result; + if (pointer) + { + result.pointer = dynamic_cast(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& operator=(RefPtrImpl && 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(); + } + + 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; + } + }; + } +} + +#endif \ No newline at end of file -- cgit v1.2.3