Derived from: public BObject
Declared in: <support/Locker.h>
The BLocker class provides a locking mechanism that protects a section of 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 disposition of calls 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 its lock's "owner"--the thread that's currently between Lock() and Unlock() calls. It lets the lock owner 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 MyObject : public BObject { public: void DoThis(); void DoThat(); void DoThisAndThat(); private: BLocker lock; };
And let's implement the member functions as shown below:
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() will be consider the lock's owner, and so it 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.
BLocker(void) BLocker(const char *name)
Sets up the object. The optional name is purely for diagnostics and debugging.
virtual ~BLocker(void)
Deletes the object. If there are any threads blocked waiting to lock the object, they're immediately unblocked.
inline bool IsLocked(void) const
Checks to see whether the calling thread is the thread that currently owns the lock. If it is, IsLocked() returns TRUE. If it's not, IsLocked() returns FALSE
void Lock(void) void Unlock(void)
These functions lock and unlock the BLocker.
Lock() attempts to lock the BLocker and set the lock's owner to the calling thread. The function doesn't return until it has succeeded. While the BLocker is locked, non-owner calls to Lock() will block. The owner, on the other hand, can make additional, nested calls to Lock() without blocking.
Unlock() releases one level of nested locks and returns immediately. When the BLocker is completely unlocked--when all nested Lock() calls have been matched by calls to Unlock() --the lock's owner is "unset", allowing some other thread to lock the BLocker. If there are threads blocked in Lock() calls 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()
inline thread_id LockOwner(void) const
Returns the thread that currently owns the lock, or -1 if the BLocker isn't currently locked.
See also: Lock()
The Be Book, HTML Edition, for Developer Release 8 of the Be Operating System.
Copyright © 1996 Be, Inc. All rights reserved.
Be, the Be logo, BeBox, BeOS, BeWare, and GeekPort are trademarks of Be, Inc.
Last modified September 6, 1996.