DigestCPP

Lets Understand With Example

  • Home
  • Design Patterns
  • Adapter Design Pattern
  • Strategy Design Pattern
  • C++11 Features
  • std::thread c++11
  • Contact Us

std::condition variable c++11

std::condition_variable is a class in c++11, it will be used by thread to wake up other(one or more) waiting thread. In other word, one or multiple threads are waiting for a specific condition, when condition is satisfy then a thread can wake up other (one or more) waiting thread.

Main API of std::condition_variable class (assume std::condition_variable obj;) :

  • obj.notify_one(); //wake up only one thread
  • obj.notify_all(); //wake up all waiting threads
  • obj.wait(ul); //ul is unique pointer, thread waits for notification
  • obj.wait_for(ul, duration); //ul is unique pointer, thread waits for notification for duration
  • obj.wait_until(ul, time_point); //ul is unique pointer, thread waits for notification until time-point

Note:

  • wait() API internally unlock the mutex before going to sleep that why we will be using unique lock instead of lock guard.
  • wait() API internally lock the mutex after receiving notification from other thread that why we will be using unique lock instead of lock guard.
  • Using lambdas, checking flag to avoid suspicious wake up call.

Example: There are two thread(Reader and Writer), Reader is waiting for Writer thread, so using condition variable Writer thread(after completion of writing) can wake up Reader thread.

Source code with example:

/*
Program: Condition Variable 
Author: Alpha Master
Date: 6 Feb 2021
*/

//Header File
#include<iostream>
#include<thread>
#include<chrono>
#include<mutex>
#include<condition_variable>

//Global Variable
bool dataReady{false}; 
std::mutex gMtx;
std::condition_variable gConVar;
int data{0};


//Reader Thread
void ReadThread()
{
    auto i{0};
    while(i<5)
    {
        std::cout<<"!!!Waiting, Data is NOT ready"<<std::endl;
        {
	    std::unique_lock<std::mutex> ul(gMtx);
            //Using lambdas, checking flag to avoid suspicious wakeup call
            //wait internally unlock the mutex so we are using unique pointer 
            gConVar.wait(ul, []{return dataReady;});
            std::cout<<"Got the data:"<<data<<std::endl;
            dataReady = false;
       	}
        ++i;
    }
}

//Writer Thread
void WriteThread()
{
    auto i{0};
    while(i<5)
    {
	//Wait till, data is read by reader
        while(dataReady)
        {
	    std::this_thread::sleep_for(std::chrono::seconds(1));	
        }
        //Now, Writer will write
        {
            std::lock_guard<std::mutex> lg(gMtx);
            ++data;
            dataReady = true; 
            //purposefully waiting to verify the result
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        gConVar.notify_one();
        ++i;
    }

}

int main()
{
    std::cout<<"Conditon variable Functionality"<<std::endl;
	
    //Thread 1 and its joinable
    std::thread t1(ReadThread);
   
    //Thread 2 and its also joinable
    std::thread t2(WriteThread);

    //std::cout<<"Main thread is Waiting for Child thread"<<std::endl;
    t1.join();
    t2.join();

    return 0;
};

Output:

Conditon variable Functionality
!!!Waiting, Data is NOT ready
Got the data:1
!!!Waiting, Data is NOT ready
Got the data:2
!!!Waiting, Data is NOT ready
Got the data:3
!!!Waiting, Data is NOT ready
Got the data:4
!!!Waiting, Data is NOT ready
Got the data:5

Primary Sidebar

Copyright © 2021

  • Contact us