vendredi 23 juillet 2021

How does the wait() call get invoked with notify in this code?

I have a c++ code as follows that uses condition-variable for synchronization.

#include <iostream> 
#include <condition_variable>

int n = 4;
enum class Turn { FOO, BAR };
Turn turn = Turn::FOO;

std::mutex mut;
std::condition_variable cv;

void foo() {
    for (int i = 0; i < n; i++) {
        std::unique_lock<std::mutex> lock(mut);

        // wait for signal from bar & turn == FOO
        cv.wait(lock, [] {return turn == Turn::FOO; });

        std::cout << "foo" << std::endl;

        // unlock & signal bar
        lock.unlock();
        turn = Turn::BAR;
        cv.notify_one();
    }
}

void bar() {
    for (int i = 0; i < n; i++) {
        std::unique_lock<std::mutex> lock(mut);

        // wait for signal from foo & turn == BAR
        cv.wait(lock, [] {return turn == Turn::BAR; });

        std::cout << "bar" << std::endl;

        // unlock &  signal foo
        lock.unlock();
        turn = Turn::FOO;
        cv.notify_one();
    }
}

int main() {
    std::thread thread_1(foo);
    std::thread thread_2(bar);
    thread_2.join();
    thread_1.join();
    
    return 0; 
}

The output observed:

Output

Question:

How would the cv.wait(lock, [] {return turn == Turn::FOO; }); inside the foo() get triggered in the beginning?

From what I read, the wait() call with the predicate would be equivalent to:while (!pred()) { wait(lock); }. The predicate is true at the beginning (the initial value of turn is Turn::FOO), but how would the wait call get a notify? Regarding wait(), I see this:

Atomically unlocks lock, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits.

But I don't see the other thread's (the one running bar()) to have it's notify_one() executed since turn is still FOO.

Aucun commentaire:

Enregistrer un commentaire