SourcePro® API Reference Guide

 
List of all members | Public Types | Public Member Functions | Private Member Functions | Related Functions
RWSemaphore Class Reference

A synchronization object that maintains a non-negative counter. More...

#include <rw/sync/RWSemaphore.h>

Inheritance diagram for RWSemaphore:
RWSynchObject

Public Types

typedef RWTLockGuard< RWSemaphoreLockGuard
 
typedef RWTTryLockGuard< RWSemaphoreTryLockGuard
 
typedef RWTUnlockGuard< RWSemaphoreUnlockGuard
 

Public Member Functions

 RWSemaphore (unsigned count=0, RWCancellationState state=0)
 
 ~RWSemaphore ()
 
void acquire ()
 
RWWaitStatus acquire (unsigned long milliseconds)
 
RWSemaphoreRepgetSemaphoreRep () const
 
void P ()
 
RWWaitStatus P (unsigned long milliseconds)
 
void release ()
 
bool tryAcquire ()
 
void V ()
 
- Public Member Functions inherited from RWSynchObject
void disableCancellation ()
 
void enableCancellation (RWCancellationState)
 
bool isCancellationEnabled () const
 
void setCancellation (RWCancellationState)
 

Private Member Functions

 RWSemaphore (const RWSemaphore &second)
 
RWSemaphoreoperator= (const RWSemaphore &second)
 

Related Functions

(Note that these are not member functions.)

typedef void * RWSemaphoreRep
 

Additional Inherited Members

- Protected Member Functions inherited from RWSynchObject
 RWSynchObject (RWCancellationState state=0)
 
 RWSynchObject (RWStaticCtor)
 
 RWSynchObject (const RWSynchObject &second)
 
RWSynchObjectoperator= (const RWSynchObject &second)
 
void testCancellation ()
 

Detailed Description

An RWSemaphore is a synchronization object that maintains a non-negative counter. When a semaphore is acquired, the count is decremented. If the count is zero when acquire() is called, then the calling thread is put on a wait queue and blocks. When the thread reaches the head of the queue, it can acquire the semaphore as soon as the counter is incremented. The count is incremented when a thread calls release() on the semaphore. The initial count of a semaphore is set when it is created; it defaults to 0.

An important difference between a mutex and a semaphore with a count of 1 is that a mutex can be released only by the thread that acquired it. A semaphore can be released by any thread.

Among the uses of semaphores are restricting access to some limited resource, and signaling some condition between threads.

Example
// This program simulates a situation where 5 people all want to
// take a nap but there are only two pillows. (And no one is
// willing to risk a stiff neck by sleeping without one!)
// A semaphore with an initial count of 2 is used to coordinate
// access to this limited resource. The semaphore ensures that
// at most two people are sleeping at any given time.
#include <iostream>
#include <rw/sync/RWSemaphore.h>
#include <rw/sync/RWMutexLock.h>
#include <rw/functor/rwBind.h>
#include <rw/thread/RWThread.h>
#include <rw/thread/RWThreadFunction.h>
RWSemaphore sem(2); // Coordinate pool of 2 pillows
RWMutexLock coutLock; // Coordinate use of cout
void print(int id, const char* p)
{
RWMutexLock::LockGuard lock(coutLock);
std::cout << "Thread " << id << " " << p << std::endl;
}
void takeNap(int id)
{
print(id, "is waiting for a pillow");
sem.acquire(); // Get one of the two pillows
print(id, "has acquired a pillow and is settling down for a nap");
rwSleep(1000); // Even a 1 second nap can be very refreshing!
print(id, "is awake and making a pillow available");
sem.release(); // Make a pillow available
}
int main()
{
int i;
RWThread thread[5];
for (i = 0; i < 5; ++i) {
thread[i] = RWThreadFunction::make(rwBind(takeNap, i + 1));
thread[i].start();
}
for (i = 0; i < 5; ++i) {
thread[i].join();
}
return 0;
}

OUTPUT:

Thread 1 is waiting for a pillow
Thread 1 has acquired a pillow and is settling down for a nap
Thread 2 is waiting for a pillow
Thread 2 has acquired a pillow and is settling down for a nap
Thread 3 is waiting for a pillow
Thread 4 is waiting for a pillow
Thread 5 is waiting for a pillow
Thread 1 is awake and making a pillow available
Thread 2 is awake and making a pillow available
Thread 3 has acquired a pillow and is settling down for a nap
Thread 4 has acquired a pillow and is settling down for a nap
Thread 3 is awake and making a pillow available
Thread 4 is awake and making a pillow available
Thread 5 has acquired a pillow and is settling down for a nap
Thread 5 is awake and making a pillow available
See also
RWSynchObject, RWTLockGuard, RWTTryLockGuard, RWTUnlockGuard

Member Typedef Documentation

Predefined type for compatible guard.

Predefined type for compatible guard.

Predefined type for compatible guard.

Constructor & Destructor Documentation

RWSemaphore::RWSemaphore ( unsigned  count = 0,
RWCancellationState  state = 0 
)

Creates a semaphore with an initial counter set to count. The thread cancellation state of the object is initialized to state. Possible exceptions include RWTHRResourceLimit and RWTHRInternalError.

RWSemaphore::~RWSemaphore ( )

Recovers any system resources used to implement the RWSemaphore. Possible exceptions include RWTHRInternalError.

RWSemaphore::RWSemaphore ( const RWSemaphore second)
private

Copy construction prohibited.

Member Function Documentation

void RWSemaphore::acquire ( )

Acquires the semaphore by attempting to decrement the count. If the semaphore count is zero, the current thread blocks until another thread increments the count by calling release(). Otherwise, the count is decremented and the thread is allowed to proceed. Possible exceptions include RWCancellation, RWTHRResourceLimit, and RWTHRInternalError.

This method returns immediately in single-threaded builds. If the resource is unavailable for acquisition, a debug assertion occurs or an RWTHRInternalError is thrown.

RWWaitStatus RWSemaphore::acquire ( unsigned long  milliseconds)

Acquires the semaphore by attempting to decrement the count. If the semaphore count is zero, the current thread blocks until another thread increments the count or the specified amount of time expires. If the time has expired, the method returns RW_THR_TIMEOUT. Otherwise, the count is decremented and the thread is allowed to proceed. Possible exceptions include RWCancellation, RWTHRResourceLimit, and RWTHRInternalError.

This method returns immediately in single-threaded builds.

RWSemaphoreRep* RWSemaphore::getSemaphoreRep ( ) const

Provides access to the underlying mechanism.

Condition:
This function is available only in build configurations based on Win32 threads.
RWSemaphore& RWSemaphore::operator= ( const RWSemaphore second)
private

Assignment prohibited.

void RWSemaphore::P ( )
inline

Calls acquire(). P stands for passeren, which is Dutch for to pass. Provided for those who wish to use this traditional sign handed down from the Dutch inventor of the semaphore, E. W. Dijkstra. Possible exceptions include RWCancellation, RWTHRResourceLimit, and RWTHRInternalError.

RWWaitStatus RWSemaphore::P ( unsigned long  milliseconds)
inline

Returns the result of calling acquire(milliseconds). P stands for passeren, which is Dutch for to pass. Provided for those who wish to use this traditional sign handed down from the Dutch inventor of the semaphore, E. W. Dijkstra. Possible exceptions include RWCancellation, RWTHRResourceLimit, and RWTHRInternalError.

void RWSemaphore::release ( )

Releases the semaphore by incrementing the semaphore count. Possible exceptions include RWTHRInternalError.

Note
This method always increments the count, even if the count is increased beyond that supplied to the constructor. For instance, the sequence sem = RWSemaphore(1); sem.release(); increases the sempaphore's count to 2.
bool RWSemaphore::tryAcquire ( )

Tries to acquire the semaphore by decrementing the count. If successful, returns true; otherwise returns false. Possible exceptions include RWCancellation and RWTHRInternalError.

void RWSemaphore::V ( )
inline

Calls release(). V stands for vrygeven, which is Dutch for "to release." Provided for those who wish to use this traditional sign handed down from the Dutch inventor of the semaphore, E. W. Dijkstra. Possible exceptions include RWTHRInternalError.

Note
This method always increments the count, even if the count is increased beyond that supplied to the constructor. For instance, the sequence sem = RWSemaphore(1); sem.v(); increases the semaphore's count to 2.

Friends And Related Function Documentation

typedef void* RWSemaphoreRep
related

This is the internal semaphore representation.

Condition:
This type is used for build configurations based on Win32 threads.

Copyright © 2023 Rogue Wave Software, Inc., a Perforce company. All Rights Reserved.