Класс latch
Класс latch из заголовка <latch>
представляет собой одноразовый барьер синхронизации.
Он позволяет одному или нескольким потокам ожидать,
пока заданное количество потоков не выполнят операцию
обратного отсчёта. В отличие от barrier,
класс latch является одноразовым: после того
как счётчик достигнет нуля, его нельзя сбросить или
использовать повторно.
При создании объекта latch в конструктор
передаётся начальное значение счётчика. Каждый поток
может уменьшить счётчик на единицу с помощью метода
count_down. Поток, который хочет дождаться
обнуления счётчика, вызывает метод wait.
Также существуют методы try_wait и
arrive_and_wait.
Синтаксис
#include <latch>
std::latch name(count);
Основные методы
Класс latch предоставляет следующие методы:
void count_down(ptrdiff_t n = 1);
bool try_wait() const noexcept;
void wait() const;
void arrive_and_wait(ptrdiff_t n = 1);
Пример
Давайте создадим объект latch со счётчиком
равным 3. Запустим три потока, каждый из
которых уменьшает счётчик, и главный поток, который
ожидает обнуления:
#include <iostream>
#include <latch>
#include <thread>
#include <vector>
using namespace std;
int main()
{
latch lat(3);
vector<thread> threads;
for (int i = 0; i < 3; i++)
{
threads.emplace_back([&lat, i]()
{
cout << "Thread " << i << " started" << endl;
lat.count_down();
});
}
lat.wait();
cout << "All threads finished" << endl;
for (auto& t : threads)
{
t.join();
}
return 0;
}
Результат выполнения кода:
"Thread 0 started"
"Thread 1 started"
"Thread 2 started"
"All threads finished"
Пример
Давайте используем метод arrive_and_wait,
который одновременно уменьшает счётчик и ожидает
его обнуления:
#include <iostream>
#include <latch>
#include <thread>
#include <vector>
using namespace std;
int main()
{
latch lat(4);
vector<thread> threads;
for (int i = 0; i < 4; i++)
{
threads.emplace_back([&lat, i]()
{
cout << "Thread " << i << " ready" << endl;
lat.arrive_and_wait();
cout << "Thread " << i << " continues" << endl;
});
}
for (auto& t : threads)
{
t.join();
}
return 0;
}
Результат выполнения кода:
"Thread 0 ready"
"Thread 1 ready"
"Thread 2 ready"
"Thread 3 ready"
"Thread 0 continues"
"Thread 1 continues"
"Thread 2 continues"
"Thread 3 continues"
Пример
Давайте проверим метод try_wait, который
возвращает true, если счётчик уже обнулён,
и false в противном случае:
#include <iostream>
#include <latch>
using namespace std;
int main()
{
latch lat(1);
cout << boolalpha;
cout << lat.try_wait() << endl;
lat.count_down();
cout << lat.try_wait() << endl;
return 0;
}
Результат выполнения кода:
false
true