RWSemaphore RWSynchObject
#include <rw/sync/RWSemaphore.h>
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 will be put on a wait queue and block. 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 only be released 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.
// 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.h> #include <rw/sync/RWSemaphore.h> #include <rw/sync/RWMutexLock.h> #include <rw/thread/RWRunnableSelf.h> #include <rw/thread/rwtMakeThreadFunction.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); cout << "Thread " << id << " " << p << 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] = rwtMakeThreadFunction(takeNap, i+1)).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 * */
typedef HANDLE RWSemaphoreRep; // Win32 Only
Native type used for internal implementation.
typedef RWTLockGuard<RWSemaphore> LockGuard; typedef RWTTryLockGuard<RWSemaphore> TryLockGuard; typedef RWTUnlockGuard<RWSemaphore> UnlockGuard;
Predefined types for compatible guards.
RWSemaphore(unsigned count = 0, RWCancellationState state=RW_CANCELLATION_DISABLED);
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(void);
Recovers any system resources used to implement the RWSemaphore. Possible exceptions include RWTHRInternalError.
void acquire(void);
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.
RWWaitStatus 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.
RWSemaphoreRep* getSemaphoreRep(void) const;
Currently supported for the Win32 platform only, this method provides access to the underlying mechanism.
void P(void);
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 P(unsigned long milliseconds);
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 release(void);
Releases the semaphore by incrementing the semaphore count. Possible exceptions include RWTHRInternalError.
NOTE: This method always increments the count, even if this increases the count beyond the count supplied to the constructor. For instance, the sequence sem = RWSemaphore(1); sem.release(); increases sem's count to 2.
RWBoolean tryAcquire(void);
Tries to acquire the semaphore by decrementing the count. If successful, returns TRUE; otherwise returns FALSE. Possible exceptions include RWCancellation and RWTHRInternalError.
void V(void);
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 this increases the count beyond the count supplied to the constructor. For instance, the sequence sem = RWSemaphore(1); sem.v(); increases sem's count to 2.
RWSynchObject, RWTLockGuard<Resource>, RWTTryLockGuard, RWTTryLockGuard<Resource>, RWTUnlockGuard<Resource>
©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.