#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> &copy)
  : 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__)

Posted by 셈말짓기 :