libstdc++
latch
Go to the documentation of this file.
1 // <latch> -*- C++ -*-
2 
3 // Copyright (C) 2020-2026 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file include/latch
26  * This is a Standard C++ Library header.
27  */
28 
29 #ifndef _GLIBCXX_LATCH
30 #define _GLIBCXX_LATCH 1
31 
32 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
34 #endif
35 
36 #include <bits/requires_hosted.h> // concurrency
37 
38 #define __glibcxx_want_latch
39 #include <bits/version.h>
40 
41 #ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait
42 #include <bits/atomic_base.h>
43 #include <ext/numeric_traits.h>
44 #include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc.
45 
46 namespace std _GLIBCXX_VISIBILITY(default)
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49 
50  class latch
51  {
52  public:
53  static constexpr ptrdiff_t
54  max() noexcept
55  {
57  constexpr auto __max = __int_traits<__detail::__platform_wait_t>::__max;
58  if constexpr (std::cmp_less(__max, __PTRDIFF_MAX__))
59  return __max;
60  return __PTRDIFF_MAX__;
61  }
62 
63  constexpr explicit
64  latch(ptrdiff_t __expected) noexcept
65  : _M_counter(__expected)
66  { __glibcxx_assert(__expected >= 0 && __expected <= max()); }
67 
68  ~latch() = default;
69 
70  latch(const latch&) = delete;
71  latch& operator=(const latch&) = delete;
72 
73  _GLIBCXX_ALWAYS_INLINE void
74  count_down(ptrdiff_t __update = 1)
75  {
76  __glibcxx_assert(__update >= 0 && __update <= max());
77  auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update,
78  memory_order::release);
79  if (std::cmp_equal(__old, __update))
80  __atomic_impl::notify_all(&_M_counter);
81  else
82  __glibcxx_assert(std::cmp_less(__update, __old));
83  }
84 
85  _GLIBCXX_ALWAYS_INLINE bool
86  try_wait() const noexcept
87  { return __atomic_impl::load(&_M_counter, memory_order::acquire) == 0; }
88 
89  _GLIBCXX_ALWAYS_INLINE void
90  wait() const noexcept
91  {
92  auto const __vfn = [this] {
93  return __atomic_impl::load(&_M_counter, memory_order::acquire);
94  };
95  auto const __pred = [](__detail::__platform_wait_t __v) {
96  return __v == 0;
97  };
98  std::__atomic_wait_address(&_M_counter, __pred, __vfn);
99  }
100 
101  _GLIBCXX_ALWAYS_INLINE void
102  arrive_and_wait(ptrdiff_t __update = 1) noexcept
103  {
104  // The standard specifies this functions as count_down(update); wait();
105  // but we combine those two calls into one and avoid the wait() if we
106  // know the counter reached zero.
107 
108  __glibcxx_assert(__update >= 0 && __update <= max());
109  // Use acq_rel here because an omitted wait() would have used acquire:
110  auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update,
111  memory_order::acq_rel);
112  if (std::cmp_equal(__old, __update))
113  __atomic_impl::notify_all(&_M_counter);
114  else
115  {
116  __glibcxx_assert(std::cmp_less(__update, __old));
117  wait();
118  }
119  }
120 
121  private:
122  alignas(__detail::__platform_wait_alignment)
123  __detail::__platform_wait_t _M_counter;
124  };
125 _GLIBCXX_END_NAMESPACE_VERSION
126 } // namespace
127 #endif // __cpp_lib_latch
128 #endif // _GLIBCXX_LATCH
requires_hosted.h
numeric_traits.h
std
ISO C++ entities toplevel namespace is std.
atomic_base.h
__gnu_cxx::__int_traits
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.
Definition: ext/numeric_traits.h:134
intcmp.h
version.h
std::max
constexpr const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:257