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
}
.
.
.
};
The synchronization semantics of an
RWCondition instance are illustrated in the interaction diagram
Figure 25: