1#ifndef BOOST_COMPAT_LATCH_HPP_INCLUDED
2#define BOOST_COMPAT_LATCH_HPP_INCLUDED
3
4// Copyright 2023 Peter Dimov.
5// Copyright 2023 Christian Mazakas.
6// Distributed under the Boost Software License, Version 1.0.
7// https://www.boost.org/LICENSE_1_0.txt
8
9#include <boost/assert.hpp>
10
11#include <climits>
12#include <condition_variable>
13#include <mutex>
14
15namespace boost
16{
17namespace compat
18{
19
20class latch {
21private:
22 std::ptrdiff_t n_;
23 mutable std::mutex m_;
24 mutable std::condition_variable cv_;
25
26public:
27 explicit latch(std::ptrdiff_t expected) : n_{expected}, m_{}, cv_{} {
28 BOOST_ASSERT(n_ >= 0);
29 BOOST_ASSERT(n_ <= max());
30 }
31
32 latch(latch const &) = delete;
33 latch &operator=(latch const &) = delete;
34
35 ~latch() = default;
36
37 void count_down(std::ptrdiff_t n = 1) {
38 std::unique_lock<std::mutex> lk(m_);
39 count_down_and_notify(lk, n);
40 }
41
42 bool try_wait() const noexcept {
43 std::unique_lock<std::mutex> lk(m_);
44 return is_ready();
45 }
46
47 void wait() const {
48 std::unique_lock<std::mutex> lk(m_);
49 wait_impl(lk);
50 }
51
52 void arrive_and_wait(std::ptrdiff_t n = 1) {
53 std::unique_lock<std::mutex> lk(m_);
54 bool should_wait = count_down_and_notify(lk, n);
55 if (should_wait) {
56 wait_impl(lk);
57 }
58 }
59
60 static constexpr std::ptrdiff_t max() noexcept { return PTRDIFF_MAX; }
61
62private:
63 bool is_ready() const { return n_ == 0; }
64
65 bool count_down_and_notify(std::unique_lock<std::mutex> &lk,
66 std::ptrdiff_t n) {
67 BOOST_ASSERT(n <= n_);
68 n_ -= n;
69 if (n_ == 0) {
70 lk.unlock();
71 cv_.notify_all();
72 return false;
73 }
74
75 return true;
76 }
77
78 void wait_impl(std::unique_lock<std::mutex> &lk) const {
79 cv_.wait(lock&: lk, p: [this] { return this->is_ready(); });
80 }
81};
82
83} // namespace compat
84} // namespace boost
85
86#endif // #ifndef BOOST_COMPAT_LATCH_HPP_INCLUDED
87

source code of boost/libs/compat/include/boost/compat/latch.hpp