xref: /haiku/headers/private/shared/AutoLocker.h (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
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 // AutoLockerReadLocking
30 template<typename Lockable>
31 class AutoLockerReadLocking {
32 public:
33 	inline bool Lock(Lockable* lockable)
34 	{
35 		return lockable->ReadLock();
36 	}
37 
38 	inline void Unlock(Lockable* lockable)
39 	{
40 		lockable->ReadUnlock();
41 	}
42 };
43 
44 // AutoLockerWriteLocking
45 template<typename Lockable>
46 class AutoLockerWriteLocking {
47 public:
48 	inline bool Lock(Lockable* lockable)
49 	{
50 		return lockable->WriteLock();
51 	}
52 
53 	inline void Unlock(Lockable* lockable)
54 	{
55 		lockable->WriteUnlock();
56 	}
57 };
58 
59 // AutoLocker
60 template<typename Lockable,
61 		 typename Locking = AutoLockerStandardLocking<Lockable> >
62 class AutoLocker {
63 private:
64 	typedef AutoLocker<Lockable, Locking>	ThisClass;
65 public:
66 	inline AutoLocker()
67 		:
68 		fLockable(NULL),
69 		fLocked(false)
70 	{
71 	}
72 
73 	inline AutoLocker(const Locking& locking)
74 		:
75 		fLockable(NULL),
76 		fLocking(locking),
77 		fLocked(false)
78 	{
79 	}
80 
81 	inline AutoLocker(Lockable* lockable, bool alreadyLocked = false,
82 		bool lockIfNotLocked = true)
83 		:
84 		fLockable(lockable),
85 		fLocked(fLockable && alreadyLocked)
86 	{
87 		if (!alreadyLocked && lockIfNotLocked)
88 			Lock();
89 	}
90 
91 	inline AutoLocker(Lockable& lockable, bool alreadyLocked = false,
92 		bool lockIfNotLocked = true)
93 		:
94 		fLockable(&lockable),
95 		fLocked(fLockable && alreadyLocked)
96 	{
97 		if (!alreadyLocked && lockIfNotLocked)
98 			Lock();
99 	}
100 
101 	inline ~AutoLocker()
102 	{
103 		Unlock();
104 	}
105 
106 	inline void SetTo(Lockable* lockable, bool alreadyLocked,
107 		bool lockIfNotLocked = true)
108 	{
109 		Unlock();
110 		fLockable = lockable;
111 		fLocked = (lockable && alreadyLocked);
112 		if (!alreadyLocked && lockIfNotLocked)
113 			Lock();
114 	}
115 
116 	inline void SetTo(Lockable& lockable, bool alreadyLocked,
117 		bool lockIfNotLocked = true)
118 	{
119 		SetTo(&lockable, alreadyLocked, lockIfNotLocked);
120 	}
121 
122 	inline void Unset()
123 	{
124 		Unlock();
125 		Detach();
126 	}
127 
128 	inline bool Lock()
129 	{
130 		if (fLockable && !fLocked)
131 			fLocked = fLocking.Lock(fLockable);
132 		return fLocked;
133 	}
134 
135 	inline void Unlock()
136 	{
137 		if (fLockable && fLocked) {
138 			fLocking.Unlock(fLockable);
139 			fLocked = false;
140 		}
141 	}
142 
143 	inline void Detach()
144 	{
145 		fLockable = NULL;
146 		fLocked = false;
147 	}
148 
149 	inline AutoLocker<Lockable, Locking>& operator=(Lockable* lockable)
150 	{
151 		SetTo(lockable);
152 		return *this;
153 	}
154 
155 	inline AutoLocker<Lockable, Locking>& operator=(Lockable& lockable)
156 	{
157 		SetTo(&lockable);
158 		return *this;
159 	}
160 
161 	inline bool IsLocked() const	{ return fLocked; }
162 
163 	inline operator bool() const	{ return fLocked; }
164 
165 protected:
166 	Lockable*	fLockable;
167 	Locking		fLocking;
168 	bool		fLocked;
169 };
170 
171 
172 }	// namespace BPrivate
173 
174 using ::BPrivate::AutoLocker;
175 using ::BPrivate::AutoLockerReadLocking;
176 using ::BPrivate::AutoLockerWriteLocking;
177 
178 #endif	// _AUTO_LOCKER_H
179