]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/libcxx/include/latch
Merge llvm-project main llvmorg-17-init-19304-gd0b54bb50e51
[FreeBSD/FreeBSD.git] / contrib / llvm-project / libcxx / include / latch
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef _LIBCPP_LATCH
11 #define _LIBCPP_LATCH
12
13 /*
14     latch synopsis
15
16 namespace std
17 {
18
19   class latch
20   {
21   public:
22     static constexpr ptrdiff_t max() noexcept;
23
24     constexpr explicit latch(ptrdiff_t __expected);
25     ~latch();
26
27     latch(const latch&) = delete;
28     latch& operator=(const latch&) = delete;
29
30     void count_down(ptrdiff_t __update = 1);
31     bool try_wait() const noexcept;
32     void wait() const;
33     void arrive_and_wait(ptrdiff_t __update = 1);
34
35   private:
36     ptrdiff_t __counter; // exposition only
37   };
38
39 }
40
41 */
42
43 #include <__assert> // all public C++ headers provide the assertion handler
44 #include <__atomic/atomic_base.h>
45 #include <__atomic/atomic_sync.h>
46 #include <__atomic/memory_order.h>
47 #include <__availability>
48 #include <__config>
49 #include <cstddef>
50 #include <limits>
51 #include <version>
52
53 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
54 #  pragma GCC system_header
55 #endif
56
57 #ifdef _LIBCPP_HAS_NO_THREADS
58 # error "<latch> is not supported since libc++ has been configured without support for threads."
59 #endif
60
61 _LIBCPP_PUSH_MACROS
62 #include <__undef_macros>
63
64 #if _LIBCPP_STD_VER >= 14
65
66 _LIBCPP_BEGIN_NAMESPACE_STD
67
68 class latch
69 {
70     __atomic_base<ptrdiff_t> __a_;
71
72 public:
73     static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept {
74         return numeric_limits<ptrdiff_t>::max();
75     }
76
77     inline _LIBCPP_INLINE_VISIBILITY
78     constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected)
79     {
80         _LIBCPP_ASSERT_UNCATEGORIZED(__expected >= 0,
81                                      "latch::latch(ptrdiff_t): latch cannot be "
82                                      "initialized with a negative value");
83         _LIBCPP_ASSERT_UNCATEGORIZED(__expected <= max(),
84                                      "latch::latch(ptrdiff_t): latch cannot be "
85                                      "initialized with a value greater than max()");
86     }
87
88     _LIBCPP_HIDE_FROM_ABI ~latch() = default;
89     latch(const latch&) = delete;
90     latch& operator=(const latch&) = delete;
91
92     inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
93     void count_down(ptrdiff_t __update = 1)
94     {
95         _LIBCPP_ASSERT_UNCATEGORIZED(
96             __update >= 0, "latch::count_down called with a negative value");
97         auto const __old = __a_.fetch_sub(__update, memory_order_release);
98         _LIBCPP_ASSERT_UNCATEGORIZED(
99             __update <= __old, "latch::count_down called with a value greater "
100                                "than the internal counter");
101         if (__old == __update)
102             __a_.notify_all();
103     }
104     inline _LIBCPP_INLINE_VISIBILITY
105     bool try_wait() const noexcept
106     {
107         return 0 == __a_.load(memory_order_acquire);
108     }
109     inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
110     void wait() const
111     {
112         __cxx_atomic_wait(&__a_.__a_, [this]() -> bool {
113             return try_wait();
114         });
115     }
116     inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
117     void arrive_and_wait(ptrdiff_t __update = 1)
118     {
119         _LIBCPP_ASSERT_UNCATEGORIZED(
120             __update >= 0, "latch::arrive_and_wait called with a negative value");
121         // other preconditions on __update are checked in count_down()
122
123         count_down(__update);
124         wait();
125     }
126 };
127
128 _LIBCPP_END_NAMESPACE_STD
129
130 #endif // _LIBCPP_STD_VER >= 14
131
132 _LIBCPP_POP_MACROS
133
134 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
135 #  include <atomic>
136 #endif
137
138 #endif //_LIBCPP_LATCH