Reputation: 3260
I am reading the example code of using condition_variable
here. I post the code below:
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::cout << "------------------------\n";
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing data\n";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completed\n";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processing\n";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});
}
std::cout << "Back in main(), data = " << data << '\n';
worker.join();
return 0;
}
My question is the worker_thread
is launched first, so I would assume the mutex m
is locked by the worker_thread
, but why in the main
the mutex m
still can be locked by lock_guard
?
Upvotes: 2
Views: 1181
Reputation: 275200
A condition variable is only one part of a tripod.
The three parts are the condition variable, state and the mutex that guards the state.
The condition variable provides a mechanism to notify when the state changes.
This operation uses all 3:
cv.wait(lk, []{return ready;})
The condition variable's method takes a lock (which must have been acquired), and a lambda (which tests the state).
Within the wait
method, the lk
is unlocked until the condition variable detects a message (which could be spurious). When it detects a message, it relocks the mutex and runs the test (whose goal is to determine if the detection was spurious). If the test fails, it unlocks and waits again: if the test passes, it keeps the lock locked and exits.
There is also the "the test threw" path, which results in a different lock state depending on the version of the standard your code implemented (C++11 had a defect, IIRC).
The important thing you missed is that wait
unlocks the mutex passed in.
Upvotes: 8