Public Member Functions | List of all members
BLocker Class Reference

Semaphore-type class for thread safety. More...

Inherited by BPrivate::BTokenSpace.

Public Member Functions

 BLocker ()
 Create a new BLocker with the default name "some BLocker" and benaphore-style locking. More...
 
 BLocker (const char *name)
 Creates a new BLocker with the given name and benaphore-style locking. More...
 
 BLocker (bool benaphoreStyle)
 Creates a BLocker with the default name "some BLocker" and the given locking style. More...
 
 BLocker (const char *name, bool benaphoreStyle)
 Creates a new BLocker with the given name and locking style. More...
 
virtual ~BLocker ()
 Destructor. More...
 
int32 CountLockRequests () const
 Return the number of threads with a pending lock request. More...
 
int32 CountLocks () const
 Return the number of recursive locks that are currently held. More...
 
status_t InitCheck () const
 Check whether the locker has properly initialized. More...
 
bool IsLocked () const
 Check if the calling thread is actually holding the lock. More...
 
bool Lock ()
 Add a lock request and block on it until we get it. More...
 
thread_id LockingThread () const
 Return the thread_id of the thread that's currently holding the lock. More...
 
status_t LockWithTimeout (bigtime_t timeout)
 Add a lock request and block until we get it or until it times out. More...
 
sem_id Sem () const
 Return the sem_id of the semaphore this object holds. More...
 
void Unlock ()
 Release the lock that's currently held. More...
 

Detailed Description

Semaphore-type class for thread safety.

The BLocker interface is not merely a wrapper around a semaphore, but it also has two advantages. First of all, it implements a benaphore. A benaphore is in some ways more speed efficient, because before it uses the internal semaphore, it first checks against a variable that is only operated on with atomic operations. Setting a variable is a lot more efficient than acquiring a semaphore, thus this type of locking is much preferred.

It basically works as follows. Whenever you newly created BLocker object receives a locking request, it atomically sets the benaphore variable to 1. Then only additional calls from different threads will utilize the semaphore. You can imagine that in many cases where you protect of data that might be accessed by two or more concurrent threads, but the chances of it happening being very small, the benaphore benefits the most from its speed.

The other feature of BLocker that improves basic semaphore handling is that it allows for recursive locks. The following piece of code works with a BLocker, but block inevitably with a semaphore. Let's pretend I call Water():

Flower::Grow(int length)
{
if (fLock->Lock()) {
fLength += length;
fLock->Unlock();
return B_OK;
} else
return B_ERROR;
}
Flower::Water(int amount)
{
if (fLock->Lock()) {
status_t status = Grow(amount * 2);
fLock->Unlock();
return status;
} else
return B_ERROR;
}

This code would work because BLocker keeps track of the amount of lock requests from the same thread. A normal semaphore would block in Grow() because the semaphore would be acquired already. Please do make sure you pair every Lock() with an Unlock() though, or you'll create a deadlock.

See also
BAutolock
Since
BeOS R3

Constructor & Destructor Documentation

◆ BLocker() [1/4]

BLocker::BLocker ( )

Create a new BLocker with the default name "some BLocker" and benaphore-style locking.

This BLocker will use the benaphore-style locking.

Note
For debugging purposes, it's extremely convenient to actually give a name to the object. In case of a deadlock, it's easier to track down which BLocker object might have caused the problems.
See also
BLocker(const char*, bool) for all the options.
Since
BeOS R3

◆ BLocker() [2/4]

BLocker::BLocker ( const char *  name)

Creates a new BLocker with the given name and benaphore-style locking.

Parameters
nameA NULL-terminated string that contains the name of the semaphore. Note that the length of the names are limited to B_OS_NAME_LENGTH constant, which includes the \0 character.
See also
BLocker(const char* name, bool benaphoreStyle) for all the options.
Since
BeOS R3

◆ BLocker() [3/4]

BLocker::BLocker ( bool  benaphoreStyle)

Creates a BLocker with the default name "some BLocker" and the given locking style.

Note
For debugging purposes, it's extremely convenient to actually give a name to the object. In case of a deadlock, it's easier to track down which BLocker object might have caused the problems.
Parameters
benaphoreStyleIf you pass true, the locker will be in benaphore style (which is the default option for other constructors). If you pass false, the object will completely rely on semaphores for its functioning.
See also
BLocker(const char* name, bool benaphoreStyle) if you also want to set a name.
Since
BeOS R4

◆ BLocker() [4/4]

BLocker::BLocker ( const char *  name,
bool  benaphoreStyle 
)

Creates a new BLocker with the given name and locking style.

Parameters
nameA NULL-terminated string that contains the name of the semaphore. Note that the length of the names are limited to B_OS_NAME_LENGTH constant, which includes the \0 character.
benaphoreStyleIf you pass true, the locker will be in benaphore style (which is the default option for other constructors). If you pass false, the object will completely rely on semaphores for its functioning.
Since
BeOS R4

◆ ~BLocker()

BLocker::~BLocker ( )
virtual

Destructor.

Release the internal semaphore. Because of this, any pending Lock() calls from other threads be cancelled. The return code will be false for those calls.

Since
BeOS R3

Member Function Documentation

◆ CountLockRequests()

int32 BLocker::CountLockRequests ( void  ) const

Return the number of threads with a pending lock request.

Returns
The number of threads with a pending lock request as an int32.
Since
BeOS R3

◆ CountLocks()

int32 BLocker::CountLocks ( void  ) const

Return the number of recursive locks that are currently held.

Returns
the number of currently held recursive locks as an int32.
Since
BeOS R3

◆ InitCheck()

status_t BLocker::InitCheck ( void  ) const

Check whether the locker has properly initialized.

Returns
A status code, B_OK if the semaphore has been properly initialized or any other error (negative) value related to semaphore initialization.
Since
Haiku R1

◆ IsLocked()

bool BLocker::IsLocked ( void  ) const

Check if the calling thread is actually holding the lock.

Returns
Whether or not the calling thread is holding the lock.
Return values
trueThe thread from which this method is called from is currently holding the lock.
falseThe object is unlocked or the lock is held by another thread.
Since
BeOS R3

◆ Lock()

bool BLocker::Lock ( )

Add a lock request and block on it until we get it.

Return values
trueLock acquired successfully.
falseFailed to acquire the lock. Most probable cause is that the object is deleted. This frees the semaphore and releases the pending Lock() requests.
See also
LockWithTimeout(bigtime_t timeout), Unlock()
Since
BeOS R3

Referenced by BAutolock::Lock().

◆ LockingThread()

thread_id BLocker::LockingThread ( void  ) const

Return the thread_id of the thread that's currently holding the lock.

Since
BeOS R3

◆ LockWithTimeout()

status_t BLocker::LockWithTimeout ( bigtime_t  timeout)

Add a lock request and block until we get it or until it times out.

Parameters
timeoutThis is a timeout in microseconds (one millionth of a second) relative to now.
See also
Lock(), Unlock()
Since
BeOS R3

◆ Sem()

sem_id BLocker::Sem ( void  ) const

Return the sem_id of the semaphore this object holds.

Warning
Like any other internal objects that the Haiku API might expose, this semaphore id should in general be left alone. You should not use any of the public low-level semaphore functions on this semaphore, because it will harm the internal consistency of the object.
Returns
The sem_id of the semaphore this object holds.
Since
BeOS R3

◆ Unlock()

void BLocker::Unlock ( void  )

Release the lock that's currently held.

Since
BeOS R3

Referenced by BAutolock::Unlock().