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