Cross-Platform C++

ot
class ConditionVariable

#include "ot/base/ConditionVariable.h"

Provides a means for a thread to be signalled when a condition becomes true. When a thread has acquired a mutex on some shared data, but then finds that the data is not in the correct state for it to do some work, then it should release the mutex and wait for another thread to signal it that the shared data has changed. This is the basic function of a POSIX-style condition variable.

A condition variable is always used in conjunction with a mutex. The mutex is used to synchronize access to the shared data, and the condition variable is used to signal to waiting threads that a condition or predicate has become true.

A program cannot examine the shared data without having the mutex locked. But if the mutex is locked, no other thread will be able to change the state, so the wait operation atomically releases the mutex and blocks the thread pending a signal from another thread. When the waiting thread is signalled, the mutex is re-acquired before the wait() method returns to the caller.

Here is a simple example of a thread that pulls a single item from a queue. If the queue is empty, it blocks until an item becomes available:

    WorkItem Worker::getNextWorkItem()
    {
        // acquire the queue's mutex
        RecursiveMutex::Lock lock(m_queueMutex);
        while(m_queue.empty())
        {
            try
            {
                // mutex is released for the wait...
                m_queueCV.wait();
                // ...and re-acquired on return
            }
            catch(InterruptedException& e) {}
        }
        // pop the first item from the work queue
        WorkItem ret = m_queue.front();
        m_queue.pop_front();
        return ret;
        // mutex lock is automatically released on exit
    }

Note the structure of this function, where the predicate is tested in a while loop. This is a standard and recommended technique which is used to make the function robust in the presence of spurious wake-ups.

Following on from the previous example, here is a function that adds an item to the queue and signals the waiting thread that there is some work to be done:

    void Worker::queueWorkItem(const WorkItem& item)
    {
        // acquire the queue's mutex
        RecursiveMutex::Lock lock(m_queueMutex);
        m_queue.push_back(item);
        // inform a waiting thread that a work item is now available
        m_queueCV.signal();
        // mutex is automatically released on exit from the scope
    }

In the above example it is not a requirement that the mutex lock be held while the signal() operation is performed, but it is generally better to do so. If the function added multiple items to the queue, then broadcast() would be a better choice than signal() if multiple worker threads could be waiting on the queue.

A single condition variable may be associated with more than one mutex. Likewise a single mutex may be associated with more than one condition variable.

On POSIX-compliant systems this class is a simple wrapper around a POSIX threads condition variable. On other systems, a condition variable is emulated using the available synchronization primitives.




Constructor/Destructor Summary
ConditionVariable()
         Constructs a ConditionVariable.
~ConditionVariable()
         Releases system resources associated with this ConditionVariable.

Method Summary
 void broadcast()
         Awakens all threads that are waiting on this condition variable.
 void signal()
         Awakens one of the threads that are waiting on this condition variable.
 void wait(RecursiveMutex& mutex)
         Waits and blocks the calling thread until the ConditionVariable becomes signalled.
 bool wait(RecursiveMutex& mutex, unsigned long milliseconds)
         Waits and blocks the calling thread until the ConditionVariable becomes signalled or the timeout value expires.

Constructor/Destructor Detail

ConditionVariable

 ConditionVariable()
Constructs a ConditionVariable.


~ConditionVariable

 ~ConditionVariable()
Releases system resources associated with this ConditionVariable.


Method Detail

broadcast

void broadcast()
Awakens all threads that are waiting on this condition variable. Every awakened thread will compete to re-acquire the mutex that it had locked prior to entering wait().


signal

void signal()
Awakens one of the threads that are waiting on this condition variable. If no threads are waiting on this condition variable, nothing happens. If several threads are waiting, exactly one is woken, but it is not specified which one.

When a thread is awakened, it re-acquires the mutex that was released by the wait() call before returning to the application.

See also:
wait()

wait

void wait(RecursiveMutex& mutex)
Waits and blocks the calling thread until the ConditionVariable becomes signalled. This method allows a thread to wait for a condition and atomically release the associated mutex that it needs to hold to check the condition. The thread waits for another thread to make the condition true and that thread's resulting call to signal() or broadcast().

Upon completion, the mutex is locked and owned by the calling thread.

On most occasions, control is not returned to the caller until another thread has called signal() or broadcast() on this ConditionVariable. However, it is possible for spurious wake-ups to occur. For this reason, the caller should always check the condition in a while loop.

Parameters:
mutex - the mutex object associated with the condition.
See also:
signal() , broadcast()

wait

bool wait(RecursiveMutex& mutex,
          unsigned long milliseconds)
Waits and blocks the calling thread until the ConditionVariable becomes signalled or the timeout value expires. This method allows a thread to wait for a condition and atomically release the associated mutex that it needs to hold to check the condition. The thread waits for another thread to make the condition true and that thread's resulting call to signal() or broadcast().

Upon completion, the mutex is locked and owned by the calling thread.

Parameters:
mutex - the mutex object associated with the condition.
milliseconds - the number of milliseconds to wait before timing-out.
Returns:
true if the ConditionVariable was signalled; false if timed-out
Exceptions:
InterruptedException - if the current thread is interrupted. The mutex is re-acquired before throwing this exception.
See also:
wait() , signal() , broadcast() , Thread::interrupt()


Cross-Platform C++

Found a bug or missing feature? Please email us at support@elcel.com

Copyright © 2000-2003 ElCel Technology   Trademark Acknowledgements