xref: /haiku/headers/private/kernel/util/AutoLock.h (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
1 /*
2  * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #ifndef KERNEL_UTIL_AUTO_LOCKER_H
7 #define KERNEL_UTIL_AUTO_LOCKER_H
8 
9 #include <lock.h>
10 
11 namespace BPrivate {
12 
13 // AutoLockerStandardLocking
14 template<typename Lockable>
15 class AutoLockerStandardLocking {
16 public:
17 	inline bool Lock(Lockable *lockable)
18 	{
19 		return lockable->Lock();
20 	}
21 
22 	inline void Unlock(Lockable *lockable)
23 	{
24 		lockable->Unlock();
25 	}
26 };
27 
28 // AutoLockerReadLocking
29 template<typename Lockable>
30 class AutoLockerReadLocking {
31 public:
32 	inline bool Lock(Lockable *lockable)
33 	{
34 		return lockable->ReadLock();
35 	}
36 
37 	inline void Unlock(Lockable *lockable)
38 	{
39 		lockable->ReadUnlock();
40 	}
41 };
42 
43 // AutoLockerWriteLocking
44 template<typename Lockable>
45 class AutoLockerWriteLocking {
46 public:
47 	inline bool Lock(Lockable *lockable)
48 	{
49 		return lockable->WriteLock();
50 	}
51 
52 	inline void Unlock(Lockable *lockable)
53 	{
54 		lockable->WriteUnlock();
55 	}
56 };
57 
58 // AutoLocker
59 template<typename Lockable,
60 		 typename Locking = AutoLockerStandardLocking<Lockable> >
61 class AutoLocker {
62 private:
63 	typedef AutoLocker<Lockable, Locking>	ThisClass;
64 public:
65 	inline AutoLocker()
66 		: fLockable(NULL),
67 		  fLocked(false)
68 	{
69 	}
70 
71 	inline AutoLocker(Lockable *lockable, bool alreadyLocked = false)
72 		: fLockable(lockable),
73 		  fLocked(fLockable && alreadyLocked)
74 	{
75 		if (!fLocked)
76 			_Lock();
77 	}
78 
79 	inline AutoLocker(Lockable &lockable, bool alreadyLocked = false)
80 		: fLockable(&lockable),
81 		  fLocked(fLockable && alreadyLocked)
82 	{
83 		if (!fLocked)
84 			_Lock();
85 	}
86 
87 	inline ~AutoLocker()
88 	{
89 		_Unlock();
90 	}
91 
92 	inline void SetTo(Lockable *lockable, bool alreadyLocked)
93 	{
94 		_Unlock();
95 		fLockable = lockable;
96 		fLocked = alreadyLocked;
97 		if (!fLocked)
98 			_Lock();
99 	}
100 
101 	inline void SetTo(Lockable &lockable, bool alreadyLocked)
102 	{
103 		SetTo(&lockable, alreadyLocked);
104 	}
105 
106 	inline void Unset()
107 	{
108 		_Unlock();
109 	}
110 
111 	inline void Unlock()
112 	{
113 		_Unlock();
114 	}
115 
116 	inline void Detach()
117 	{
118 		fLockable = NULL;
119 		fLocked = false;
120 	}
121 
122 	inline AutoLocker<Lockable, Locking> &operator=(Lockable *lockable)
123 	{
124 		SetTo(lockable);
125 		return *this;
126 	}
127 
128 	inline AutoLocker<Lockable, Locking> &operator=(Lockable &lockable)
129 	{
130 		SetTo(&lockable);
131 		return *this;
132 	}
133 
134 	inline bool IsLocked() const	{ return fLocked; }
135 
136 	inline operator bool() const	{ return fLocked; }
137 
138 private:
139 	inline void _Lock()
140 	{
141 		if (fLockable)
142 			fLocked = fLocking.Lock(fLockable);
143 	}
144 
145 	inline void _Unlock()
146 	{
147 		if (fLockable && fLocked) {
148 			fLocking.Unlock(fLockable);
149 			fLocked = false;
150 		}
151 	}
152 
153 private:
154 	Lockable	*fLockable;
155 	bool		fLocked;
156 	Locking		fLocking;
157 };
158 
159 
160 // #pragma mark -
161 // #pragma mark ----- instantiations -----
162 
163 // MutexLocking
164 class MutexLocking {
165 public:
166 	inline bool Lock(mutex *lockable)
167 	{
168 		mutex_lock(lockable);
169 		return true;
170 	}
171 
172 	inline void Unlock(mutex *lockable)
173 	{
174 		mutex_unlock(lockable);
175 	}
176 };
177 
178 // MutexLocker
179 typedef AutoLocker<mutex, MutexLocking> MutexLocker;
180 
181 // RecursiveLockLocking
182 class RecursiveLockLocking {
183 public:
184 	inline bool Lock(recursive_lock *lockable)
185 	{
186 		recursive_lock_lock(lockable);
187 		return true;
188 	}
189 
190 	inline void Unlock(recursive_lock *lockable)
191 	{
192 		recursive_lock_unlock(lockable);
193 	}
194 };
195 
196 // RecursiveLocker
197 typedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker;
198 
199 // BenaphoreLocking
200 class BenaphoreLocking {
201 public:
202 	inline bool Lock(benaphore *lockable)
203 	{
204 		return benaphore_lock(lockable) == B_OK;
205 	}
206 
207 	inline void Unlock(benaphore *lockable)
208 	{
209 		benaphore_unlock(lockable);
210 	}
211 };
212 
213 // BenaphoreLocker
214 typedef AutoLocker<benaphore, BenaphoreLocking> BenaphoreLocker;
215 
216 }	// namespace BPrivate
217 
218 using BPrivate::AutoLocker;
219 using BPrivate::MutexLocker;
220 using BPrivate::RecursiveLocker;
221 using BPrivate::BenaphoreLocker;
222 
223 #endif	// KERNEL_UTIL_AUTO_LOCKER_H
224