Skip to content
Search

Std::condition variable

lastmod 2018-08-17created 2015-03-2410 edits

Sometimes tasks running on different threads need to wait for each other. A condition_variable lets you block a thread until a certain condition is met; the release condition can be set from another thread, or a timeout can be specified. In effect, condition_variable enables communication between threads. Think of condition_variable as the event object in the WIn32 API.

How to use

All variables involved in the wait() condition of a condition_variable must share the std::mutex passed to wait().

The common use of condition vars is something like:

// THREAD 01:
    pthread_mutex_lock(&mutex);
    while (!condition)
        pthread_cond_wait(&cond, &mutex);
    /* do something that requires holding the mutex and condition is true */
    pthread_mutex_unlock(&mutex);

// THREAD 02:
    pthread_mutex_lock(&mutex);
    /* do something that might make condition true */
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

Example

#include <chrono>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <string>
#include <iostream>

using namespace std;

static mutex _m;
static mutex _ms;
static condition_variable _cv;

void print(string const & str)
{
    lock_guard<mutex> guard(_ms);
    cout << str << endl;
}

void print(string const & str, thread::id const & id)
{
    lock_guard<mutex> guard(_ms);
    cout << str << id << endl;
}

void runner()
{
    unique_lock<mutex> locker(_m);
    print("Runner prefix wait(): ", this_thread::get_id());
    _cv.wait(locker);
    print("Runner suffix wait(): ", this_thread::get_id());
}

void runner2()
{
    for (int i = 0; i < 3; ++i) {
        print("prefix sleep.");
        this_thread::sleep_for(chrono::milliseconds(1000));
        print("suffix sleep.");
        _cv.notify_one();
        print("notify one.");
    }
}

int main()
{
    thread t1([&](){ runner(); });
    thread t2([&](){ runner(); });
    thread t3([&](){ runner2(); });

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

OUTPUT: (blank lines added where nothing happens, for readability)

prefix sleep.
Runner prefix wait(): 0x700000081000
Runner prefix wait(): 0x700000104000

suffix sleep.
notify one.
prefix sleep.
Runner suffix wait(): 0x700000081000

suffix sleep.
notify one.
prefix sleep.
Runner suffix wait(): 0x700000104000

suffix sleep.
notify one.

Favorite site

References


  1. Blog.naver_-jidon333-_condition_variable.pdf ↩