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