Listing 1: Reference count template

#ifndef __RefCount_h__
#define __RefCount_h__

template<class DATA>
class CHReferenceCount
{
public:
    CHReferenceCount();
    CHReferenceCount(const CHReferenceCount<DATA>& objRefCount);
    ~CHReferenceCount();
    CHReferenceCount<DATA>&
      operator=(const CHReferenceCount<DATA> &robjRefCount);
    void Reset();

protected:
    inline const DATA* const GetData() const;
    inline DATA* const GetData();

private:
    // Reference counting implementation
    void CopyOnWrite();
    void CopyReference(const CHReferenceCount<DATA>& robjRefCount);
    void NewReference();
    void ReleaseReference();
    
    inline int ReferenceCount();

    DATA*  m_pRefData;  // pointer to shared data structure
    int*  m_pnRefCount; // pointer to reference counter
};

///////////////////////////////////////////////////////////////////
// inline functions

template<class DATA>
inline const DATA* const CHReferenceCount<DATA>::GetData() const
{
    return m_pRefData;
}

template<class DATA>
inline DATA* const CHReferenceCount<DATA>::GetData()
{
    if (ReferenceCount() > 1)
        CopyOnWrite();
    return m_pRefData;
}

template<class DATA>
inline int CHReferenceCount<DATA>::ReferenceCount()
{
    return *m_pnRefCount;
}

///////////////////////////////////////////////////////////////////
// out-of-line functions
template<class DATA>
CHReferenceCount<DATA>::CHReferenceCount()
{
    NewReference();
}

template<class DATA>
CHReferenceCount<DATA>::CHReferenceCount
    (const CHReferenceCount<DATA>& robjRefCount)
{ 
    CopyReference(robjRefCount);
}

template<class DATA>
CHReferenceCount<DATA>::~CHReferenceCount()
{
    ReleaseReference();
}

template<class DATA>
CHReferenceCount<DATA>&
CHReferenceCount<DATA>::operator=
    (const CHReferenceCount<DATA>& robjRefCount)
{
    if (robjRefCount.m_pRefData != m_pRefData)
    {
        ReleaseReference();
        CopyReference(robjRefCount);
    }

    return(*this);
}

template<class DATA>
void CHReferenceCount<DATA>::CopyReference
    (const CHReferenceCount<DATA>& robjRefCount)
{
    ASSERT(robjRefCount.m_pRefData && robjRefCount.m_pnRefCount);
    
    m_pRefData = robjRefCount.m_pRefData;
    m_pnRefCount = robjRefCount.m_pnRefCount;
    ++*m_pnRefCount;
}

template<class DATA>
void CHReferenceCount<DATA>::NewReference()
{
    m_pRefData = new DATA;
    m_pnRefCount = new int(1);
}

template<class DATA>
void CHReferenceCount<DATA>::ReleaseReference()
{
    --*m_pnRefCount;
    
    if (*m_pnRefCount == 0)
    {
        delete m_pnRefCount;
        m_pnRefCount=NULL;

        delete m_pRefData;
        m_pRefData=NULL;
    }
}

template<class DATA>
void CHReferenceCount<DATA>::CopyOnWrite()
{
    DATA* pRefData = new DATA(*m_pRefData);

    ReleaseReference();
    
    m_pRefData = pRefData;
    m_pnRefCount = new int(1);
}

template<class DATA>
void CHReferenceCount<DATA>::Reset()
{
    ReleaseReference();
    m_pRefData =  new DATA;
    m_pnRefCount = new int(1);
}

#endif
//End of File