Monday, August 1, 2016

A CountdownLatch for C++ multi-threaded programs

Java standard library comes with CountDownLatch which is  synchronization aid which allows one or more threads to wait on until a set of operations being performed by other threads completes.

For  example, let one thread input a string to some queues (one or two queues) and wait for completion of two operations, which are:
  1. Calculating the hashcode of the string
  2. Finding the count of unique chars in the string
The task submitter may wait asynchronously on the countdownlatch for the operations to be completed. The task executor threads will countdown the countdown latch once they complete their operations. Waiters get notified once the count of the countdownlatch reches zero. In this example, the waiter thread will create a countdownlatch object with count 2 and somehow pass the reference of the countdownlatch object to the executor threads (May be putting the string and pointer to the countdownlatch object in the task object).

We may achieve similar functionalities using Posix thread mutexes and condition variables (Threading libraries other than pthread will work as well). But as CountDownLatch is an useful and frequently used patterns, so it will be nice to have a library for the same.
I implemented a CountDownLatch class for C++ in less than 100 lines of code which provides similar functionalities as its Java counterpart. The code is available in Github(countdownlatch). May be useful for you as well :):):)...........

Below is a sample program demonstrating the use of countdownlatch:

#include <unistd.h>
#include <thread>
#include <vector>
#include <iostream>
#include <countdownlatch.hpp>

void fun(clatch::countdownlatch *cl) {
    cl->await();
    std::cout << "Wait is over " << std::endl;
}

int main() {
    auto cl = new clatch::countdownlatch(10);
    int i = 0;
    std::vector<std::thread*> ts;
    while (i++ < 2) {
        std::thread *t  = new std::thread(fun, cl);
        ts.push_back(t);
    }

    i = 0;
    while (i++ < 10) {
        sleep(1);
        cl->count_down();
    }
    i = 0;
    while (i < 2) {
        ts[i++]->join();
    }
    i = 0;
    while (i < 2) {
        delete ts[i++];
    }
    delete cl;
    return 0;
}

 

2 comments:

  1. So, in other words, you are actually implementing a 'barrier' mechanism ?

    ReplyDelete
    Replies
    1. No.. It's very similar to the countdown latch that Java provides.

      Delete