yapf/countedptr.hpp
changeset 3900 2c84ed52709d
child 4434 a08cb4b5c179
equal deleted inserted replaced
3899:5ba7f20a14ca 3900:2c84ed52709d
       
     1 /* $Id$ */
       
     2 
       
     3 #ifndef COUNTEDPTR_HPP
       
     4 #define COUNTEDPTR_HPP
       
     5 
       
     6 /** @file CCountedPtr - smart pointer implementation */
       
     7 
       
     8 /** CCountedPtr - simple reference counting smart pointer.
       
     9 *
       
    10 *     One of the standard ways how to maintain object's lifetime.
       
    11 *
       
    12 *     See http://ootips.org/yonat/4dev/smart-pointers.html for more
       
    13 *   general info about smart pointers.
       
    14 *
       
    15 *     This class implements ref-counted pointer for objects/interfaces that
       
    16 *   support AddRef() and Release() methods.
       
    17 */
       
    18 template <class Tcls_>
       
    19 class CCountedPtr {
       
    20 	/** redefine the template argument to make it visible for derived classes */
       
    21 public:
       
    22 	typedef Tcls_ Tcls;
       
    23 
       
    24 protected:
       
    25 	/** here we hold our pointer to the target */
       
    26 	Tcls* m_pT;
       
    27 
       
    28 public:
       
    29 	/** default (NULL) construct or construct from a raw pointer */
       
    30 	FORCEINLINE CCountedPtr(Tcls* pObj = NULL) : m_pT(pObj) {AddRef();};
       
    31 
       
    32 	/** copy constructor (invoked also when initializing from another smart ptr) */
       
    33 	FORCEINLINE CCountedPtr(const CCountedPtr& src) : m_pT(src.m_pT) {AddRef();};
       
    34 
       
    35 	/** destructor releasing the reference */
       
    36 	FORCEINLINE ~CCountedPtr() {Release();};
       
    37 
       
    38 protected:
       
    39 	/** add one ref to the underlaying object */
       
    40 	FORCEINLINE void AddRef() {if (m_pT != NULL) m_pT->AddRef();}
       
    41 
       
    42 public:
       
    43 	/** release smart pointer (and decrement ref count) if not null */
       
    44 	FORCEINLINE void Release() {if (m_pT != NULL) {m_pT->Release(); m_pT = NULL;}}
       
    45 
       
    46 	/** dereference of smart pointer - const way */
       
    47 	FORCEINLINE const Tcls* operator -> () const {assert(m_pT != NULL); return m_pT;};
       
    48 
       
    49 	/** dereference of smart pointer - non const way */
       
    50 	FORCEINLINE Tcls* operator -> () {assert(m_pT != NULL); return m_pT;};
       
    51 
       
    52 	/** raw pointer casting operator - const way */
       
    53 	FORCEINLINE operator const Tcls*() const {assert(m_pT == NULL); return m_pT;}
       
    54 
       
    55 	/** raw pointer casting operator - non-const way */
       
    56 	FORCEINLINE operator Tcls*() {assert(m_pT == NULL); return m_pT;}
       
    57 
       
    58 	/** operator & to support output arguments */
       
    59 	FORCEINLINE Tcls** operator &() {assert(m_pT == NULL); return &m_pT;}
       
    60 
       
    61 	/** assignment operator from raw ptr */
       
    62 	FORCEINLINE CCountedPtr& operator = (Tcls* pT) {Assign(pT); return *this;}
       
    63 
       
    64 	/** assignment operator from another smart ptr */
       
    65 	FORCEINLINE CCountedPtr& operator = (CCountedPtr& src) {Assign(src.m_pT); return *this;}
       
    66 
       
    67 	/** assignment operator helper */
       
    68 	FORCEINLINE void Assign(Tcls* pT);
       
    69 
       
    70 	/** one way how to test for NULL value */
       
    71 	FORCEINLINE bool IsNull() const {return m_pT == NULL;}
       
    72 
       
    73 	/** another way how to test for NULL value */
       
    74 	FORCEINLINE bool operator == (const CCountedPtr& sp) const {return m_pT == sp.m_pT;}
       
    75 
       
    76 	/** yet another way how to test for NULL value */
       
    77 	FORCEINLINE bool operator != (const CCountedPtr& sp) const	{return m_pT != sp.m_pT;}
       
    78 
       
    79 	/** assign pointer w/o incrementing ref count */
       
    80 	FORCEINLINE void Attach(Tcls* pT) {Release(); m_pT = pT;}
       
    81 
       
    82 	/** detach pointer w/o decrementing ref count */
       
    83 	FORCEINLINE Tcls* Detach() {Tcls* pT = m_pT; m_pT = NULL; return pT;}
       
    84 };
       
    85 
       
    86 template <class Tcls_>
       
    87 FORCEINLINE void CCountedPtr<Tcls_>::Assign(Tcls* pT)
       
    88 {
       
    89 	// if they are the same, we do nothing
       
    90 	if (pT != m_pT) {
       
    91 		if (pT) pT->AddRef();        // AddRef new pointer if any
       
    92 		Tcls* pTold = m_pT;          // save original ptr
       
    93 		m_pT = pT;                   // update m_pT to new value
       
    94 		if (pTold) pTold->Release(); // release old ptr if any
       
    95 	}
       
    96 }
       
    97 
       
    98 
       
    99 #endif /* COUNTEDPTR_HPP */