Consider the first thread function and global variables:
std::mutex mut;
std::condition_variable officer;
bool firstPlayerIsReady = false;
bool secondPlayerIsReady = false;
void firstPlayer(){
constexpr auto doIt = true;
while(doIt)
{
std::unique_lock lock{mut};
auto toContinue = ring();
secondPlayerIsReady = true;
firstPlayerIsReady = false;
officer.notify_one(); //#1
if(!toContinue) return;
officer.wait(lock,[=](){ return firstPlayerIsReady;});
}
}
It calls some ring and ring() returns a continuation condition; It then updates readiness values for each thread in the next loop;
Consider the next thread:
void secondPlayer(){
constexpr auto doIt = true;
while(doIt)
{
auto period = std::chrono::seconds(5);
std::this_thread::sleep_for(period);
std::unique_lock lock{mut}; //#2
officer.wait(lock,[this](){ return secondPlayerIsReady;});
auto toContinue = ring();
firstPlayerIsReady = true;
secondPlayerIsReady = false;
officer.notify_one();
if(!toContinue) return;
}
}
This thread wait for 5 seconds and after are locked with wait( ) until the first thread calls the notify_one( ); Further, similar to the first thread.
A priori, the line with #1 tag was executed earlier than the line with #2 tag, therefore the notification was sent earlier than the second thread was locked. The question is - Is there a notify_one ( ) queue? Otherwise, the notification wasn't sent, obviously.
constexpr volatile auto doIt
? while that expression is valid, thevolatile
qualifier is useless in the context of your code. secondly you are not actually protecting concurrent accesses tofirstPlayerIsReady
, likewise the other – Pyromanianotify()
is called beforewait()
? – Camilla