Question

Is it possible to use single condition variable for bidirectional synchronization (i.e. two different conditions are waited for at different times on the same condition variable)? I'm sure that no more than one thread will wait on the condition variable at any time. The example code below illustrates what I'm thinking about:

#include <condition_variable>
#include <thread>
#include <mutex>
#include <iostream>

std::condition_variable condvar;
std::mutex mutex;
int i;

void even()
{
    while (i < 10000) {
        std::unique_lock<std::mutex> lock(mutex);
        if (i % 2 != 0) {
            condvar.notify_one();
            condvar.wait(lock, [&](){ return i % 2 == 0; });
        }
        i++;
        std::cout << i << std::endl;
    }
    condvar.notify_one();
}

void odd()
{
    while (i < 10001) {
        std::unique_lock<std::mutex> lock(mutex);
        if (i % 2 != 1) {
            condvar.notify_one();
            condvar.wait(lock, [&](){ return i % 2 == 1; });
        }
        i++;
        std::cout << i << std::endl;
    }
}

int main()
{
    i = 0;
    std::thread a(even);
    std::thread b(odd);
    a.join();
    b.join();
}
Was it helpful?

Solution

Yes, it's perfectly safe. However, I wouldn't get into the habit of calling notify_one when you actually want to notify all threads waiting for the condition, even if you "know" only one thread will be waiting.

OTHER TIPS

Fundamentally, notifying a condition variable really only declares "the condition you are looking for may have occurred."

The only concern one could have with bidirectional communication with one condition variable is that a thread may be woken up by a notify when there is no data available for it. Proper use of condition variables is done in a while loop, so the worst case is that the thread sees no data is available, and goes back to sleep. This is totally safe, so bidirectional communication with one condition variable is possible.

That being said, there is little advantage to waking up threads unnecessarily, so it is usually preferable to have one mutex protecting the data (i.e. you must hold the mutex to access the data), and two different condition variables indicating different conditions. This will minimize how many times you wake up a thread to find it has no data to work on (called a "spurious" notification).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top