chxavrefptr.h
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:6k
- /*****************************************************************************
- * chxavrefptr.h
- * -------------
- *
- * Synopsis:
- * A simple reference-counting wrapper class for pointers
- *
- * Advantages:
- *
- * 1) Does not require pointee to derive from body class
- * 2) Can be used with pointers to non-UDTs, e.g., int, bool, etc
- * 3) Can be used with objects that can not be (easily)
- * modified to derive from a body class
- *
- * Note that this differs from the ownership semantics for
- * auto_ptr, which transfers ownership when assigning from one
- * object to another.
- *
- * Efficiency cost:
- *
- * 1) CPU cycles for counter manipulation
- * 2) Requires an extra small object allocation for each object
- * that is referenced
- *
- * Notable limitations:
- *
- * 1) Reference count is not caried around with the object; be
- * careful when extracting or holding on to underlying raw
- * pointer (one work around is to use operator new and allocate
- * a count before the object in memory)
- *
- *
- * Target:
- * Symbian OS
- *
- *
- * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
- *
- *****************************************************************************/
- #ifndef _chxavrefptr_h_
- #define _chxavrefptr_h_
- // Helix includes...
- #include "hxassert.h"
- #define D_REFPTR 0
- // class RefCounter
- class RefCounter
- {
- public:
- unsigned int GetRefCount() const;
- protected:
- // derive only
- RefCounter(bool bStartNewCounter = false);
- RefCounter(const RefCounter& rhs);
- ~RefCounter();
- bool AquireNewCounter(const RefCounter& otherCounter);
- bool ReleaseCounter(bool bStartNewCounter = false);
-
-
- private:
- bool DecrementCounter();
- RefCounter& operator=(const RefCounter& rhs);
- private:
- unsigned int* m_pCounter;
- };
- inline
- RefCounter::RefCounter(bool bStartNewCounter)
- : m_pCounter( bStartNewCounter ? new unsigned(1) : 0 )
- {
- }
- inline
- RefCounter::RefCounter(const RefCounter& rhs)
- : m_pCounter(rhs.m_pCounter)
- {
- if(m_pCounter)
- {
- // we now refer to the same counter
- ++(*m_pCounter);
- }
- }
- ////////////////////////////////////////////////////////////
- // release count; return true if count goes to zero
- inline
- bool RefCounter::DecrementCounter()
- {
- HX_ASSERT(m_pCounter != 0);
- HX_ASSERT(*m_pCounter != 0);
- if( --(*m_pCounter) == 0 )
- {
- // we held last reference; we clean up counter
- delete m_pCounter;
- m_pCounter = 0;
- return true;
- }
- return false;
- }
- ////////////////////////////////////////////////
- // abandon our reference on the current counter;
- // possibly create a new one if caller indicates
- // we should start a new counter
- //
- // returns true if count goes to zero (in this case derived
- // class should clean up the object associated with the
- // old counter)
- //
- inline
- bool RefCounter::ReleaseCounter(bool bStartNewCounter)
- {
- // this could be optimized to reuse the old counter
- // if its count went to zero
- bool bCleanup = false;
- if( m_pCounter )
- {
- bCleanup = DecrementCounter();
- }
- if(bStartNewCounter)
- {
- m_pCounter = new unsigned(1);
- }
- else
- {
- m_pCounter = 0;
- }
- return bCleanup;
- }
- ////////////////////////////////////////////////
- // abandon our counter for new counter
- //
- // returns true if count goes to zero (in this case derived
- // class should clean up the object associated with the counter)
- //
- inline
- bool RefCounter::AquireNewCounter(const RefCounter& otherCounter)
- {
- bool bCleanup = false;
- if( m_pCounter )
- {
- bCleanup = DecrementCounter();
- }
- if(otherCounter.m_pCounter)
- {
- m_pCounter = otherCounter.m_pCounter;
- ++(*m_pCounter);
- }
-
- return bCleanup;
- }
- inline
- RefCounter::~RefCounter()
- {
- // derived class should call ReleaseCounter()
- HX_ASSERT(0 == m_pCounter );
- }
- // mostly for debug
- inline
- unsigned int RefCounter::GetRefCount() const
- {
- return m_pCounter ? *m_pCounter : 0;
- }
- // class refptr
- template<typename T>
- class refptr : public RefCounter
- {
- public:
-
- // ctor and dtor
- /*explicit*/ refptr(T* p = 0);
- refptr(const refptr<T>& rhs);
- ~refptr();
- // assignment
- refptr<T>& operator= (const refptr<T>& rhs);
- refptr<T>& operator= (T* p);
- // access
- T* Ptr() const;
- T* operator-> () const;
- T& operator* () const;
- // other
- operator bool() const { return m_p != 0; }
- void Reset(T* p = 0);
-
- private:
- T* m_p;
- };
-
- template<typename T>
- inline
- refptr<T>::refptr(T* p)
- // tell base to start new counter if p != 0
- : RefCounter(p ? true : false)
- , m_p(p)
- {
- }
- template<typename T>
- inline
- refptr<T>::refptr(const refptr<T>& rhs)
- : RefCounter(rhs)
- , m_p(rhs.m_p)
- {
- }
- ////////////////////////////////////////////////
- // a non-zero pointer means we are beginning
- // ref counting of the referenced object
- template <typename T>
- inline
- void refptr<T>::Reset(T* p)
- {
- if( m_p != p)
- {
- // release current counter, start with new if p != 0
- if( ReleaseCounter(p != 0) )
- {
- // old counter went to 0; old object is no longer referenced by anyone
- delete const_cast<T *>(m_p);
- }
- m_p = p;
- }
- }
- template<typename T>
- inline
- refptr<T>::~refptr()
- {
- Reset();
- }
- template< typename T>
- inline
- refptr<T>& refptr<T>::operator= (const refptr<T>& rhs)
- {
- // lhs and rhs unchanged if referenced objects are the same
- if( m_p != rhs.m_p )
- {
- if(AquireNewCounter(rhs))
- {
- //DPRINTF(D_REFPTR, ("refptr<>(x%x): deleting(2)n", m_p));
- // old counter went to 0; old object is no longer referenced by anyone
- delete const_cast<T *>(m_p);
- }
- m_p = rhs.m_p;
- }
- return *this;
- }
- template< typename T>
- inline
- refptr<T>& refptr<T>::operator= (T* p)
- {
- Reset(p);
- return *this;
- }
- template <typename T>
- inline
- T* refptr<T>::Ptr() const
- {
- return m_p;
- }
- template <typename T>
- inline
- T* refptr<T>::operator->() const
- {
- HX_ASSERT_VALID_PTR(m_p);
- return m_p;
- }
- template <typename T>
- inline
- T& refptr<T>::operator*() const
- {
- return *m_p;
- }
- #endif // _chxavrefptr_h_