What is the best way to wait on multiple condition variables in C++11? What is the best way to wait on multiple condition variables in C++11? multithreading multithreading

What is the best way to wait on multiple condition variables in C++11?


You ask,

What is the best way to wait on multiple condition variables in C++11?

You can't, and must redesign. One thread may wait on only one condition variable (and its associated mutex) at a time. In this regard the Windows facilities for synchronization are rather richer than those of the "POSIX-style" family of synchronization primitives.

The typical approach with thread-safe queues is to enqueue a special "all done!" message, or to design a "breakable" (or "shutdown-able") queue. In the latter case, the queue's internal condition variable then protects a complex predicate: either an item is available or the queue has been broken.

In a comment you observe that

a notify_all() will have no effect if there is no one waiting

That's true but probably not relevant. wait()ing on a condition variable also implies checking a predicate, and checking it before actually blocking for a notification. So, a worker thread busy processing a queue item that "misses" a notify_all() will see, the next time it inspects the queue condition, that the predicate (a new item is available, or, the queue is all done) has changed.


Recently I resolved this issue with the help of single condition variable and separate Boolean variable for each producer/worker. The predicate within the wait function in consumer thread can check for these flags and take the decision which producer/worker has satisfied the condition.


Maybe this can works:

get rid of interrupt.

 message wait_and_pop(std::condition_variable& interrupt) {    std::unique_lock<std::mutex> lock(mutex);    {        new_msg_notification.wait(lock,[&]{            return !queue.empty() || stop;        });        if( !stop )        {            auto msg(std::move(queue.front()));            queue.pop();            return msg;        }        else        {            return NULL; //or some 'terminate' message        }}

In destructor, replace interrupt.notify_all() with new_msg_notification.notify_all()