C++ 20 – <latch> Header
Last Updated :
15 May, 2023
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
#include <iostream>
#include <latch>
#include <thread>
void worker(std::latch& latch)
{
std::cout << "Worker thread started" << std::endl;
std::cout << "Worker thread finished" << std::endl;
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();
}
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
#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
Share your thoughts in the comments
Please Login to comment...