C++ barrier::arrive_and_wait() Function



The std::barrier::arrive_and_wait() function in C++, is a synchronization mechanism introduced in C++20 that allows thread to wait until the specified number of threads have reached a certain point in execution.

When this function is invoked, it indicates that its arrival at the barrier and waits for other threads to arrive, once all the threads reached the barrier they are released to continue execution.

Syntax

Following is the syntax for std::barrier::arrive_and_wait() function.

void arrive_and_wait();

Parameters

It does not accepts any parameter.

Return value

This function does not returns anything.

Exception

It throws std::system_error with an error code allowed for mutex types on error.

Example 1

In the following example, we are going to consider the basic usage of the arrive_and_wait() function.

#include <iostream>
#include <thread>
#include <barrier>
#include <vector>
void x(int id, std::barrier < > & y) {
   std::cout << "Thread " << id << " Working\n";
   std::this_thread::sleep_for(std::chrono::seconds(1));
   std::cout << "Thread " << id << " reached barrier.\n";
   y.arrive_and_wait();
   std::cout << "Thread " << id << " passed the barrier.\n";
}
int main() {
   const int num_threads = 2;
   std::barrier < > y(num_threads);
   std::vector < std::thread > a;
   for (int i = 0; i < num_threads; ++i) {
      a.emplace_back(x, i + 1, std::ref(y));
   }
   for (auto & thread: a) {
      thread.join();
   }
   return 0;
}

Output

Output of the above code is as follows −

Thread 1 Working
Thread 2 Working
Thread 2 reached barrier.
Thread 1 reached barrier.
Thread 1 passed the barrier.
Thread 2 passed the barrier.

Example 2

Consider the following example, we are going to use the two separate barriers, where threads first synchronize at x1 after completing the first part and then at x2.

#include <iostream>
#include <thread>
#include <barrier>
#include <vector>
void a(int b, std::barrier < > & x1, std::barrier < > & x2) {
   std::cout << "Thread " << b << " Working on first task.\n";
   std::this_thread::sleep_for(std::chrono::seconds(1));
   x1.arrive_and_wait();
   std::cout << "Thread " << b << " Working on second task.\n";
   std::this_thread::sleep_for(std::chrono::seconds(1));
   x2.arrive_and_wait();
}
int main() {
   const int x = 2;
   std::barrier < > x1(x);
   std::barrier < > x2(x);
   std::vector < std::thread > threads;
   for (int i = 0; i < x; ++i) {
      threads.emplace_back(a, i + 1, std::ref(x1), std::ref(x2));
   }
   for (auto & thread: threads) {
      thread.join();
   }
   return 0;
}

Output

Following is the output of the above code −

Thread 2 Working on first task.
Thread 1 Working on first task.
Thread 1 Working on second task.
Thread 2 Working on second task.
cpp_barrier.htm
Advertisements