chxavrefptr.h
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:6k
源码类别:

Symbian

开发平台:

C/C++

  1. /*****************************************************************************
  2.  * chxavrefptr.h
  3.  * -------------
  4.  *
  5.  * Synopsis:
  6.  * A simple reference-counting wrapper class for pointers
  7.  *
  8.  * Advantages:
  9.  * 
  10.  * 1) Does not require pointee to derive from body class
  11.  * 2) Can be used with pointers to non-UDTs, e.g., int, bool, etc
  12.  * 3) Can be used with objects that can not be (easily)
  13.  *    modified to derive from a body class
  14.  * 
  15.  * Note that this differs from the ownership semantics for
  16.  * auto_ptr, which transfers ownership when assigning from one
  17.  * object to another.
  18.  * 
  19.  * Efficiency cost:
  20.  * 
  21.  * 1) CPU cycles for counter manipulation
  22.  * 2) Requires an extra small object allocation for each object
  23.  * that is referenced
  24.  * 
  25.  * Notable limitations:
  26.  * 
  27.  * 1) Reference count is not caried around with the object; be
  28.  * careful when extracting or holding on to underlying raw
  29.  * pointer (one work around is to use operator new and allocate
  30.  * a count before the object in memory)
  31.  * 
  32.  *
  33.  * Target:
  34.  * Symbian OS
  35.  *
  36.  *
  37.  * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
  38.  *
  39.  *****************************************************************************/
  40. #ifndef _chxavrefptr_h_
  41. #define _chxavrefptr_h_
  42. // Helix includes...
  43. #include "hxassert.h"
  44. #define D_REFPTR 0
  45. // class RefCounter
  46. class RefCounter
  47. {
  48. public:
  49.     unsigned int GetRefCount() const;
  50. protected:
  51.     // derive only
  52.     RefCounter(bool bStartNewCounter = false);
  53.     RefCounter(const RefCounter& rhs);
  54.     ~RefCounter();
  55.     bool AquireNewCounter(const RefCounter& otherCounter);
  56.     bool ReleaseCounter(bool bStartNewCounter = false);
  57.     
  58.     
  59. private:
  60.     bool DecrementCounter();
  61.     RefCounter& operator=(const RefCounter& rhs);
  62. private:
  63.     unsigned int* m_pCounter;
  64. };
  65. inline 
  66. RefCounter::RefCounter(bool bStartNewCounter)
  67. : m_pCounter( bStartNewCounter ? new unsigned(1) : 0 )
  68. {
  69. }
  70. inline 
  71. RefCounter::RefCounter(const RefCounter& rhs)
  72. : m_pCounter(rhs.m_pCounter)
  73. {
  74.     if(m_pCounter)
  75.     {
  76. // we now refer to the same counter
  77. ++(*m_pCounter);
  78.     }
  79. }
  80. ////////////////////////////////////////////////////////////
  81. // release count; return true if count goes to zero
  82. inline
  83. bool RefCounter::DecrementCounter()
  84. {
  85.     HX_ASSERT(m_pCounter != 0);
  86.     HX_ASSERT(*m_pCounter != 0);
  87.     if( --(*m_pCounter) == 0 )
  88.     {
  89. // we held last reference; we clean up counter
  90. delete m_pCounter;
  91. m_pCounter = 0;
  92. return true;
  93.     }
  94.     return false;
  95. }
  96. ////////////////////////////////////////////////
  97. // abandon our reference on the current counter;
  98. // possibly create a new one if caller indicates
  99. // we should start a new counter
  100. //
  101. // returns true if count goes to zero (in this case derived
  102. // class should clean up the object associated with the
  103. // old counter)
  104. //
  105. inline
  106. bool RefCounter::ReleaseCounter(bool bStartNewCounter)
  107. {
  108.     // this could be optimized to reuse the old counter
  109.     // if its count went to zero
  110.     bool bCleanup = false;
  111.     if( m_pCounter )
  112.     { 
  113. bCleanup = DecrementCounter();
  114.     }
  115.     if(bStartNewCounter)
  116.     {
  117. m_pCounter = new unsigned(1);
  118.     }
  119.     else
  120.     {
  121. m_pCounter = 0;
  122.     }
  123.     return bCleanup;
  124. }
  125. ////////////////////////////////////////////////
  126. // abandon our counter for new counter
  127. //
  128. // returns true if count goes to zero (in this case derived
  129. // class should clean up the object associated with the counter)
  130. //
  131. inline
  132. bool RefCounter::AquireNewCounter(const RefCounter& otherCounter)
  133. {
  134.     bool bCleanup = false;
  135.     if( m_pCounter )
  136.     { 
  137. bCleanup = DecrementCounter();
  138.     }
  139.     if(otherCounter.m_pCounter)
  140.     {
  141. m_pCounter = otherCounter.m_pCounter;
  142. ++(*m_pCounter);
  143.     }
  144.   
  145.     return bCleanup;
  146. }
  147. inline
  148. RefCounter::~RefCounter()
  149. {
  150.     // derived class should call ReleaseCounter()
  151.     HX_ASSERT(0 == m_pCounter );
  152. }
  153. // mostly for debug
  154. inline
  155. unsigned int RefCounter::GetRefCount() const
  156. {
  157.     return m_pCounter ? *m_pCounter : 0;
  158. }
  159. // class refptr
  160. template<typename T>
  161. class refptr : public RefCounter
  162. {
  163. public:
  164.     // ctor and dtor
  165.     /*explicit*/ refptr(T* p = 0);
  166.     refptr(const refptr<T>& rhs);
  167.     ~refptr();
  168.     // assignment
  169.     refptr<T>& operator= (const refptr<T>& rhs);
  170.     refptr<T>& operator= (T* p);
  171.     // access
  172.     T* Ptr() const;
  173.     T* operator-> () const;
  174.     T& operator* () const;
  175.      // other
  176.     operator bool() const { return m_p != 0; }
  177.     void Reset(T* p = 0);
  178.  
  179. private:
  180.     T* m_p;
  181. };
  182. template<typename T>
  183. inline
  184. refptr<T>::refptr(T* p)
  185. // tell base to start new counter if p != 0
  186. : RefCounter(p ? true : false) 
  187. , m_p(p)
  188. {
  189. }
  190. template<typename T>
  191. inline
  192. refptr<T>::refptr(const refptr<T>& rhs)
  193. : RefCounter(rhs) 
  194. , m_p(rhs.m_p) 
  195. {
  196. }
  197. ////////////////////////////////////////////////
  198. // a non-zero pointer means we are beginning
  199. // ref counting of the referenced object
  200. template <typename T>
  201. inline
  202. void refptr<T>::Reset(T* p)
  203. {
  204.     if( m_p != p)
  205.     {
  206. // release current counter, start with new if p != 0
  207. if( ReleaseCounter(p != 0) )
  208. {
  209.     // old counter went to 0; old object is no longer referenced by anyone
  210.     delete const_cast<T *>(m_p);
  211. }
  212. m_p = p;
  213.     }
  214. }
  215. template<typename T>
  216. inline
  217. refptr<T>::~refptr()
  218. {
  219.     Reset();
  220. }
  221. template< typename T>
  222. inline
  223. refptr<T>& refptr<T>::operator= (const refptr<T>& rhs)
  224. {
  225.     // lhs and rhs unchanged if referenced objects are the same
  226.     if( m_p != rhs.m_p )
  227.     {
  228. if(AquireNewCounter(rhs))
  229. {
  230.             //DPRINTF(D_REFPTR, ("refptr<>(x%x): deleting(2)n", m_p));
  231.     // old counter went to 0; old object is no longer referenced by anyone
  232.     delete const_cast<T *>(m_p);
  233. }
  234. m_p = rhs.m_p;
  235.     }
  236.     return *this;
  237. }
  238. template< typename T>
  239. inline
  240. refptr<T>& refptr<T>::operator= (T* p)
  241. {
  242.     Reset(p);
  243.     return *this;
  244. }
  245. template <typename T>
  246. inline
  247. T* refptr<T>::Ptr() const
  248. {
  249.     return m_p;
  250. }
  251. template <typename T>
  252. inline
  253. T* refptr<T>::operator->() const
  254. {
  255.     HX_ASSERT_VALID_PTR(m_p);
  256.     return m_p;
  257. }
  258. template <typename T>
  259. inline
  260. T& refptr<T>::operator*() const
  261. {
  262.     return *m_p;
  263. }
  264. #endif // _chxavrefptr_h_