mirror of
https://github.com/0TheSpy/Seaside.git
synced 2025-01-11 11:33:01 +08:00
320 lines
8.1 KiB
C
320 lines
8.1 KiB
C
|
#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 <class REFCOUNTED_ITEM_PTR>
|
||
|
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 T = IRefCounted>
|
||
|
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 T>
|
||
|
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<T>& p) const { return operator==((const void*)p); }
|
||
|
bool operator!=(const CBaseAutoPtr<T>& 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<T>& from) : m_pObject(from.m_pObject) {}
|
||
|
void operator=(const CBaseAutoPtr<T>& from) { m_pObject = from.m_pObject; }
|
||
|
|
||
|
T* m_pObject;
|
||
|
};
|
||
|
|
||
|
template <class T>
|
||
|
class CRefPtr : public CBaseAutoPtr<T>
|
||
|
{
|
||
|
typedef CBaseAutoPtr<T> BaseClass;
|
||
|
public:
|
||
|
CRefPtr() {}
|
||
|
CRefPtr(T* pInit) : BaseClass(pInit) {}
|
||
|
CRefPtr(const CRefPtr<T>& from) : BaseClass(from) {}
|
||
|
~CRefPtr() { if (BaseClass::m_pObject) BaseClass::m_pObject->Release(); }
|
||
|
|
||
|
void operator=(const CRefPtr<T>& 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 <const bool bSelfDelete, typename CRefThreading = CRefMT>
|
||
|
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 <typename CRefThreading = CRefMT>
|
||
|
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<true, CRefST> CRefCountServiceST;
|
||
|
typedef CRefCountServiceBase<false, CRefST> CRefCountServiceNoDeleteST;
|
||
|
|
||
|
typedef CRefCountServiceBase<true, CRefMT> CRefCountServiceMT;
|
||
|
typedef CRefCountServiceBase<false, CRefMT> 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 BASE_REFCOUNTED, int FINAL_REFS, const char* pszName>
|
||
|
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
|