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 its 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 its 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