#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