mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-02 09:40:35 +00:00
100 lines
3.3 KiB
C++
100 lines
3.3 KiB
C++
|
/* $Id$ */
|
||
|
|
||
|
#ifndef COUNTEDPTR_HPP
|
||
|
#define COUNTEDPTR_HPP
|
||
|
|
||
|
/** @file CCountedPtr - smart pointer implementation */
|
||
|
|
||
|
/** CCountedPtr - simple reference counting smart pointer.
|
||
|
*
|
||
|
* One of the standard ways how to maintain object's lifetime.
|
||
|
*
|
||
|
* See http://ootips.org/yonat/4dev/smart-pointers.html for more
|
||
|
* general info about smart pointers.
|
||
|
*
|
||
|
* This class implements ref-counted pointer for objects/interfaces that
|
||
|
* support AddRef() and Release() methods.
|
||
|
*/
|
||
|
template <class Tcls_>
|
||
|
class CCountedPtr {
|
||
|
/** redefine the template argument to make it visible for derived classes */
|
||
|
public:
|
||
|
typedef Tcls_ Tcls;
|
||
|
|
||
|
protected:
|
||
|
/** here we hold our pointer to the target */
|
||
|
Tcls* m_pT;
|
||
|
|
||
|
public:
|
||
|
/** default (NULL) construct or construct from a raw pointer */
|
||
|
FORCEINLINE CCountedPtr(Tcls* pObj = NULL) : m_pT(pObj) {AddRef();};
|
||
|
|
||
|
/** copy constructor (invoked also when initializing from another smart ptr) */
|
||
|
FORCEINLINE CCountedPtr(const CCountedPtr& src) : m_pT(src.m_pT) {AddRef();};
|
||
|
|
||
|
/** destructor releasing the reference */
|
||
|
FORCEINLINE ~CCountedPtr() {Release();};
|
||
|
|
||
|
protected:
|
||
|
/** add one ref to the underlaying object */
|
||
|
FORCEINLINE void AddRef() {if (m_pT != NULL) m_pT->AddRef();}
|
||
|
|
||
|
public:
|
||
|
/** release smart pointer (and decrement ref count) if not null */
|
||
|
FORCEINLINE void Release() {if (m_pT != NULL) {m_pT->Release(); m_pT = NULL;}}
|
||
|
|
||
|
/** dereference of smart pointer - const way */
|
||
|
FORCEINLINE const Tcls* operator -> () const {assert(m_pT != NULL); return m_pT;};
|
||
|
|
||
|
/** dereference of smart pointer - non const way */
|
||
|
FORCEINLINE Tcls* operator -> () {assert(m_pT != NULL); return m_pT;};
|
||
|
|
||
|
/** raw pointer casting operator - const way */
|
||
|
FORCEINLINE operator const Tcls*() const {assert(m_pT == NULL); return m_pT;}
|
||
|
|
||
|
/** raw pointer casting operator - non-const way */
|
||
|
FORCEINLINE operator Tcls*() {assert(m_pT == NULL); return m_pT;}
|
||
|
|
||
|
/** operator & to support output arguments */
|
||
|
FORCEINLINE Tcls** operator &() {assert(m_pT == NULL); return &m_pT;}
|
||
|
|
||
|
/** assignment operator from raw ptr */
|
||
|
FORCEINLINE CCountedPtr& operator = (Tcls* pT) {Assign(pT); return *this;}
|
||
|
|
||
|
/** assignment operator from another smart ptr */
|
||
|
FORCEINLINE CCountedPtr& operator = (CCountedPtr& src) {Assign(src.m_pT); return *this;}
|
||
|
|
||
|
/** assignment operator helper */
|
||
|
FORCEINLINE void Assign(Tcls* pT);
|
||
|
|
||
|
/** one way how to test for NULL value */
|
||
|
FORCEINLINE bool IsNull() const {return m_pT == NULL;}
|
||
|
|
||
|
/** another way how to test for NULL value */
|
||
|
FORCEINLINE bool operator == (const CCountedPtr& sp) const {return m_pT == sp.m_pT;}
|
||
|
|
||
|
/** yet another way how to test for NULL value */
|
||
|
FORCEINLINE bool operator != (const CCountedPtr& sp) const {return m_pT != sp.m_pT;}
|
||
|
|
||
|
/** assign pointer w/o incrementing ref count */
|
||
|
FORCEINLINE void Attach(Tcls* pT) {Release(); m_pT = pT;}
|
||
|
|
||
|
/** detach pointer w/o decrementing ref count */
|
||
|
FORCEINLINE Tcls* Detach() {Tcls* pT = m_pT; m_pT = NULL; return pT;}
|
||
|
};
|
||
|
|
||
|
template <class Tcls_>
|
||
|
FORCEINLINE void CCountedPtr<Tcls_>::Assign(Tcls* pT)
|
||
|
{
|
||
|
// if they are the same, we do nothing
|
||
|
if (pT != m_pT) {
|
||
|
if (pT) pT->AddRef(); // AddRef new pointer if any
|
||
|
Tcls* pTold = m_pT; // save original ptr
|
||
|
m_pT = pT; // update m_pT to new value
|
||
|
if (pTold) pTold->Release(); // release old ptr if any
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif /* COUNTEDPTR_HPP */
|