#pragma once #include "StarException.hpp" #include "StarHash.hpp" namespace Star { // Reference counted ptr for intrusive reference counted types. Calls // unqualified refPtrIncRef and refPtrDecRef functions to manage the reference // count. template class RefPtr { public: typedef T element_type; RefPtr(); explicit RefPtr(T* p, bool addRef = true); RefPtr(RefPtr const& r); RefPtr(RefPtr&& r); template RefPtr(RefPtr const& r); template RefPtr(RefPtr&& r); ~RefPtr(); RefPtr& operator=(RefPtr const& r); RefPtr& operator=(RefPtr&& r); template RefPtr& operator=(RefPtr const& r); template RefPtr& operator=(RefPtr&& r); void reset(); void reset(T* r, bool addRef = true); T& operator*() const; T* operator->() const; T* get() const; explicit operator bool() const; private: template friend class RefPtr; T* m_ptr; }; template bool operator==(RefPtr const& a, RefPtr const& b); template bool operator!=(RefPtr const& a, RefPtr const& b); template bool operator==(RefPtr const& a, T* b); template bool operator!=(RefPtr const& a, T* b); template bool operator==(T* a, RefPtr const& b); template bool operator!=(T* a, RefPtr const& b); template bool operator<(RefPtr const& a, RefPtr const& b); template bool is(RefPtr const& p); template bool is(RefPtr const& p); template RefPtr as(RefPtr const& p); template RefPtr as(RefPtr const& p); template RefPtr make_ref(Args&&... args); template struct hash> { size_t operator()(RefPtr const& a) const; hash hasher; }; // Base class for RefPtr that is NOT thread safe. This can have a performance // benefit over shared_ptr in single threaded contexts. class RefCounter { public: friend void refPtrIncRef(RefCounter* p); friend void refPtrDecRef(RefCounter* p); protected: RefCounter(); virtual ~RefCounter() = default; private: size_t m_refCounter; }; template RefPtr::RefPtr() : m_ptr(nullptr) {} template RefPtr::RefPtr(T* p, bool addRef) : m_ptr(nullptr) { reset(p, addRef); } template RefPtr::RefPtr(RefPtr const& r) : RefPtr(r.m_ptr) {} template RefPtr::RefPtr(RefPtr&& r) { m_ptr = r.m_ptr; r.m_ptr = nullptr; } template template RefPtr::RefPtr(RefPtr const& r) : RefPtr(r.m_ptr) {} template template RefPtr::RefPtr(RefPtr&& r) { m_ptr = r.m_ptr; r.m_ptr = nullptr; } template RefPtr::~RefPtr() { if (m_ptr) refPtrDecRef(m_ptr); } template RefPtr& RefPtr::operator=(RefPtr const& r) { reset(r.m_ptr); return *this; } template RefPtr& RefPtr::operator=(RefPtr&& r) { if (m_ptr) refPtrDecRef(m_ptr); m_ptr = r.m_ptr; r.m_ptr = nullptr; return *this; } template template RefPtr& RefPtr::operator=(RefPtr const& r) { reset(r.m_ptr); return *this; } template template RefPtr& RefPtr::operator=(RefPtr&& r) { if (m_ptr) refPtrDecRef(m_ptr); m_ptr = r.m_ptr; r.m_ptr = nullptr; return *this; } template void RefPtr::reset() { reset(nullptr); } template void RefPtr::reset(T* r, bool addRef) { if (m_ptr == r) return; if (m_ptr) refPtrDecRef(m_ptr); m_ptr = r; if (m_ptr && addRef) refPtrIncRef(m_ptr); } template T& RefPtr::operator*() const { return *m_ptr; } template T* RefPtr::operator->() const { return m_ptr; } template T* RefPtr::get() const { return m_ptr; } template RefPtr::operator bool() const { return m_ptr != nullptr; } template bool operator==(RefPtr const& a, RefPtr const& b) { return a.get() == b.get(); } template bool operator!=(RefPtr const& a, RefPtr const& b) { return a.get() != b.get(); } template bool operator==(RefPtr const& a, T* b) { return a.get() == b; } template bool operator!=(RefPtr const& a, T* b) { return a.get() != b; } template bool operator==(T* a, RefPtr const& b) { return a == b.get(); } template bool operator!=(T* a, RefPtr const& b) { return a != b.get(); } template bool operator<(RefPtr const& a, RefPtr const& b) { return a.get() < b.get(); } template bool is(RefPtr const& p) { return (bool)dynamic_cast(p.get()); } template bool is(RefPtr const& p) { return (bool)dynamic_cast(p.get()); } template RefPtr as(RefPtr const& p) { return RefPtr(dynamic_cast(p.get())); } template RefPtr as(RefPtr const& p) { return RefPtr(dynamic_cast(p.get())); } template RefPtr make_ref(Args&&... args) { return RefPtr(new T(std::forward(args)...)); } template size_t hash>::operator()(RefPtr const& a) const { return hasher(a.get()); } inline void refPtrIncRef(RefCounter* p) { ++p->m_refCounter; } inline void refPtrDecRef(RefCounter* p) { if (--p->m_refCounter == 0) delete p; } inline RefCounter::RefCounter() : m_refCounter(0) {} }