chxavrefptr.h
来自「symbian 下的helix player源代码」· C头文件 代码 · 共 310 行
H
310 行
/*****************************************************************************
* 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_
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?