A condition variable lets a thread wait for an event, such as work arriving, instead of repeatedly checking shared data. Another thread changes the data and notifies a waiter. The condition variable works alongside a mutex that protects the data being checked. section 4.1 section 4.1.1
In C++, include <condition_variable>. Prefer std::condition_variable when using std::mutex. std::condition_variable_any accepts other mutex-like types, but its flexibility may carry extra costs. section 4.1.1
Wait for work in a queue
A producer locks a mutex, pushes an item onto a queue, then calls notify_one(). A consumer holds a std::unique_lock and calls wait(lock, predicate), where the predicate tests whether the queue is nonempty. Once the wait returns, it removes an item under the lock, unlocks, and processes the item. Notifying after the producer unlocks avoids waking a consumer only to make it wait for that mutex. section 4.1.1
Listing 4.1. Waiting for data to process with std::condition_variable
std::mutex mut;
std::queue<data_chunk> data_queue; #1
std::condition_variable data_cond;
void data_preparation_thread()
{
while(more_data_to_prepare())
{
data_chunk const data=prepare_data();
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(data); #2
}
data_cond.notify_one(); #3
}
}
void data_processing_thread()
{
while(true)
{
std::unique_lock<std::mutex> lk(mut); #4
data_cond.wait(
lk,[]{return !data_queue.empty();}); #5
data_chunk data=data_queue.front();
data_queue.pop();
lk.unlock(); #6
process(data);
if(is_last_chunk(data))
break;
}
}
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":1,\"ch\":51},{\"line\":1,\"ch\":53}],[{\"line\":10,\"ch\":51},{\"line\":10,\"ch\":53}],[{\"line\":12,\"ch\":51},{\"line\":12,\"ch\":53}],[{\"line\":19,\"ch\":51},{\"line\":19,\"ch\":53}],[{\"line\":21,\"ch\":51},{\"line\":21,\"ch\":53}],[{\"line\":24,\"ch\":51},{\"line\":24,\"ch\":53}]]"}
!@%STYLE%@!
The producer–consumer listing shows the queue predicate, notify_one(), and the consumer’s unlock before processing. section 4.1.1
The same pattern can be enclosed in a thread-safe queue: push() adds data and notifies; wait_and_pop() waits for a nonempty queue before removing an item. With several consumers dividing the work, notify_one() wakes one waiting thread to check the condition; it does not specify which one. section 4.1.2






