#ifndef __REFCOUNT_H__ #define __REFCOUNT_H__ // Simple shared pointer. Takes ownership of passed regular pointers template class CSharedPointer { public: CSharedPointer(); CSharedPointer(const CSharedPointer& v); CSharedPointer(T *v); ~CSharedPointer(); void clear(); T& operator*() const; T* operator->() const; T* Value() const {return m_ptr; } // Promise to NEVER EVER call delete on the returned value bool operator==(const CSharedPointer& cmp) const { return m_ptr == cmp.m_ptr; } inline bool operator!=(const CSharedPointer& cmp) const { return m_ptr != cmp.m_ptr; } bool operator<(const CSharedPointer& cmp) const { return m_ptr < cmp.m_ptr; } // Magic for CSharedPointer foo(bar); if (foo) ... // aka safe bool idiom typedef void (CSharedPointer::*bool_type)() const; void uncomparable() const {} operator bool_type() const { return m_ptr ? &CSharedPointer::uncomparable : 0; } CSharedPointer& operator=(const CSharedPointer& v); CSharedPointer& operator=(T *v); protected: int* m_refcount; T* m_ptr; }; template class CSharedPointerArray { public: CSharedPointerArray(); CSharedPointerArray(const CSharedPointerArray& v); CSharedPointerArray(T *v); ~CSharedPointerArray(); void clear(); T& operator*() const; T* operator->() const; T* Value() const {return m_ptr; } // Promise to NEVER EVER call delete on the returned value bool operator==(const CSharedPointerArray& cmp) const { return m_ptr == cmp.m_ptr; } inline bool operator!=(const CSharedPointerArray& cmp) const { return m_ptr != cmp.m_ptr; } bool operator<(const CSharedPointerArray& cmp) const { return m_ptr < cmp.m_ptr; } // Magic for CSharedPointerArray foo(bar); if (foo) ... // aka safe bool idiom typedef void (CSharedPointerArray::*bool_type)() const; void uncomparable() const {} operator bool_type() const { return m_ptr ? &CSharedPointerArray::uncomparable : 0; } CSharedPointerArray& operator=(const CSharedPointerArray& v); CSharedPointerArray& operator=(T *v); protected: int* m_refcount; T* m_ptr; }; // Trivial template class to refcount objects with COW semantics. template class CRefcountObject { public: CRefcountObject(); CRefcountObject(const CRefcountObject& v); CRefcountObject(const T& v); virtual ~CRefcountObject(); void clear(); T& Get(); const T& operator*() const; const T* operator->() const; bool operator==(const CRefcountObject& cmp) const; inline bool operator!=(const CRefcountObject& cmp) const { return !(*this == cmp); } bool operator<(const CRefcountObject& cmp) const; CRefcountObject& operator=(const CRefcountObject& v); protected: int* m_refcount; T* m_ptr; }; template class CRefcountObject_Uninitialized { /* Almost same as CRefcountObject but does not allocate an object initially. You need to ensure to assign some data prior to calling operator* or ->, otherwise you'll dereference the null-pointer. */ public: CRefcountObject_Uninitialized(); CRefcountObject_Uninitialized(const CRefcountObject_Uninitialized& v); CRefcountObject_Uninitialized(const T& v); virtual ~CRefcountObject_Uninitialized(); void clear(); T& Get(); const T& operator*() const; const T* operator->() const; bool operator==(const CRefcountObject_Uninitialized& cmp) const; inline bool operator!=(const CRefcountObject_Uninitialized& cmp) const { return !(*this == cmp); } bool operator<(const CRefcountObject_Uninitialized& cmp) const; CRefcountObject_Uninitialized& operator=(const CRefcountObject_Uninitialized& v); bool operator!() const { return m_ptr == 0; } protected: int* m_refcount; T* m_ptr; }; template CSharedPointer::CSharedPointer() { m_ptr = 0; m_refcount = 0; } template CSharedPointer::CSharedPointer(const CSharedPointer& v) { m_ptr = v.m_ptr; m_refcount = v.m_refcount; if (m_refcount) (*m_refcount)++; } template CSharedPointer::CSharedPointer(T* v) { if (v) { m_ptr = v; m_refcount = new int(1); } else { m_ptr = 0; m_refcount = 0; } } template CSharedPointer::~CSharedPointer() { if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } } template void CSharedPointer::clear() { if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } m_refcount = 0; m_ptr = 0; } template T& CSharedPointer::operator*() const { return *m_ptr; } template T* CSharedPointer::operator->() const { return m_ptr; } template CSharedPointer& CSharedPointer::operator=(const CSharedPointer& v) { if (this == &v) return *this; if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } m_ptr = v.m_ptr; m_refcount = v.m_refcount; if (m_refcount) (*m_refcount)++; return *this; } template CSharedPointer& CSharedPointer::operator=(T* v) { if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } if (v) { m_ptr = v; m_refcount = new int(1); } else { m_ptr = 0; m_refcount = 0; } return *this; } template CSharedPointerArray::CSharedPointerArray() { m_ptr = 0; m_refcount = 0; } template CSharedPointerArray::CSharedPointerArray(const CSharedPointerArray& v) { m_ptr = v.m_ptr; m_refcount = v.m_refcount; if (m_refcount) (*m_refcount)++; } template CSharedPointerArray::CSharedPointerArray(T* v) { if (v) { m_ptr = v; m_refcount = new int(1); } else { m_ptr = 0; m_refcount = 0; } } template CSharedPointerArray::~CSharedPointerArray() { if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete [] m_ptr; } } template void CSharedPointerArray::clear() { if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete [] m_ptr; } m_refcount = 0; m_ptr = 0; } template T& CSharedPointerArray::operator*() const { return *m_ptr; } template T* CSharedPointerArray::operator->() const { return m_ptr; } template CSharedPointerArray& CSharedPointerArray::operator=(const CSharedPointerArray& v) { if (this == &v) return *this; if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete [] m_ptr; } m_ptr = v.m_ptr; m_refcount = v.m_refcount; if (m_refcount) (*m_refcount)++; return *this; } template CSharedPointerArray& CSharedPointerArray::operator=(T* v) { if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete [] m_ptr; } if (v) { m_ptr = v; m_refcount = new int(1); } else { m_ptr = 0; m_refcount = 0; } return *this; } template bool CRefcountObject::operator==(const CRefcountObject& cmp) const { if (m_ptr == cmp.m_ptr) return true; return *m_ptr == *cmp.m_ptr; } template CRefcountObject::CRefcountObject() { m_refcount = new int(1); m_ptr = new T; } template CRefcountObject::CRefcountObject(const CRefcountObject& v) { m_refcount = v.m_refcount; (*m_refcount)++; m_ptr = v.m_ptr; } template CRefcountObject::CRefcountObject(const T& v) { m_ptr = new T(v); m_refcount = new int(1); } template CRefcountObject::~CRefcountObject() { if ((*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } } template T& CRefcountObject::Get() { if (*m_refcount != 1) { (*m_refcount)--; m_refcount = new int(1); T* ptr = new T(*m_ptr); m_ptr = ptr; } return *m_ptr; } template CRefcountObject& CRefcountObject::operator=(const CRefcountObject& v) { if (m_ptr == v.m_ptr) return *this; if ((*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } m_refcount = v.m_refcount; (*m_refcount)++; m_ptr = v.m_ptr; return *this; } template bool CRefcountObject::operator<(const CRefcountObject& cmp) const { if (m_ptr == cmp.m_ptr) return false; return *m_ptr < *cmp.m_ptr; } template void CRefcountObject::clear() { if (*m_refcount != 1) { (*m_refcount)--; m_refcount = new int(1); } else delete m_ptr; m_ptr = new T; } template const T& CRefcountObject::operator*() const { return *m_ptr; } template const T* CRefcountObject::operator->() const { return m_ptr; } // The same for the uninitialized version template bool CRefcountObject_Uninitialized::operator==(const CRefcountObject_Uninitialized& cmp) const { if (m_ptr == cmp.m_ptr) return true; return *m_ptr == *cmp.m_ptr; } template CRefcountObject_Uninitialized::CRefcountObject_Uninitialized() { m_refcount = 0; m_ptr = 0; } template CRefcountObject_Uninitialized::CRefcountObject_Uninitialized(const CRefcountObject_Uninitialized& v) { m_refcount = v.m_refcount; if (m_refcount) (*m_refcount)++; m_ptr = v.m_ptr; } template CRefcountObject_Uninitialized::CRefcountObject_Uninitialized(const T& v) { m_ptr = new T(v); m_refcount = new int(1); } template CRefcountObject_Uninitialized::~CRefcountObject_Uninitialized() { if (!m_refcount) return; if (*m_refcount == 1) { delete m_refcount; delete m_ptr; } else (*m_refcount)--; } template T& CRefcountObject_Uninitialized::Get() { if (!m_refcount) { m_refcount= new int(1); m_ptr = new T; } else if (*m_refcount != 1) { (*m_refcount)--; m_refcount = new int(1); T* ptr = new T(*m_ptr); m_ptr = ptr; } return *m_ptr; } template CRefcountObject_Uninitialized& CRefcountObject_Uninitialized::operator=(const CRefcountObject_Uninitialized& v) { if (m_ptr == v.m_ptr) return *this; if (m_refcount && (*m_refcount)-- == 1) { delete m_refcount; delete m_ptr; } m_refcount = v.m_refcount; if (m_refcount) (*m_refcount)++; m_ptr = v.m_ptr; return *this; } template bool CRefcountObject_Uninitialized::operator<(const CRefcountObject_Uninitialized& cmp) const { if (m_ptr == cmp.m_ptr) return false; if (!m_ptr) return true; if (!cmp.m_ptr) return false; return *m_ptr < *cmp.m_ptr; } template void CRefcountObject_Uninitialized::clear() { if (!m_refcount) return; else if (*m_refcount != 1) (*m_refcount)--; else { delete m_ptr; delete m_refcount; } m_refcount = 0; m_ptr = 0; } template const T& CRefcountObject_Uninitialized::operator*() const { return *m_ptr; } template const T* CRefcountObject_Uninitialized::operator->() const { return m_ptr; } #endif //__REFCOUNT_H__