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