Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /******************************************************************************␊ |
2 | *␊ |
3 | * $Id: $␊ |
4 | *␊ |
5 | * Copyright (C) 1997-2011 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 | ␊ |
163 |