condition_variable / shared variable / Signalling

Thread1 notifies/signals Thread2 for condition. Then thread2 starts executes, until then thread2 is blocked
Advantages?
1. Avoids busy waiting, ie done by spinlock
2. Similar to [Semaphores]

POSIX


#include <stdio.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
using namespace std;

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *fun1(void* arg) {
    //pthread_mutex_lock(&mutex);
    cout << "Thread1 waiting on condition\n";

    //pthread_cond_wait() might provide unexepected result without mutex
    pthread_cond_wait(&cond, &mutex);
    cout << "Condition satisfied\n";
    //pthread_mutex_unlock(&mutex);
}
void *fun2(void* arg) {
    sleep(1);
    cout << "Thread2 signalled the condition\n";
    pthread_cond_signal(&cond);
}
int main(){
    pthread_t tid1,tid2;
    pthread_create(&tid1, 0, fun1, 0);
    pthread_create(&tid2, 0, fun2, 0);

    pthread_join(tid1, 0);
    pthread_join(tid2, 0);
}
$ ./a.out
Thread1 waiting on condition
Thread2 signalled the condition
Condition satisfied
            

Ping Pong Game

POSIX pthread C++11 (2 threads. 1 producer 1 consumer) C++11 (4 threads. 2 producers 2 consumers)
Code
pthread_cond_t cond_ping = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_pong = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int j=0;

void *pong(void* arg) {
    while (j < 10) {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond_pong, &mutex);
        ++j;
        cout << "Pong" << ",j:"<< j << "\n";
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&cond_ping);
    }
}
void *ping(void* arg) {
    while( j < 10) {
        sleep(1);
        pthread_cond_signal(&cond_pong);
        pthread_mutex_lock(&mutex);
        ++j;
        cout << "Ping" << ",j:" << j << "\n";
        pthread_cond_wait(&cond_ping, &mutex);
        pthread_mutex_unlock(&mutex);
    }
}
int main(){
    pthread_t tid1,tid2;
    pthread_create(&tid1, 0, ping, 0);
    pthread_create(&tid2, 0, pong, 0);

    pthread_join(tid1, 0);
    pthread_join(tid2, 0);
}
$ ./a.out
Ping,j:1
Pong,j:2
Ping,j:3
Pong,j:4
Ping,j:5
Pong,j:6
Ping,j:7
Pong,j:8
Ping,j:9
Pong,j:10
thread1 prints ping and then signal on condition variable.
thread2 waits for signal and then only prints pong
notify_one() notify 1 of threads waiting on
condition variable (test).
bool test = false;
mutex m;
condition_variable cv;

void ping() {
  // No mutex is needed since only 1 thread
  // enters here
  cout << "ping\n";
  test = true;
  cv.notify_one();
}
void pong() {
    unique_lock ul(m);

    // Any thread entering is blocked on condition_variable cv
    // For thread to enter Critical Section, lambda should return true
    // test is condition predicate
    cv.wait(ul, []
            { return test; });
    cout << "pong\n";
}

int main(){
    int num_of_threads = 2;
    thread t[num_of_threads];
    t[0] = thread(pong);
    t[1] = thread(ping);

    for (auto i = 0; i < num_of_threads; i++)
        t[i].join();
    return 0;
}
$ ./a.out
ping
pong
thread1,2 prints ping and then signal on condition variable.
thread3,4 waits for signal and then only prints pong
notify_all() notify all of threads waiting on
condition variable (test).
mutex m;
condition_variable cv;

void ping() {
    unique_lock ul(m);

    // Any thread entering is blocked on condition_variable cv
    // !test means test should be false
    cv.wait(ul, []
            { return !test; });
    cout << "ping\n";
    test = true;
    cv.notify_all();
}
void pong() {
    unique_lock ul(m);

    // Any thread entering is blocked on condition_variable cv
    // For thread to enter Critical Section, test should be true
    // test is condition predicate
    cv.wait(ul, []
            { return test; });
    test = false;
    cout << "pong\n";
}

int main() {
  int num_of_threads = 4;
  thread t[num_of_threads];
  t[0] = thread(pong);
  t[1] = thread(pong);
  t[2] = thread(ping);
  t[3] = thread(ping);

  for (auto i = 0; i < num_of_threads; i++)
      t[i].join();
  return 0;
}
$ ./a.out
ping
pong
ping
pong