Saturday, 27 June 2020

Multithreading:5.condition_variable

Many a times we would want a thread to execute some commands based on some conditions. For this we are going to use std:: condition_variable. This class methods such wait, notify which would either make a thread wait or notify other threads. That is exactly the functionality we would need.

To go into code, we would want to understand to basic methods in the class std::condition_variable. One is wait and the other is notify

Wait 
void wait( std::unique_lock<std::mutex>& lock );
lock:an object of type std::unique_lock<std::mutex>, which must be locked by the current thread. Need not be locked till notify

template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
Pred: predicate which returns ​false if the waiting should be continued.

Notify
void notify_all() noexcept;
Unblocks all threads currently waiting for *this.

In the below code we want the main thread to print abcdef and the thread t1 to print 123456.
For this to happen, we want the main thread to start printing the alphabets and t1 to wait till the main completes its job. And we need some variable to tell that the main is done with this job, in this case we are using a bool alphadone.

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mu;
std::condition_variable cv;
std::string data;
bool alphadone = false;
bool numericdone = false;
void print_number()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(mu);
cv.wait(lk, [] {return alphadone; });//wait till alphadone is made true by main thread
//thread is adding numbers to data
data += " 123456";
// Send data back to main()
numericdone = true;
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread t1(print_number);
//main is adding alphabets to data
data = "abcdef";
// send data to the t1 thread
{
//print_number thread will wait till alphadone is made true
std::lock_guard<std::mutex> lk(mu);
alphadone = true;
}
cv.notify_all();
// wait for print_number
{
std::unique_lock<std::mutex> lk(mu);
cv.wait(lk, [] {return numericdone; }); //wait for numericdone to be made true
}
std::cout << data << '\n';
t1.join();
return 1;
}

No comments:

Post a Comment