The RWCondition Class
As explained in Using Condition Variables, another common form of thread synchronization is condition synchronization, which uses an implementation of a condition variable. To implement condition synchronization using a condition variable, you combine the functionality of RWCondition with the mutual exclusion capability of RWMutexLock.
When using an RWCondition instance to implement condition synchronization, a mutex is required to prohibit changes to the program state upon which the synchronization condition depends. A thread subjected to condition synchronization acquires the mutex, tests the condition, and if the condition is found to be false, calls the wait() function on the condition variable. This wait operation temporarily unlocks the mutex so other threads can access and update the program state.
A thread that is going to change the program state acquires the mutex, updates the state, and signals one waiting thread by calling the signal() function on the condition variable. When the waiting thread is awakened, the mutex is reacquired and control is returned to the thread.
Having exited the wait, a thread typically reevaluates the synchronization condition. If the condition is still false, the thread again waits. If the condition is true, the thread has achieved synchronization and can now release the mutex and proceed.
NOTE: The mutex must be acquired prior to calling the wait(), signal(), or signalAll() functions. Failure to do so produces assertions in the debug version of the library and can result in other errors in the release version.
The mutex can be acquired and released using its own member functions or the acquire() and release() member functions of the RWCondition class.
To simplify implementation, the RWCondition class includes both a mutex and a condition-variable interface. An RWCondition class instance does not possess its own mutex; you must supply a reference to an RWMutexLock instance when you construct each condition instance. Like the RWMutexLock class, RWCondition also has public typedefs for the lock guard classes.
The class definition in Example 37 demonstrates typical usage for the RWCondition class.
Example 37 – Using condition synchronization
#include <rw/sync/RWMutexLock.h>
#include <rw/sync/RWCondition.h>
 
class ConditionMonitor {
private:
RWMutexLock mutex_;
RWCondition condition_;
// Declare other state variables here...
bool state_; // Dummy state variable
public:
ConditionMonitor() :
condition_(mutex_), // 1
state_(false)
{
}
 
bool waitForStateChange() {
RWCondition::LockGuard lock(condition_); // 2
bool initial = state_;
while(state_ == initial) { // 3
condition_.wait(); // 4
}
return state_;
}
void changeState(bool newState) {
RWCondition::LockGuard lock(condition_);
state_ = newState;
condition_.signalAll(); // 5
}
.
.
.
};
//1 Initializes the condition with a reference to a mutex. This mutex must be acquired whenever the condition wait(), signal(), or signalAll() functions are called.
//2 Acquires a lock on the mutex using the condition variable’s interface.
//3 Tests for a change in state.
//4 Waits for another thread to signal that it has changed the state.
//5 Signals the change in state.
The synchronization semantics of an RWCondition instance are illustrated in the interaction diagram Figure 25:
Figure 25 – RWCondition interactions