// Copyright (C) 2000 Sean Cavanaugh // This file is licensed under the terms of the Lesser GNU Public License // (see LPGL.txt, or http://www.gnu.org/copyleft/lesser.txt) #if !defined(AFX_ReferencePtr_H__BAEBCE9D_CD68_40AF_8A54_B23A0D14E807__INCLUDED_) #define AFX_ReferencePtr_H__BAEBCE9D_CD68_40AF_8A54_B23A0D14E807__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #include "assert.h" #include "limits.h" #ifdef SYSTEM_POSIX #ifdef HAVE_STDDEF_H // For NULL #include #endif #endif #include "ReferenceCounter.h" /*! \author Sean Cavanaugh \email sean@dimensionalrift.com \cvsauthor $Author: sean $ \date $Date: 2000/09/11 20:28:24 $ \version $Revision: 1.1 $ \brief ReferencePtr is a simplified ReferencePtr, primiarily for use with reference counted pointers. Its purpose is solely for simplified garbage collection, and not any kind of advanced copy on write functionality. Passing a normal pointer to this class effectively starts its reference count at one and should not be manually deleted. (But it may be referenced as long as you know the object still exists in some scope somewhere) */ template class ReferencePtrBlock { public: DATA_T* pData; // User defined data block mutable ReferenceCounter ReferenceCount; }; template class ReferencePtr { public: // Construction ReferencePtr(); ReferencePtr(DATA_T* other); ReferencePtr(const ReferencePtr& other); virtual ~ReferencePtr(); // Assignment ReferencePtr& operator=(const ReferencePtr& other); ReferencePtr& operator=(DATA_T* other); // Dereferencing operator DATA_T*() const {return m_pData->pData;} DATA_T* operator->() const {return m_pData->pData;} protected: // Internal methods void Alloc(); // Allocate the m_pData void Release(); // Releases a reference count (possibly freeing memory) protected: // Member data ReferencePtrBlock* m_pData; }; template ReferencePtr::ReferencePtr() { Alloc(); } template ReferencePtr::ReferencePtr(DATA_T* other) { Alloc(); m_pData->pData = other; m_pData->ReferenceCount = 1; } template ReferencePtr::ReferencePtr(const ReferencePtr& other) { m_pData = other.m_pData; m_pData->ReferenceCount++; } template ReferencePtr::~ReferencePtr() { Release(); } template ReferencePtr& ReferencePtr::operator=(const ReferencePtr& other) { if (m_pData != other.m_pData) { Release(); m_pData = other.m_pData; m_pData->ReferenceCount++; } return *this; } template ReferencePtr& ReferencePtr::operator=(DATA_T* other) { if (m_pData->ReferenceCount.dec() <= 0) { delete m_pData->pData; m_pData->pData = other; m_pData->ReferenceCount = 1; } else { Alloc(); m_pData->pData = other; } return *this; } template void ReferencePtr::Alloc() { m_pData = new ReferencePtrBlock; m_pData->ReferenceCount = 1; m_pData->pData = NULL; } template void ReferencePtr::Release() { assert(m_pData != NULL); if (m_pData->ReferenceCount.dec() <= 0) { delete m_pData->pData; m_pData->pData = NULL; delete m_pData; m_pData = NULL; } } #endif // !defined(AFX_ReferencePtr_H__BAEBCE9D_CD68_40AF_8A54_B23A0D14E807__INCLUDED_)