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