blob: 806401e88caa879a02102a22c03db7187bc1698b [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Locking protocol classes for member function automatic operations.
20 * This header covers ucommon access related classes. These are used to
21 * provide automatic management of locks and synchronization objects through
22 * common virtual base classes which can be used with automatic objects.
23 * These classes are related to "protocols" and are used in conjunction
24 * with smart pointer/referencing classes. The access interface supports
25 * member functions to acquire a lock when entered and automatically
26 * release the lock when the member function returns that are used in
27 * conjunction with special referencing smart pointers.
28 * @file ucommon/access.h
29 */
30
31// we do this twice because of some bizarre issue in just this file that
32// otherwise breaks doxygen and lists all items outside the namespace...
33#include <ucommon/platform.h>
34
35#ifndef _UCOMMON_ACCESS_H_
36#define _UCOMMON_ACCESS_H_
37
38#ifndef _UCOMMON_CPR_H_
39#include <ucommon/cpr.h>
40#endif
41
42#ifndef _UCOMMON_PROTOCOLS_H_
43#include <ucommon/protocols.h>
44#endif
45
46NAMESPACE_UCOMMON
47
48/**
49 * Common unlock protocol for locking protocol interface classes.
50 * This is to assure _unlock is a common base virtual method.
51 * @author David Sugar <dyfet@gnutelephony.org>
52 */
53class __EXPORT UnlockAccess
54{
55public:
56 virtual ~UnlockAccess();
57
58protected:
59 virtual void _unlock(void) = 0;
60};
61
62/**
63 * An exclusive locking protocol interface base.
64 * This is an abstract class to form objects that will operate under an
65 * exclusive lock while being actively referenced by a smart pointer.
66 * @author David Sugar <dyfet@gnutelephony.org>
67 */
68class __EXPORT ExclusiveAccess : public UnlockAccess
69{
70protected:
71 virtual ~ExclusiveAccess();
72
73 virtual void _lock(void) = 0;
74
75public:
76 /**
77 * Access interface to exclusive lock the object.
78 */
79 inline void exclusive_lock(void)
80 {return _lock();}
81
82 /**
83 * Access interface to release a lock.
84 */
85 inline void release_exclusive(void)
86 {return _unlock();}
87};
88
89/**
90 * An exclusive locking access interface base.
91 * This is an abstract class to form objects that will operate under an
92 * exclusive lock while being actively referenced by a smart pointer.
93 * @author David Sugar <dyfet@gnutelephony.org>
94 */
95class __EXPORT SharedAccess : protected UnlockAccess
96{
97protected:
98 virtual ~SharedAccess();
99
100protected:
101 /**
102 * Access interface to share lock the object.
103 */
104 virtual void _share(void) = 0;
105
106public:
107 /**
108 * Share the lock with other referencers. Many of our shared locking
109 * objects support the ability to switch between shared and exclusive
110 * mode. This derived protocol member allows one to restore the lock
111 * to shared mode after it has been made exclusive.
112 */
113 virtual void share(void);
114
115 /**
116 * Convert object to an exclusive lock. Many of our shared locking
117 * objects such as the "conditional lock" support the ability to switch
118 * between shared and exclusive locking modes. This derived protocol
119 * member allows one to temporarily assert exclusive locking when tied
120 * to such methods.
121 */
122 virtual void exclusive(void);
123
124 inline void shared_lock(void)
125 {return _share();}
126
127 inline void release_share(void)
128 {return _unlock();}
129};
130
131/**
132 * A kind of smart pointer object to support exclusive locking protocol.
133 * This object initiates an exclusive lock for the object being referenced when
134 * it is instantiated, and releases the exclusive lock when it is destroyed.
135 * You would pass the pointer an object that has the Exclusive as a base class.
136 * @author David Sugar <dyfet@gnutelephony.org>
137 */
138class __EXPORT exclusive_access
139{
140private:
141 ExclusiveAccess *lock;
142
143public:
144 /**
145 * Create an instance of an exclusive object reference.
146 * @param object containing Exclusive base class protocol to lock.
147 */
148 exclusive_access(ExclusiveAccess *object);
149
150 /**
151 * Destroy reference to exclusively locked object, release lock.
152 */
153 ~exclusive_access();
154
155 /**
156 * Test if the reference holds an active lock.
157 * @return true if is not locking an object.
158 */
159 inline bool operator!() const
160 {return lock == NULL;};
161
162 /**
163 * Test if the reference holds an active lock.
164 * @return true if locking an object.
165 */
166 inline operator bool() const
167 {return lock != NULL;};
168
169 /**
170 * Release a held lock programmatically. This can be used to de-reference
171 * the object being exclusively locked without having to wait for the
172 * destructor to be called when the exclusive_lock falls out of scope.
173 */
174 void release(void);
175};
176
177/**
178 * A kind of smart pointer object to support shared locking protocol.
179 * This object initiates a shared lock for the object being referenced when
180 * it is instantiated, and releases the shared lock when it is destroyed.
181 * You would pass the pointer an object that has the Shared as a base class.
182 * @author David Sugar <dyfet@gnutelephony.org>
183 */
184class __EXPORT shared_access
185{
186private:
187 SharedAccess *lock;
188 int state;
189 bool modify;
190
191public:
192 /**
193 * Create an instance of an exclusive object reference.
194 * @param object containing Exclusive base class protocol to lock.
195 */
196 shared_access(SharedAccess *object);
197
198 /**
199 * Destroy reference to shared locked object, release lock.
200 */
201 ~shared_access();
202
203 /**
204 * Test if the reference holds an active lock.
205 * @return true if is not locking an object.
206 */
207 inline bool operator!() const
208 {return lock == NULL;};
209
210 /**
211 * Test if the reference holds an active lock.
212 * @return true if locking an object.
213 */
214 inline operator bool() const
215 {return lock != NULL;};
216
217 /**
218 * Release a held lock programmatically. This can be used to de-reference
219 * the object being share locked without having to wait for the
220 * destructor to be called when the shared_lock falls out of scope.
221 */
222 void release(void);
223
224 /**
225 * Call exclusive access on referenced objects protocol.
226 */
227 void exclusive(void);
228
229 /**
230 * Restore shared access on referenced objects protocol.
231 */
232 void share(void);
233};
234
235/**
236 * Convenience function to exclusively lock an object through it's protocol.
237 * @param object to lock.
238 */
239inline void lock(ExclusiveAccess& object)
240 {object.exclusive_lock();}
241
242/**
243 * Convenience function to unlock an exclusive object through it's protocol.
244 * @param object to unlock.
245 */
246inline void unlock(ExclusiveAccess& object)
247 {object.release_exclusive();}
248
249/**
250 * Convenience function to access (lock) shared object through it's protocol.
251 * @param object to share lock.
252 */
253inline void access(SharedAccess& object)
254 {object.shared_lock();}
255
256/**
257 * Convenience function to unlock shared object through it's protocol.
258 * @param object to unlock.
259 */
260inline void release(SharedAccess& object)
261 {object.release_share();}
262
263/**
264 * Convenience function to exclusive lock shared object through it's protocol.
265 * @param object to exclusive lock.
266 */
267inline void exclusive(SharedAccess& object)
268 {object.exclusive();}
269
270/**
271 * Convenience function to restore shared locking for object through it's protocol.
272 * @param object to restore shared locking.
273 */
274inline void share(SharedAccess& object)
275 {object.share();}
276
277/**
278 * Convenience type to use for object referencing an exclusive object.
279 */
280typedef exclusive_access exlock_t;
281
282/**
283 * Convenience type to use for object referencing a shared object.
284 */
285typedef shared_access shlock_t;
286
287/**
288 * Convenience function to release a reference to an exclusive lock.
289 * @param reference to object referencing exclusive locked object.
290 */
291inline void release(exlock_t &reference)
292 {reference.release();}
293
294/**
295 * Convenience function to release a reference to a shared lock.
296 * @param reference to object referencing shared locked object.
297 */
298inline void release(shlock_t &reference)
299 {reference.release();}
300
301// Special macros to allow member functions of an object with a protocol
302// to create self locking states while the member functions are called by
303// placing an exclusive_lock or shared_lock smart object on their stack
304// frame to reference their self.
305
306#define exclusive_object() exlock_t __autolock__ = this
307#define protected_object() shlock_t __autolock__ = this
308#define exclusive_locking(x) exlock_t __autolock__ = &x
309#define protected_locking(x) shlock_t __autolock__ = &x
310
311END_NAMESPACE
312
313#endif