The Support Kit: BLocker

The Support Kit Table of Contents | The Support Kit Index

# BLocker

Derived from: none

Declared in: be/support/Locker.h

Library: libbe.so

###### Summary

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;
       };

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 an equal number of `Unlock()` calls.

See also: the BAutolock class

## Constructor and Destructor

### BLocker()

`BLocker(`void`)`
`BLocker(`const char *name`)`
`BLocker(`bool benaphore_style`)`
`BLocker(`const char *name, bool benaphore_style`)`

Sets up the object, creating a semaphore to implement the locking mechanism. The optional name is for diagnostics and debugging.

By default, a BLocker is implemented as a benaphore –– a hybrid integer mutex and semaphore. This allows for faster performance when there is little contention for the lock. If you'd rather use a pure semaphore for locking, then pass `false` as the benaphore_style argument.

### ~BLocker()

virtual `~BLocker()`

Destroys the lock, deleting the controlling semaphore. If there are any threads blocked waiting to lock the object, they're immediately unblocked.

## Member Functions

### CountLocks() see LockingThread()

### CountLockRequests() see LockingThread()

### IsLocked() see LockingThread()

### Lock() , LockWithTimeout() , Unlock()

bool `Lock(`void`) `
status_t `LockWithTimeout(`bigtime_t timeout`)`
void `Unlock(`void`) `

`Lock()` tries to lock the BLocker. The function returns a) when the lock is acquired (return = `true`) or b) immediately if the BLocker's semaphore is deleted, most commonly as a result of deleting the object (return = `false`). A thread can nest Lock() calls, but each call must be balanced by a concomitant `Unlock()`.

`LockWithTimeout()` lets you declare a time limit, 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 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 BLocker, but if `LockWithTimeout()` returns 0 (`B_OK`), it has succeeded.

`Unlock()` releases one level of nested locks and returns immediately. 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.

Any thread can call Unlock() on any BLocker—the thread needn't be the lock's current holder. Call `IsLocked()` before calling `Unlock()` if you want to make sure you own a lock before you unlock it.

### LockingThread() , IsLocked() , CountLocks() , CountLockRequests() , Sem()

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 `B_ERROR` 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 holds 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.

The Support Kit Table of Contents | The Support Kit Index

The Be Book,
...in lovely HTML...
for BeOS Release 5.

Copyright © 2000 Be, Inc. All rights reserved..