I have a code something like the following:
#include <mutex>
#include <condition_variable>
#include <future>
std::mutex mtx;
std::condition_variable cv;
std::future<void> worker;
void worker_thread() {
{
std::lock_guard<std::mutex> lg{ mtx };
// do something 1
}
cv.notify_one();
// do something 2
}
int main() {
{
std::unique_lock<std::mutex> lg{ mtx };
worker = std::async(std::launch::async, worker_thread);
cv.wait(lg);
}
// do something 3
}
The main thread does not proceed to // do something 3
and I can't understand why. I thought the line cv.notify_one()
should be reached from the worker thread after cv.wait(lg)
has been passed by the main thread, so there is no reason to hang.
The worker thread is responsible for some streaming data processing, while the main thread is mainly responsible for GUI event processing.
// do something 1
is about some initialization that should be done inside the worker thread. The main thread should wait for the worker thread to finish it.
// do something 2
is the main job of the worker thread.
// do something 3
is the main job of the main thread.
Changing cv.notify_one()
to cv.notify_all()
didn't help.
Is this usage of condition variable correct?
I have to backtrack on my original answer, and I apologize to Junekey for that. I misread the code, and concluded there was a race condition. I cannot reproduce the problem. We need an example that actually blocks forever on the cv.wait in order to figure out why it is doing so. Nevertheless, the code is incorrect if for no other reason than that it could get a spurious notification and pass through cv.wait before the worker_thread calls cv.notify. That rarely happens, but it does happen.
This code is more or less canonical:
#include <mutex>
#include <condition_variable>
#include <thread>
std::mutex mtx;
std::condition_variable cv;
bool worker_done = false; // <<< puts the "condition" in condition_variable
void worker_thread() {
// do something 1
{
std::lock_guard<std::mutex> lg{ mtx };
worker_done = true; // ... and whatever
}
cv.notify_one();
// do something 2
}
int main() {
std::thread workman(worker_thread);
{
std::unique_lock<std::mutex> lg{ mtx };
while (!worker_done) {
cv.wait(lg);
}
}
// do something 3
workman.join();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With