A condition variable can be used to signal to other threads that something has happened:
mutex m;
condition_variable cv;
thread t1([&cv]{
// processing
...
cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck);
But as you can see, there is a window of opportunity that the thread processing is finished and the notification is passing by before we get to wait to be notified, so we will wait forever.
In that case, a common solution is the use of a flag:
mutex m;
condition_variable cv;
bool done = false;
thread t1([&cv,&done]{
// processing
...
done = true;
cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck, [&done]{return done;});
Is using a flag the common way to use a condition_variable, or is my interpretation wrong?
A condition variable should always be associated with some condition, which you should test:
unique_lock<mutex> lck(m); while (!something) cv.wait(lck);The condition is checked while the mutex is held, so that implies the mutex should protect the data associated with the condition, so you know it won’t change between testing it and waiting.
The test is a
whilenot just anifbecause some condition variable implementations (including pthreads-based ones) may wake up spuriously i.e. when noone signalled it, so you should check the condition in a loop and re-wait while it isn’t true. There’s an overload ofwaitthat takes a predicate and automatically handles spurious wake ups by waiting until the predicate returns true, e.g. here’s the above example modified to use a lambda that checks the condition:unique_lock<mutex> lck(m); cv.wait(lck, [&] { return something; });(In simple cases I find the explicit
whileloop easier to read.)A condition variable that is in use can be thought of as a 3-tuple consisting of the condition variable, a mutex and a predicate, which are conceptually bound together by being used together to wait on the condition variable. All concurrent waits on a particular condition variable object must use the same mutex, and will generally also be waiting on the same predicate (or a related predicate that depends on the same data, protected by the same mutex.)