1// AutoLocker.h
2//
3// Copyright (c) 2004, Ingo Weinhold (bonefish@cs.tu-berlin.de)
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22//
23// Except as contained in this notice, the name of a copyright holder shall
24// not be used in advertising or otherwise to promote the sale, use or other
25// dealings in this Software without prior written authorization of the
26// copyright holder.
27
28#ifndef AUTO_LOCKER_H
29#define AUTO_LOCKER_H
30
31#include <SupportDefs.h>
32
33// locking
34
35// AutoLockerStandardLocking
36template<typename Lockable>
37class AutoLockerStandardLocking {
38public:
39	inline bool Lock(Lockable *lockable)
40	{
41		return lockable->Lock();
42	}
43
44	inline void Unlock(Lockable *lockable)
45	{
46		lockable->Unlock();
47	}
48};
49
50// AutoLockerReadLocking
51template<typename Lockable>
52class AutoLockerReadLocking {
53public:
54	inline bool Lock(Lockable *lockable)
55	{
56		return lockable->ReadLock();
57	}
58
59	inline void Unlock(Lockable *lockable)
60	{
61		lockable->ReadUnlock();
62	}
63};
64
65// AutoLockerWriteLocking
66template<typename Lockable>
67class AutoLockerWriteLocking {
68public:
69	inline bool Lock(Lockable *lockable)
70	{
71		return lockable->WriteLock();
72	}
73
74	inline void Unlock(Lockable *lockable)
75	{
76		lockable->WriteUnlock();
77	}
78};
79
80// AutoLocker
81template<typename Lockable,
82		 typename Locking = AutoLockerStandardLocking<Lockable> >
83class AutoLocker {
84private:
85	typedef AutoLocker<Lockable, Locking>	ThisClass;
86public:
87	inline AutoLocker(Lockable *lockable, bool alreadyLocked = false)
88		: fLockable(lockable),
89		  fLocked(fLockable && alreadyLocked)
90	{
91		if (!fLocked)
92			_Lock();
93	}
94
95	inline AutoLocker(Lockable &lockable, bool alreadyLocked = false)
96		: fLockable(&lockable),
97		  fLocked(fLockable && alreadyLocked)
98	{
99		if (!fLocked)
100			_Lock();
101	}
102
103	inline ~AutoLocker()
104	{
105		Unlock();
106	}
107
108	inline void SetTo(Lockable *lockable, bool alreadyLocked)
109	{
110		Unlock();
111		fLockable = lockable;
112		fLocked = alreadyLocked;
113		if (!fLocked)
114			_Lock();
115	}
116
117	inline void SetTo(Lockable &lockable, bool alreadyLocked)
118	{
119		SetTo(&lockable, alreadyLocked);
120	}
121
122	inline void Unset()
123	{
124		Unlock();
125	}
126
127	inline AutoLocker<Lockable, Locking> &operator=(Lockable *lockable)
128	{
129		SetTo(lockable);
130		return *this;
131	}
132
133	inline AutoLocker<Lockable, Locking> &operator=(Lockable &lockable)
134	{
135		SetTo(&lockable);
136		return *this;
137	}
138
139	inline bool IsLocked() const	{ return fLocked; }
140
141	inline void Unlock()
142	{
143		if (fLockable && fLocked) {
144			fLocking.Unlock(fLockable);
145			fLocked = false;
146		}
147	}
148
149	inline operator bool() const	{ return fLocked; }
150
151private:
152	inline void _Lock()
153	{
154		if (fLockable)
155			fLocked = fLocking.Lock(fLockable);
156	}
157
158private:
159	Lockable	*fLockable;
160	bool		fLocked;
161	Locking		fLocking;
162};
163
164#endif	// AUTO_LOCKER_H
165