|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
|
6 * |
|
7 * Permission to use, copy, modify, and distribute this software and its |
|
8 * documentation under the terms of the GNU General Public License is hereby |
|
9 * granted. No representations are made about the suitability of this software |
|
10 * for any purpose. It is provided "as is" without express or implied warranty. |
|
11 * See the GNU General Public License for more details. |
|
12 * |
|
13 * Documents produced by Doxygen are derivative works derived from the |
|
14 * input used in their production; they are not affected by this license. |
|
15 * |
|
16 */ |
|
17 |
|
18 #ifndef LOCKINGPTR_H |
|
19 #define LOCKINGPTR_H |
|
20 |
|
21 /*! @brief Abstract interface for lockable objects. |
|
22 * |
|
23 * By implementing this interface, a smart pointer can be created which |
|
24 * will lock this object. This is used to prevent that an internal pointer |
|
25 * owned by a lockable object would become invalid when the object is removed from |
|
26 * memory, leaving the client with an invalid pointer. By letting the client use |
|
27 * a smart pointer instead of the real object the object will be locked into |
|
28 * memory until the pointer is no longer used, at which point the owner object will be |
|
29 * unlock and can be removed from memory. |
|
30 */ |
|
31 class LockableObj |
|
32 { |
|
33 public: |
|
34 LockableObj() : m_lockCount(0) {} |
|
35 virtual ~LockableObj() {} |
|
36 |
|
37 /*! Returns TRUE if the object is currently locked. */ |
|
38 bool isLocked() const { return m_lockCount>0; } |
|
39 |
|
40 //VC++6.0 workaround |
|
41 // protected: |
|
42 /*! Called when the object is locked. */ |
|
43 virtual void lock() const = 0; |
|
44 |
|
45 /*! Called when the object is unlocked. */ |
|
46 virtual void unlock() const = 0; |
|
47 |
|
48 //VC++6.0 workaround |
|
49 // private: |
|
50 // template<class T> friend class LockingPtr; |
|
51 int m_lockCount; |
|
52 }; |
|
53 |
|
54 /*! @brief Smart pointer which keeps a lock on the owner of the pointer. |
|
55 * |
|
56 * With the pointer an owner object derived from LockableObj is associated. |
|
57 * As long as the smart object exists it will keep a lock on the obj by calling |
|
58 * LockableObj::lock(). Smart pointers can be copied and passed by value. As |
|
59 * soon as there or no more smart pointer references to the object, |
|
60 * LockableObj::unlock() will be called automatically. |
|
61 */ |
|
62 template<class T> class LockingPtr |
|
63 { |
|
64 LockableObj *m_owner; |
|
65 const T *m_ptr; |
|
66 |
|
67 public: |
|
68 /*! Creates a smart pointer for pointer \a p owned by object \a o. |
|
69 */ |
|
70 LockingPtr(const LockableObj *o,const T* p) |
|
71 { |
|
72 if (o->m_lockCount==0) o->lock(); |
|
73 m_owner = (LockableObj *)o; |
|
74 m_owner->m_lockCount++; |
|
75 m_ptr = p; |
|
76 } |
|
77 |
|
78 /*! Copies the smart pointer \a lp |
|
79 */ |
|
80 LockingPtr(const LockingPtr &lp) |
|
81 { |
|
82 m_ptr = lp.m_ptr; |
|
83 m_owner = lp.m_owner; |
|
84 m_owner->m_lockCount++; |
|
85 } |
|
86 |
|
87 /*! Assigns the smart pointer \a lp |
|
88 */ |
|
89 LockingPtr &operator=(const LockingPtr &lp) |
|
90 { |
|
91 m_owner->m_lockCount--; |
|
92 if (m_owner->m_lockCount==0) // no more references |
|
93 { |
|
94 m_owner->unlock(); |
|
95 } |
|
96 m_ptr = lp.m_ptr; |
|
97 m_owner = lp.m_owner; |
|
98 m_owner->m_lockCount++; |
|
99 return *this; |
|
100 } |
|
101 |
|
102 /*! Destroys the smart pointer, will unlock the owner. |
|
103 */ |
|
104 ~LockingPtr() |
|
105 { |
|
106 m_owner->m_lockCount--; |
|
107 if (m_owner->m_lockCount==0) // no more references |
|
108 { |
|
109 m_owner->unlock(); |
|
110 } |
|
111 } |
|
112 |
|
113 bool isNull() const |
|
114 { |
|
115 return m_ptr==0; |
|
116 } |
|
117 |
|
118 bool operator!() const |
|
119 { |
|
120 return !m_ptr; |
|
121 } |
|
122 |
|
123 bool operator==(T *p) const |
|
124 { |
|
125 return m_ptr==p; |
|
126 } |
|
127 |
|
128 bool operator==(const LockingPtr &lp) const |
|
129 { |
|
130 return m_ptr==lp.m_ptr; |
|
131 } |
|
132 |
|
133 bool operator!=(T *p) const |
|
134 { |
|
135 return m_ptr!=p; |
|
136 } |
|
137 |
|
138 bool operator!=(const LockingPtr &lp) const |
|
139 { |
|
140 return m_ptr!=lp.m_ptr; |
|
141 } |
|
142 |
|
143 /*! Dereference operator */ |
|
144 const T& operator* () const |
|
145 { |
|
146 return *m_ptr; |
|
147 } |
|
148 |
|
149 T* pointer() const |
|
150 { |
|
151 return (T*)m_ptr; |
|
152 } |
|
153 |
|
154 /*! Pointer operator */ |
|
155 T* operator-> () const |
|
156 { |
|
157 return (T*)m_ptr; |
|
158 } |
|
159 }; |
|
160 |
|
161 #endif // LOCKINGPTR_H |
|
162 |