chxavrefptr.h

来自「著名的 helix realplayer 基于手机 symbian 系统的 播放」· 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 + -
显示快捷键?