Derived from: none
Declared in: <support/Locker.h>
The BLocker class provides a locking mechanism that can be used to protect a section of critical code. The code that you want to protect should be placed between BLocker's Lock() and Unlock() calls:
BLocker *aLock = new BLocker(); . . . aLock->Lock(); /* Protected code goes here. */ aLock->Unlock();
This guarantees that only one thread at a time will pass through the lock. After a thread has locked the BLocker object, subsequent attempts to lock by other threads are blocked until the first thread calls Unlock().
BLocker keeps track of the locking thread--the thread that's currently between Lock() and Unlock() calls. It lets the thread make nested calls to Lock() without blocking. Because of this, you can wrap a BLocker's lock around a series of functions that might, themselves, lock the same BLocker object.
For example, let's say you have a class called BadDog that's declared thus:
class BadDog : public BArchivable { public: void DoThis(); void DoThat(); void DoThisAndThat(); private: BLocker lock; };
And let's implement the member functions as follows:
void BadDog::DoThis() { lock.Lock(); /* Do this here. */ lock.Unlock(); } void BadDog::DoThat() { lock.Lock(); /* Do that here. */ lock.Unlock(); } void BadDog::DoThisAndThat() { lock.Lock(); DoThis(); DoThat(); lock.Unlock(); }
Notice that DoThisAndThat() wraps the lock around its calls to DoThis() and DoThat(), both of which contain locks as well. A thread that gets past the Lock() call in DoThisAndThat() won't block when it calls the nested Lock() calls that it runs into in DoThis() and DoThat().
Keep in mind that nested Lock() calls must be balanced by equally-nested Unlock() calls.
See also: the BAutolock class
BLocker(void) BLocker(const char *name)
Sets up the object. The optional name is purely for diagnostics and debugging.
virtual ~BLocker(void)
Destroys the lock. If there are any threads blocked waiting to lock the object, they're immediately unblocked.
bool Lock(void) status_t LockWithTimeout(bigtime_t timeout) void Unlock(void)
These functions lock and unlock the BLocker.
Lock() attempts to lock the BLocker. It waits without time limit until it can succeed and return true. It returns false only under exceptional circumstances--for example, if the BLocker and its lock have been destroyed. While a thread has the BLocker is locked, calls to Lock() by other threads will block. The locking thread, on the other hand, can make additional, nested calls to Lock() without blocking.
LockWithTimeout() is an alternative to Lock() that permits you to limit how long it should block waiting for the lock. The timeout is specified in microseconds. If LockWithTimeout() can't acquire the lock before the time limit expires, it returns B_TIMED_OUT. If the timeout is 0, this function doesn't block but immediately returns B_OK (if it locked the BLooper) or B_ERROR (if it failed to obtain the lock). If the timeout is B_INFINITE_TIMEOUT, it blocks without limit, just as Lock() does. Note that if Lock() returns 0 (false), it has failed to lock the BLooper, but if LockWithTimeout() returns 0 (B_OK), it has succeeded. [
Unlock() releases one level of nested locks and returns immediately. When the BLocker is completely unlocked--when all nested Lock() (or LockWithTimeout()) calls have been matched by calls to Unlock()--the locking thread is "unset", allowing some other thread to obtain the lock. If there are threads blocked waiting for the lock when the lock is released, the thread that's been waiting the longest acquires the lock.
Although you're not prevented from doing so, it's not good form to call Unlock() from a thread that doesn't own the lock. For debugging purposes, you can call IsLocked() before calling Unlock() to make sure this doesn't happen in your code.
See also: LockOwner()
thread_id LockingThread(void) const bool IsLocked(void) const int32 CountLocks(void) const int32 CountLockRequests(void) const sem_id Sem(void) const
These functions provide information that may be useful for debugging purposes.
LockingThread() returns the thread that currently has the BLocker locked, or -1 if the BLooper isn't locked.
IsLocked() returns true if the calling thread currently has the BLocker locked (if it's the locking thread) and false if not (if some other thread is the locking thread or the BLocker isn't locked).
CountLocks() returns the number of times the locking thread has locked the BLocker--the number of Lock() (or LockWithTimeout()) calls that have not yet been balanced by matching Unlock() calls.
CountLockRequests() returns the number of threads currently trying to lock the BLocker. The count includes the thread that currently has the lock plus all threads currently waiting to acquire it.
Sem() returns the sem_id for the semaphore that the BLocker uses to implement the locking mechanism.
See also: Lock()
LockingThread() returns the thread that currently has the BLooper locked, or -1 if the BLooper isn't locked.
IsLocked() returns true if the calling thread has the BLooper locked (if it's the lock owner) and false if not (if some other thread is the owner or the BLooper isn't locked).
See also: Lock()
The Be Book, in lovely HTML, for the BeOS Preview Release.
Copyright © 1997 Be, Inc. All rights reserved.
Be is a registered trademark; BeOS, BeBox, BeWare, GeekPort, the Be logo, and the BeOS logo are trademarks of Be, Inc.
Last modified June 30, 1997.