1/*
2 * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5#ifndef _AUTO_LOCKER_H
6#define _AUTO_LOCKER_H
7
8
9#include <stddef.h>
10
11
12namespace BPrivate {
13
14// AutoLockerStandardLocking
15template<typename Lockable>
16class AutoLockerStandardLocking {
17public:
18 inline bool Lock(Lockable* lockable)
19 {
20 return lockable->Lock();
21 }
22
23 inline void Unlock(Lockable* lockable)
24 {
25 lockable->Unlock();
26 }
27};
28
29// AutoLockerHandlerLocking
30template<typename Lockable>
31class AutoLockerHandlerLocking {
32public:
33 inline bool Lock(Lockable* lockable)
34 {
35 return lockable->LockLooper();
36 }
37
38 inline void Unlock(Lockable* lockable)
39 {
40 lockable->UnlockLooper();
41 }
42};
43
44// AutoLockerReadLocking
45template<typename Lockable>
46class AutoLockerReadLocking {
47public:
48 inline bool Lock(Lockable* lockable)
49 {
50 return lockable->ReadLock();
51 }
52
53 inline void Unlock(Lockable* lockable)
54 {
55 lockable->ReadUnlock();
56 }
57};
58
59// AutoLockerWriteLocking
60template<typename Lockable>
61class AutoLockerWriteLocking {
62public:
63 inline bool Lock(Lockable* lockable)
64 {
65 return lockable->WriteLock();
66 }
67
68 inline void Unlock(Lockable* lockable)
69 {
70 lockable->WriteUnlock();
71 }
72};
73
74// AutoLocker
75template<typename Lockable,
76 typename Locking = AutoLockerStandardLocking<Lockable> >
77class AutoLocker {
78private:
79 typedef AutoLocker<Lockable, Locking> ThisClass;
80public:
81 inline AutoLocker()
82 :
83 fLockable(NULL),
84 fLocked(false)
85 {
86 }
87
88 inline AutoLocker(const Locking& locking)
89 :
90 fLockable(NULL),
91 fLocking(locking),
92 fLocked(false)
93 {
94 }
95
96 inline AutoLocker(Lockable* lockable, bool alreadyLocked = false,
97 bool lockIfNotLocked = true)
98 :
99 fLockable(lockable),
100 fLocked(fLockable && alreadyLocked)
101 {
102 if (!alreadyLocked && lockIfNotLocked)
103 Lock();
104 }
105
106 inline AutoLocker(Lockable& lockable, bool alreadyLocked = false,
107 bool lockIfNotLocked = true)
108 :
109 fLockable(&lockable),
110 fLocked(fLockable && alreadyLocked)
111 {
112 if (!alreadyLocked && lockIfNotLocked)
113 Lock();
114 }
115
116 inline ~AutoLocker()
117 {
118 Unlock();
119 }
120
121 inline void SetTo(Lockable* lockable, bool alreadyLocked,
122 bool lockIfNotLocked = true)
123 {
124 Unlock();
125 fLockable = lockable;
126 fLocked = (lockable && alreadyLocked);
127 if (!alreadyLocked && lockIfNotLocked)
128 Lock();
129 }
130
131 inline void SetTo(Lockable& lockable, bool alreadyLocked,
132 bool lockIfNotLocked = true)
133 {
134 SetTo(&lockable, alreadyLocked, lockIfNotLocked);
135 }
136
137 inline void Unset()
138 {
139 Unlock();
140 Detach();
141 }
142
143 inline bool Lock()
144 {
145 if (fLockable && !fLocked)
146 fLocked = fLocking.Lock(fLockable);
147 return fLocked;
148 }
149
150 inline void Unlock()
151 {
152 if (fLockable && fLocked) {
153 fLocking.Unlock(fLockable);
154 fLocked = false;
155 }
156 }
157
158 inline void Detach()
159 {
160 fLockable = NULL;
161 fLocked = false;
162 }
163
164 inline AutoLocker<Lockable, Locking>& operator=(Lockable* lockable)
165 {
166 SetTo(lockable);
167 return *this;
168 }
169
170 inline AutoLocker<Lockable, Locking>& operator=(Lockable& lockable)
171 {
172 SetTo(&lockable);
173 return *this;
174 }
175
176 inline bool IsLocked() const { return fLocked; }
177
178 inline operator bool() const { return fLocked; }
179
180protected:
181 Lockable* fLockable;
182 Locking fLocking;
183 bool fLocked;
184};
185
186
187} // namespace BPrivate
188
189using ::BPrivate::AutoLocker;
190using ::BPrivate::AutoLockerHandlerLocking;
191using ::BPrivate::AutoLockerReadLocking;
192using ::BPrivate::AutoLockerWriteLocking;
193
194#endif // _AUTO_LOCKER_H