#if !defined (__REFCOUNTEDAUTOPTR__H__)
#define __REFCOUNTEDAUTOPTR__H__
#pragma once
// ------------------------------------------------------------------------- //
// Global
// ------------------------------------------------------------------------- //
template<class T> class CAutoBasicPtr;
template<class T, class lockT> class CRefcountedAutoPtrRep;
template<class T, class lockT> class CRefcountedAutoPtr;
// ------------------------------------------------------------------------- //
// Class: CAutoBasicPtr
// ------------------------------------------------------------------------- //
template <class T>
class CAutoBasicPtr
{
public:
explicit CAutoBasicPtr (T *p = NULL)
: m_pPtr (p)
{
};
CAutoBasicPtr (CAutoBasicPtr<T> &rhs)
: m_pPtr (rhs.release ())
{
};
CAutoBasicPtr<T> &operator= (CAutoBasicPtr<T> &rhs)
{
if (this != &rhs)
{
this->Reset (rhs.Release ());
}
return *this;
};
~CAutoBasicPtr (void)
{
delete this->Get ();
};
public:
T &operator *() const
{
return *this->Get ();
};
T *Get (void) const
{
return this->m_pPtr;
};
T *Release (void)
{
T *old = this->m_pPtr;
this->m_pPtr = NULL;
return old;
};
void Reset (T *p = NULL)
{
if (this->Get () != p)
delete this->Get ();
this->m_pPtr = p;
};
protected:
T *m_pPtr;
};
// ------------------------------------------------------------------------- //
// Class: CRefcountedAutoPtrRep
// ------------------------------------------------------------------------- //
template<class T, class lockT>
class CRefcountedAutoPtrRep
{
private:
friend class CRefcountedAutoPtr <T, lockT>;
protected:
mutable lockT m_Lock;
CAutoBasicPtr<T> m_Ptr;
LONG m_nRefCount;
private:
CRefcountedAutoPtrRep (T* p=NULL)
: m_Ptr(p), m_nRefCount(0)
{
};
~CRefcountedAutoPtrRep ()
{
};
private:
static CRefcountedAutoPtrRep<T,lockT>* Create (T *p);
static CRefcountedAutoPtrRep<T,lockT>* Attach (CRefcountedAutoPtrRep<T,lockT> *&rep);
static void Detach (CRefcountedAutoPtrRep<T,lockT> *&rep);
static void Assign (CRefcountedAutoPtrRep<T,lockT> *&rep, CRefcountedAutoPtrRep<T,lockT> *new_rep);
};
template<class T, class lockT>
CRefcountedAutoPtrRep<T,lockT>* CRefcountedAutoPtrRep<T,lockT>::Create (T *p)
{
CRefcountedAutoPtrRep<T,lockT> *ret = NULL;
ret = new CRefcountedAutoPtrRep<T,lockT> (p);
return ret;
}
template<class T, class lockT>
CRefcountedAutoPtrRep<T,lockT>* CRefcountedAutoPtrRep<T,lockT>::Attach (CRefcountedAutoPtrRep<T,lockT> *&rep)
{
CXASSERT (rep!=NULL);
CSyncGuard<lockT> g(rep->m_Lock);
rep->m_nRefCount++;
return rep;
}
template<class T, class lockT>
void CRefcountedAutoPtrRep<T,lockT>::Detach (CRefcountedAutoPtrRep<T,lockT> *&rep)
{
CXASSERT (rep!=NULL);
CRefcountedAutoPtrRep<T,lockT> *del = NULL;
{
CSyncGuard<lockT> g(rep->m_Lock);
if (rep->m_nRefCount-- == 0)
del = rep;
}
if (del)
delete del;
}
template<class T, class lockT>
void CRefcountedAutoPtrRep<T,lockT>::Assign (CRefcountedAutoPtrRep<T,lockT> *&rep, CRefcountedAutoPtrRep<T,lockT> *new_rep)
{
CXASSERT (rep!=NULL);
CXASSERT (new_rep!=NULL);
CRefcountedAutoPtrRep<T,lockT> *del = 0;
{
CSyncGuard<lockT> g(rep->m_Lock);
del = rep;
rep = new_rep;
if (del->m_nRefCount-- > 0)
return;
}
delete del;
}
// ------------------------------------------------------------------------- //
// Class: CRefcountedAutoPtr
// ------------------------------------------------------------------------- //
template<class T, class lockT=CNullSync>
class CRefcountedAutoPtr
{
private:
friend class CRefcountedAutoPtrRep <T, lockT>;
private:
CRefcountedAutoPtrRep<T,lockT>* m_pRep;
public:
CRefcountedAutoPtr (T* p=0)
: m_pRep(CRefcountedAutoPtrRep<T,lockT>::Create (p))
{
};
CRefcountedAutoPtr (const CRefcountedAutoPtr<T,lockT> ©)
: m_pRep( CRefcountedAutoPtrRep<T,lockT>::Attach ( ( (CRefcountedAutoPtr<T, lockT> &)copy) .m_pRep ) )
{
};
virtual ~CRefcountedAutoPtr()
{
CRefcountedAutoPtrRep<T,lockT>::Detach (m_pRep);
};
public:
inline void operator=(const CRefcountedAutoPtr<T,lockT>& copy)
{
CRefcountedAutoPtr<T,lockT> &r = (CRefcountedAutoPtr<T,lockT> &)copy;
CRefcountedAutoPtrRep<T,lockT>::Assign (m_pRep, CRefcountedAutoPtrRep<T,lockT>::Attach (r.m_pRep));
};
inline bool operator==(const CRefcountedAutoPtr<T,lockT>& crep) const
{
return (m_pRep == crep.m_pRep);
};
inline bool operator!=(const CRefcountedAutoPtr<T,lockT>& crep) const
{
return (m_pRep != crep.m_pRep);
};
inline T* operator->() const
{
return m_pRep->m_Ptr.Get();
};
inline T* Get(void) const
{
return m_pRep->m_Ptr.Get();
};
inline LONG Count(void) const
{
return m_pRep->m_nRefCount;
};
};
#endif // !defined(__REFCOUNTEDAUTOPTR__H__)