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