xref: /haiku/headers/private/shared/AutoLocker.h (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
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 
12 namespace BPrivate {
13 
14 // AutoLockerStandardLocking
15 template<typename Lockable>
16 class AutoLockerStandardLocking {
17 public:
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
30 template<typename Lockable>
31 class AutoLockerHandlerLocking {
32 public:
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
45 template<typename Lockable>
46 class AutoLockerReadLocking {
47 public:
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
60 template<typename Lockable>
61 class AutoLockerWriteLocking {
62 public:
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
75 template<typename Lockable,
76 		 typename Locking = AutoLockerStandardLocking<Lockable> >
77 class AutoLocker {
78 private:
79 	typedef AutoLocker<Lockable, Locking>	ThisClass;
80 public:
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 Lockable* Get()
159 	{
160 		return fLockable;
161 	}
162 
163 	inline Lockable* Detach()
164 	{
165 		Lockable* res = fLockable;
166 		fLockable = NULL;
167 		fLocked = false;
168 		return res;
169 	}
170 
171 	inline AutoLocker<Lockable, Locking>& operator=(Lockable* lockable)
172 	{
173 		SetTo(lockable);
174 		return *this;
175 	}
176 
177 	inline AutoLocker<Lockable, Locking>& operator=(Lockable& lockable)
178 	{
179 		SetTo(&lockable);
180 		return *this;
181 	}
182 
183 	inline bool IsLocked() const	{ return fLocked; }
184 
185 	inline operator bool() const	{ return fLocked; }
186 
187 protected:
188 	Lockable*	fLockable;
189 	Locking		fLocking;
190 	bool		fLocked;
191 };
192 
193 
194 }	// namespace BPrivate
195 
196 using ::BPrivate::AutoLocker;
197 using ::BPrivate::AutoLockerHandlerLocking;
198 using ::BPrivate::AutoLockerReadLocking;
199 using ::BPrivate::AutoLockerWriteLocking;
200 
201 #endif	// _AUTO_LOCKER_H
202