A condition is bound with a mutex (see Thread::Mutex) and with a predicate. A predicate is a set of tests that may evalute to true or false at a given time; the goal of a condition variable is to make a user thread to wait for a predicate to become true before to proceed. When a different thread changes the data so that the predicate may become true, it "signals" the condition; this wakes the waiting threads and makes them to check again for the predicate being now true. If it is so, the waiting threads will proceed and complete its opeartions.
A program using a condition must check a predicate whose status depends on operations done by other threads; hence the need to use a mutex to secure the access to the data that is checked by the predicate. Entering the wait will automatically and atomically unlock the mutex, allowing other threads to lock it and work on the shared data; the mutex is then re-locked on wakeup, so that the waiting thread can safely check the condition and eventually work on the shared data.
The relationship between mutexes and conditions is 1:N, that is, a condition may be related only with a mutex, but a mutex can be used in more than one predicate. A well designed program uses a condition for each predicate to check, although is possible to design applications where a single condition is used to control more than a predicate. However, doing so will result in a waste of context swapping, as when a condition is signaled, some thread whose predicate has data unaltered will be awaken and will do an useless test that will be still false as before. The time used to test the predicate may be trivial, but a useles context switch is a considerable waste of system resources.
Condition wait can be timed. If a thread wishes, it can wait for a condition just for a given time; if the condition is not notified in that time, the thread is awaken and signaled about this timeout; the thread must then act as if the predicate was false and terminate its waiting process.
Waits can also be interrupted by an external event; this is one of the reasons why it is necessary to check if the predicate is true after a wait is terminated; in fact, the thread may return in control after a condition wait even if the condition is not signaled, or if the condition is erroneusly signaled by a thread that is not really making the whole predicate to become true (i.e. the predicate may be a check on two variables, and a thread may signal after having changed just one of them).
A waiting process may also be stopped, if it allows so. When this happens, the mutex used by the condition is relocked, and a cleanup function is called. It is necessary to provide a cleanup code, because there is no way by which the mutex is going to be freed by itself; anyhow, a condition wait usually needs more cleanup than just releasing the owned mutex. Any non-trivial program using conditions will need a cleanup routine on its own, and that cleanup routine will find the mutex locked to be very handy.
|Class implementing a condition variable. More...|
|Fast mutex + condition structure wrapper. More...|
|Reentrant mutex + condition structure wrapper. More...|