#ifndef REFCOUNT_H #define REFCOUNT_H #include "threadtools.h" #if defined( _WIN32 ) #pragma once #endif class IRefCounted { public: virtual int AddRef() = 0; virtual int Release() = 0; }; template inline int SafeRelease(REFCOUNTED_ITEM_PTR& pRef) { REFCOUNTED_ITEM_PTR* ppRef = &pRef; if (*ppRef) { int result = (*ppRef)->Release(); *ppRef = NULL; return result; } return 0; } template class CAutoRef { public: CAutoRef(T* pRef) : m_pRef(pRef) { if (m_pRef) m_pRef->AddRef(); } ~CAutoRef() { if (m_pRef) m_pRef->Release(); } private: T* m_pRef; }; #define RetAddRef( p ) ( (p)->AddRef(), (p) ) #define InlineAddRef( p ) ( (p)->AddRef(), (p) ) template class CBaseAutoPtr { public: CBaseAutoPtr() : m_pObject(0) {} CBaseAutoPtr(T* pFrom) : m_pObject(pFrom) {} operator const void* () const { return m_pObject; } operator void* () { return m_pObject; } operator const T* () const { return m_pObject; } operator const T* () { return m_pObject; } operator T* () { return m_pObject; } int operator=(int i) { AssertMsg(i == 0, "Only NULL allowed on integer assign"); m_pObject = 0; return 0; } T* operator=(T* p) { m_pObject = p; return p; } bool operator !() const { return (!m_pObject); } bool operator!=(int i) const { AssertMsg(i == 0, "Only NULL allowed on integer compare"); return (m_pObject != NULL); } bool operator==(const void* p) const { return (m_pObject == p); } bool operator!=(const void* p) const { return (m_pObject != p); } bool operator==(T* p) const { return operator==((void*)p); } bool operator!=(T* p) const { return operator!=((void*)p); } bool operator==(const CBaseAutoPtr& p) const { return operator==((const void*)p); } bool operator!=(const CBaseAutoPtr& p) const { return operator!=((const void*)p); } T* operator->() { return m_pObject; } T& operator *() { return *m_pObject; } T** operator &() { return &m_pObject; } const T* operator->() const { return m_pObject; } const T& operator *() const { return *m_pObject; } T* const* operator &() const { return &m_pObject; } protected: CBaseAutoPtr(const CBaseAutoPtr& from) : m_pObject(from.m_pObject) {} void operator=(const CBaseAutoPtr& from) { m_pObject = from.m_pObject; } T* m_pObject; }; template class CRefPtr : public CBaseAutoPtr { typedef CBaseAutoPtr BaseClass; public: CRefPtr() {} CRefPtr(T* pInit) : BaseClass(pInit) {} CRefPtr(const CRefPtr& from) : BaseClass(from) {} ~CRefPtr() { if (BaseClass::m_pObject) BaseClass::m_pObject->Release(); } void operator=(const CRefPtr& from) { BaseClass::operator=(from); } int operator=(int i) { return BaseClass::operator=(i); } T* operator=(T* p) { return BaseClass::operator=(p); } operator bool() const { return !BaseClass::operator!(); } operator bool() { return !BaseClass::operator!(); } void SafeRelease() { if (BaseClass::m_pObject) BaseClass::m_pObject->Release(); BaseClass::m_pObject = 0; } void AssignAddRef(T* pFrom) { SafeRelease(); if (pFrom) pFrom->AddRef(); BaseClass::m_pObject = pFrom; } void AddRefAssignTo(T*& pTo) { ::SafeRelease(pTo); if (BaseClass::m_pObject) BaseClass::m_pObject->AddRef(); pTo = BaseClass::m_pObject; } }; class CRefMT { public: static int Increment(int* p) { return ThreadInterlockedIncrement((long*)p); } static int Decrement(int* p) { return ThreadInterlockedDecrement((long*)p); } }; class CRefST { public: static int Increment(int* p) { return ++(*p); } static int Decrement(int* p) { return --(*p); } }; template class NO_VTABLE CRefCountServiceBase { protected: CRefCountServiceBase() : m_iRefs(1) { } virtual ~CRefCountServiceBase() { } virtual bool OnFinalRelease() { return true; } int GetRefCount() const { return m_iRefs; } int DoAddRef() { return CRefThreading::Increment(&m_iRefs); } int DoRelease() { int result = CRefThreading::Decrement(&m_iRefs); if (result) return result; if (OnFinalRelease() && bSelfDelete) delete this; return 0; } private: int m_iRefs; }; class CRefCountServiceNull { protected: static int DoAddRef() { return 1; } static int DoRelease() { return 1; } }; template class NO_VTABLE CRefCountServiceDestruct { protected: CRefCountServiceDestruct() : m_iRefs(1) { } virtual ~CRefCountServiceDestruct() { } int GetRefCount() const { return m_iRefs; } int DoAddRef() { return CRefThreading::Increment(&m_iRefs); } int DoRelease() { int result = CRefThreading::Decrement(&m_iRefs); if (result) return result; this->~CRefCountServiceDestruct(); return 0; } private: int m_iRefs; }; typedef CRefCountServiceBase CRefCountServiceST; typedef CRefCountServiceBase CRefCountServiceNoDeleteST; typedef CRefCountServiceBase CRefCountServiceMT; typedef CRefCountServiceBase CRefCountServiceNoDeleteMT; typedef CRefCountServiceNoDeleteMT CRefCountServiceNoDelete; typedef CRefCountServiceMT CRefCountService; template < class REFCOUNT_SERVICE = CRefCountService > class NO_VTABLE CRefCounted : public REFCOUNT_SERVICE { public: virtual ~CRefCounted() {} int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } int Release() { return REFCOUNT_SERVICE::DoRelease(); } }; template < class BASE1, class REFCOUNT_SERVICE = CRefCountService > class NO_VTABLE CRefCounted1 : public BASE1, public REFCOUNT_SERVICE { public: virtual ~CRefCounted1() {} int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } int Release() { return REFCOUNT_SERVICE::DoRelease(); } }; template < class BASE1, class BASE2, class REFCOUNT_SERVICE = CRefCountService > class NO_VTABLE CRefCounted2 : public BASE1, public BASE2, public REFCOUNT_SERVICE { public: virtual ~CRefCounted2() {} int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } int Release() { return REFCOUNT_SERVICE::DoRelease(); } }; template < class BASE1, class BASE2, class BASE3, class REFCOUNT_SERVICE = CRefCountService > class NO_VTABLE CRefCounted3 : public BASE1, public BASE2, public BASE3, public REFCOUNT_SERVICE { virtual ~CRefCounted3() {} int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } int Release() { return REFCOUNT_SERVICE::DoRelease(); } }; template < class BASE1, class BASE2, class BASE3, class BASE4, class REFCOUNT_SERVICE = CRefCountService > class NO_VTABLE CRefCounted4 : public BASE1, public BASE2, public BASE3, public BASE4, public REFCOUNT_SERVICE { public: virtual ~CRefCounted4() {} int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } int Release() { return REFCOUNT_SERVICE::DoRelease(); } }; template < class BASE1, class BASE2, class BASE3, class BASE4, class BASE5, class REFCOUNT_SERVICE = CRefCountService > class NO_VTABLE CRefCounted5 : public BASE1, public BASE2, public BASE3, public BASE4, public BASE5, public REFCOUNT_SERVICE { public: virtual ~CRefCounted5() {} int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } int Release() { return REFCOUNT_SERVICE::DoRelease(); } }; template class CRefDebug : public BASE_REFCOUNTED { public: #ifdef _DEBUG CRefDebug() { AssertMsg(this->GetRefCount() == 1, "Expected initial ref count of 1"); DevMsg("%s:create 0x%x\n", (pszName) ? pszName : "", this); } virtual ~CRefDebug() { AssertDevMsg(this->GetRefCount() == FINAL_REFS, "Object still referenced on destroy?"); DevMsg("%s:destroy 0x%x\n", (pszName) ? pszName : "", this); } int AddRef() { DevMsg("%s:(0x%x)->AddRef() --> %d\n", (pszName) ? pszName : "", this, this->GetRefCount() + 1); return BASE_REFCOUNTED::AddRef(); } int Release() { DevMsg("%s:(0x%x)->Release() --> %d\n", (pszName) ? pszName : "", this, this->GetRefCount() - 1); Assert(this->GetRefCount() > 0); return BASE_REFCOUNTED::Release(); } #endif }; #endif