# The Support Kit: BLocker

Derived from: none

Declared in: be/support/Locker.h

Library: libbe.so

## Overview

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)

Sets up the object. The optional name is for diagnostics and debugging.

### ~BLocker()

          virtual ~BLocker()

Destroys the lock. 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 doesn't return until a) the lock is acquired (return = `true`) or b) the BLocker is deleted (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 BLooper, 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 Be Book, in lovely HTML, for BeOS Release 3.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.