Reputation: 1766
I'm reading this std::condition_variable
example:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
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::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();
}
Let's focus on the beggining:
std::thread worker(worker_thread);
here, we start the worked, which will lock the mutex immediately:
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
Then, we lock the mutex on main to change the value of ready
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processing\n";
}
but how is it possible that we even arrive at the line ready=true
? The mutext m
is blocked from the worked thread, so the line std::lock_guard<std::mutex> lk(m);
will wait until the mutex m
is unlocked. As I understand, when a mutex is locked and we try to lock it, we'll wait until it gets unlocked. However, it'll never get unlocked because the worked thread is waiting, therefore not releasing it.
Upvotes: 2
Views: 1451
Reputation:
Here's another example that will give you the gist of the mechanism.
#include <cstdio>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
std::mutex mtx;
std::condition_variable cv;
bool signal = 0;
void A()
{
while (1)
{
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [](){return signal;});
signal = 0;
}
printf("Lock release from th A\n");
}
}
int main()
{
std::thread th(A);
for (unsigned i = 0; i < 100; i++)
{
{
std::lock_guard<std::mutex> lock(mtx);
signal = 1;
}
cv.notify_one();
printf("Sending signal %i\n", i);
std::this_thread::sleep_for(std::chrono::seconds(5));
}
th.join();
return 0;
}
Upvotes: 0
Reputation: 7100
In the link you have attached, note that the following
The wait operations atomically release the mutex and suspend the execution of the thread.
Hence the line
cv.wait(lk, []{return ready;});
releases the mutex and suspends the execution of the thread until the condition variable is notified, a timeout expires (with wit_for()
), or a spurious wake-up occurs, hence the thread is awakened, and the mutex is atomically reacquired
Upvotes: 0