|
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 */ |