Open In App

C++ 20 – <latch> Header

Last Updated : 15 May, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In C++20, the header was introduced, which allows a synchronization primitive known as a latch. Latches allow one or more threads to wait until a certain number of operations have been finished before proceeding.

A synchronization object called a latch is initialized with a preset count value. This object enables threads to pause until the count is zero. If count_down() is invoked, the latch’s count is reduced by one. After the count has reached zero, any threads that were awaiting the latch will be freed and able to continue.

Syntax:

#include <latch>

The std::latch class has four member functions

  • explicit latch(std::ptrdiff_t count): Constructs a new latch object with an initial count of the count.
  • void count_down(std::ptrdiff_t n = 1): Subtract n from the latch count. Whenever the count reaches zero, all of the threads that are waiting on the latch become unblocked.
  • bool try_wait() const noexcept: Verifies if the tally has hit zero. In that eventuality, the output is true. If not, there will be no holdup in returning false.
  • void wait() const: Blocks the calling thread until the latch count reaches zero.

Note: Below program is used in C++14 version which will give us error. The header <latch> was added to the C++ Standard Library in C++20, so if you are using a compiler that supports only earlier versions of C++, such as C++11, C++14 or C++17, you won’t be able to use it. To fix this error, you can either upgrade your compiler to one that supports C++20 or use a different synchronization primitive, such as a barrier or a condition variable, to achieve the same functionality.

Examples of the <latch> Header

Example 1: 

C++14




// C++ Program to demonstrate Multithreading with latch
#include <iostream>
#include <latch>
#include <thread>
  
void worker(std::latch& latch)
{
    std::cout << "Worker thread started" << std::endl;
  
    // do some work
    std::cout << "Worker thread finished" << std::endl;
  
    // decrement the latch count
    latch.count_down();
}
  
int main()
{
    const int num_threads = 3;
    std::latch latch(num_threads);
  
    for (int i = 0; i < num_threads; ++i) {
        std::thread t(worker, std::ref(latch));
        t.detach();
    }
  
    // wait until all threads have finished
    latch.wait();
    std::cout << "All worker threads finished" << std::endl;
    return 0;
}


Output:

Worker thread finished
Worker thread started
Worker thread finished
All worker threads finished

Explanation of the above program

We establish a latch that has a count equal to the number of threads and assign it as a reference to every worker thread in this particular example. Once each worker thread completes its task, it executes the count_down() function on the latch. Eventually, the main thread invokes the wait() function on the latch, suspending execution until the latch’s count reduces to zero, implying that all worker threads have executed count_down(). Upon reaching zero, the primary thread becomes unblocked and emits a notification signifying the completion of all worker threads.

Example 2:  

C++14




// C++ Program to demonstrate use of producer-consumer
// Problem
#include <iostream>
#include <latch>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
  
const int kNumProducers = 2;
const int kNumConsumers = 2;
const int kNumItemsPerProducer = 5;
  
std::queue<int> gQueue;
std::mutex gMutex;
std::latch gLatch(kNumProducers);
  
void Producer(int id)
{
    for (int i = 0; i < kNumItemsPerProducer; ++i) {
        std::scoped_lock lock(gMutex);
        gQueue.push(id * kNumItemsPerProducer + i);
    }
    gLatch.count_down();
}
  
void Consumer(int id)
{
    gLatch.wait();
    while (true) {
        std::scoped_lock lock(gMutex);
        if (!gQueue.empty()) {
            int item = gQueue.front();
            gQueue.pop();
            std::cout << "Consumer " << id << " got item "
                      << item << std::endl;
        }
        else {
            break;
        }
    }
}
  
int main()
{
    std::vector<std::thread> producers;
    std::vector<std::thread> consumers;
  
    for (int i = 0; i < kNumProducers; ++i) {
        producers.emplace_back(Producer, i);
    }
  
    for (int i = 0; i < kNumConsumers; ++i) {
        consumers.emplace_back(Consumer, i);
    }
  
    for (auto& t : producers) {
        t.join();
    }
  
    for (auto& t : consumers) {
        t.join();
    }
  
    return 0;
}


Output:

Consumer 1 got item 1
Consumer 1 got item 2
Consumer 1 got item 3
Consumer 1 got item 4


Similar Reads

random header in C++ | Set 1(Generators)
This header introduces random number generation facilities. This library allows to produce random numbers using combinations of generators and distributions. Generators: Objects that generate uniformly distributed numbers.Distributions: Objects that transform sequences of numbers generated by a generator into sequences of numbers that follow a spec
11 min read
clocale header file in C++
clocale: This header file contains declaration of a set of functions and a type for internationalization support tasks. It supports date format or country specific currency symbols. For example, date/time formatting, monetary formatting and many more. Methods in clocale header: localeconv(): This function returns an object which represents numeric
2 min read
Exception Header in C++ With Examples
C++ provides a list of standard exceptions defined in header &lt;exception&gt; in namespace std where "exception" is the base class for all standard exceptions. All exceptions like bad_alloc, bad_cast, runtime_error, etc generated by the standard library inherit from std::exception. Therefore, all standard exceptions can be caught by reference. Hea
5 min read
Header Guard in C++
Header Guards in C++ are conditional compilation directives that help to avoid errors that arise when the same function or variable is defined more than once by the mistake of a programmer. According to C++, when a function or a variable is defined more than once, it yields an error. Below is the program to illustrate the same: Program 1: C/C++ Cod
4 min read
Creating a C++ reusable Header File and its Implementation Files
Reusability is one of the most important concepts of Software Engineering. Reusability means developing code that can be reused either in the same program or in different programs. C++ allows reusability through inheritance, containership, polymorphism, and genericity. But, there is another way to define independent building blocks. This can be ach
4 min read
C++ 11 - &lt;cfenv&gt; Header
C++ 11 comes with new features and improvements and one of the main addition is the &lt;cfenv&gt; header that helps the programmers or developers with great control over the floating-point environment. It governs critical features of floating-point arithmetic like rounding modes and exceptions. &lt;cfenv&gt; gives programmers the tools they need to
4 min read
C++ 11 - &lt;ratio&gt; Header
The header file, brought about by C++11, offers a class template for ratios and a collection of aliases to represent the same. The purpose of this is to enable the definition and manipulation of ratios while also providing a means to express the links between diverse units of measurement. Ratio Header in C++ The Ratio class is a template class that
3 min read
Use of "stdafx.h" header in C++ with examples
A header file contains the set of predefined standard library functions. The header file can be included in the program with the C preprocessing directive "#include". All the header files have ".h" extension. Syntax: #include &lt;header_file&gt; / "header_file" Here, #: A preprocessor directiveheader_file: Name of the header file The #include tells
3 min read
C++23 Library - &lt;spanstream&gt; Header
The &lt;spanstream&gt; header is a new addition to C++ 23 Standard Libraries Collection. It provides fixed character buffer streams for input and output. It is a collection of classes and function templates that let you manipulate letter stretch as if they were streams, much like &lt;stringstream&gt; or &lt;istringstream&gt;. However, it works with
3 min read
C++ 23 - &lt;flat_set&gt; Header
&lt;flat_set&gt; is a header file that provides the implementation of the std::flat_set container class in C++, which is a sorted associative container that stores unique elements and allows for fast access, insertion, and removal of elements. The flat_set is a container similar to the set but its elements are stored contiguously in memory. This ca
10 min read
Article Tags :
Practice Tags :