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
= newBLocker
(); . . .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:
classBadDog
: publicBArchivable
{ public: voidDoThis
(); voidDoThat
(); voidDoThisAndThat
(); private:BLocker
lock
; };
Let's implement the member functions as follows:
voidBadDog
::DoThis
() {lock
.Lock
(); /* Do this here. */lock
.Unlock
(); } voidBadDog
::DoThat
() {lock
.Lock
(); /* Do that here. */lock
.Unlock
(); } voidBadDog
::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 an equal number
of Unlock()
calls.
See also: the
BAutolock
class