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