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