xref: /haiku/docs/user/support/Locker.dox (revision 37fedaf8494b34aad811abcc49e79aa32943f880)
1/*
2 * Copyright 2007-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Niels Sascha Reedijk, niels.reedijk@gmail.com
7 *
8 * Corresponds to:
9 *		headers/os/support/Locker.h rev 36218
10 *		src/kits/support/Locker.cpp rev 32758
11 */
12
13/*!
14	\file Locker.h
15	\ingroup support
16	\ingroup libbe
17	\brief Provides locking class BLocker.
18*/
19
20
21/*!
22	\class BLocker
23	\ingroup support
24	\ingroup libbe
25	\brief Semaphore-type class for thread safety.
26
27	The BLocker interface is not merely a wrapper around a semaphore, but it
28	also has two advantages. First of all, it implements a benaphore.
29	A benaphore is in some ways more speed efficient,
30	because before it uses the internal semaphore, it first checks against a
31	variable that is only operated on with atomic operations. Setting a variable
32	is a lot more efficient than acquiring a semaphore, thus this type of locking
33	is much preferred.
34
35	It basically works as follows. Whenever you newly created BLocker object
36	receives a locking request, it atomically sets the benaphore variable to
37	\c 1. Then only additional calls from different threads will utilize the
38	semaphore. You can imagine that in many cases where you protect
39	of data that \em might be accessed by two or more concurrent threads, but
40	the chances of it happening being very small, the benaphore benefits the
41	most from it's speed.
42
43	The other feature of BLocker that improves basic semaphore handling is that
44	it allows for recursive locks. The following piece of code works with a
45	BLocker, but block inevitably with a semaphore. Let's pretend I call
46	\c Water():
47
48\code
49status_t
50Flower::Grow(int length)
51{
52    if (fLock->Lock()) {
53        fLength += length;
54        fLock->Unlock();
55        return B_OK;
56    } else {
57        return B_ERROR;
58    }
59}
60
61status_t
62Flower::Water(int amount)
63{
64    if (fLock->Lock()) {
65        status_t status = Grow(amount * 2);
66        fLock->Unlock();
67        return status;
68    } else {
69        return B_ERROR;
70    }
71}
72\endcode
73
74	This code would work because BLocker keeps track of the amount of lock
75	requests from the same thread. A normal semaphore would block in \c Grow()
76	because the semaphore would be acquired already. Please do make sure you
77	pair every Lock() with an Unlock() though, or you'll create a deadlock.
78*/
79
80
81/*!
82	\fn BLocker::BLocker()
83	\brief Constructor.
84
85	Create a new BLocker with the default name of some BLocker. This
86	BLocker will use the benaphore-style locking.
87
88	\note For debugging purposes, it's extremely convenient to actually give a
89    name to the object. In case of a deadlock, it's easier to track down which
90    BLocker object might have caused the problems.
91
92	\see BLocker(const char* name, bool benaphoreStyle) for all the options.
93*/
94
95
96/*!
97	\fn BLocker::BLocker(const char* name)
98	\brief Constructor.
99
100	Create a new BLocker with benaphore-style locking.
101
102	\param name A NULL-terminated string that contains the name of the
103				semaphore. Note that the length of the names are limited to
104				\c B_OS_NAME_LENGTH constant, which includes the \c \\0
105				character.
106
107	\see BLocker(const char* name, bool benaphoreStyle) for all the options.
108*/
109
110
111/*!
112	\fn BLocker::BLocker(bool benaphoreStyle)
113	\brief Constructor.
114
115	Creates a BLocker with the default name of <tt>some BLocker</tt>.
116
117	\note For debugging purposes, it's extremely convenient to actually give a
118		name to the object. In case of a deadlock, it's easier to track down
119		which BLocker object might have caused the problems.
120
121	\param benaphoreStyle If you pass \c true, the locker will be in benaphore
122		   style (which is the default option for other constructors). If you
123		   pass \c false, the object will completely rely on semaphores for
124		   it's functioning.
125
126	\see BLocker(const char* name, bool benaphoreStyle) if you also want
127		 to set a name.
128*/
129
130
131/*!
132	\fn BLocker::BLocker(const char* name, bool benaphoreStyle)
133	\brief Constructor.
134
135	\param name A NULL-terminated string that contains the name of the
136		   semaphore. Note that the length of the names are limited to
137		   \c B_OS_NAME_LENGTH constant, which includes the \c \\0
138		   character.
139	\param benaphoreStyle If you pass \c true, the locker will be in benaphore
140		   style (which is the default option for other constructors). If
141		   you pass \c false, the object will completely rely on semaphores
142		   for its functioning.
143*/
144
145
146/*!
147	\fn virtual BLocker::~BLocker()
148	\brief Destructor.
149
150	Release the internal semaphore. Because of this, any pending Lock() calls
151	from other threads be cancelled. The return code will be \c false for
152	those calls.
153*/
154
155
156/*!
157	\fn status_t BLocker::InitCheck() const
158	\brief Check whether the locker has properly initialized
159
160	\retval B_OK The semaphore has been properly initialized
161	\retval (negative) Any other error value that is related to semaphore
162		initialization
163*/
164
165
166/*!
167	\fn bool BLocker::Lock()
168	\brief Add a lock request and block on it until we get it.
169
170	\retval true Lock acquired successfully.
171	\retval false Failed to acquire the lock. Most probable cause is that the
172			object is deleted. This frees the semaphore and releases the
173			pending Lock() requests.
174
175	\see LockWithTimeout(bigtime_t timeout), Unlock()
176*/
177
178
179/*!
180	\fn status_t BLocker::LockWithTimeout(bigtime_t timeout)
181	\brief Add a lock request and block until we get it or until it times out.
182
183	\param timeout This is a timeout in microseconds (one millionth of a
184		   second) relative to now.
185
186	\see Lock(), Unlock()
187*/
188
189
190/*!
191	\fn void BLocker::Unlock(void)
192	\brief Release the lock that's currently held.
193*/
194
195
196/*!
197	\fn thread_id BLocker::LockingThread(void) const
198	\brief Return the \c thread_id of the thread that's currently holding the
199		   lock.
200*/
201
202
203/*!
204	\fn bool BLocker::IsLocked(void) const
205	\brief Check if the calling thread is actually holding the lock.
206
207	\retval true The thread from which this method is called from is currently
208    holding the lock.
209	\retval false The object is unlocked or the lock is held by another thread.
210*/
211
212
213/*!
214	\fn int32 BLocker::CountLocks(void) const
215	\brief Return the number of recursive locks that are currently held.
216*/
217
218
219/*!
220	\fn nt32 BLocker::CountLockRequests(void) const
221	\brief Return the number of threads with a pending lock request.
222*/
223
224
225/*!
226	\fn sem_id BLocker::Sem(void) const
227	\brief Return the sem_id of the semaphore this object holds.
228
229	\warning Like any other internal objects that the Haiku API might expose,
230    this semaphore id should in general be left alone. You should not use any
231    of the public low-level semaphore functions on this semaphore, because it
232    will harm the internal consistency of the object.
233*/
234