xref: /llvm-project/libcxx/include/__atomic/atomic_flag.h (revision 0e34f3f4968d8d32a64e26777541f939deb2274c)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___ATOMIC_ATOMIC_FLAG_H
10 #define _LIBCPP___ATOMIC_ATOMIC_FLAG_H
11 
12 #include <__atomic/atomic_sync.h>
13 #include <__atomic/contention_t.h>
14 #include <__atomic/memory_order.h>
15 #include <__atomic/support.h>
16 #include <__chrono/duration.h>
17 #include <__config>
18 #include <__memory/addressof.h>
19 #include <__thread/support.h>
20 #include <cstdint>
21 
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 #  pragma GCC system_header
24 #endif
25 
26 _LIBCPP_BEGIN_NAMESPACE_STD
27 
28 struct atomic_flag {
29   __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_;
30 
31   _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
32     return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);
33   }
34   _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
35     return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);
36   }
37 
38   _LIBCPP_HIDE_FROM_ABI bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
39     return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);
40   }
41   _LIBCPP_HIDE_FROM_ABI bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT {
42     return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);
43   }
44   _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
45     __cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);
46   }
47   _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT {
48     __cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);
49   }
50 
51 #if _LIBCPP_STD_VER >= 20
52   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const
53       volatile _NOEXCEPT {
54     std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
55   }
56   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
57   wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
58     std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
59   }
60   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT {
61     std::__atomic_notify_one(*this);
62   }
63   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); }
64   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
65     std::__atomic_notify_all(*this);
66   }
67   _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); }
68 #endif
69 
70 #if _LIBCPP_STD_VER >= 20
71   _LIBCPP_HIDE_FROM_ABI constexpr atomic_flag() _NOEXCEPT : __a_(false) {}
72 #else
73   atomic_flag() _NOEXCEPT = default;
74 #endif
75 
76   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION
77 
78   atomic_flag(const atomic_flag&)                     = delete;
79   atomic_flag& operator=(const atomic_flag&)          = delete;
80   atomic_flag& operator=(const atomic_flag&) volatile = delete;
81 };
82 
83 template <>
84 struct __atomic_waitable_traits<atomic_flag> {
85   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE __atomic_load(const atomic_flag& __a, memory_order __order) {
86     return std::__cxx_atomic_load(&__a.__a_, __order);
87   }
88 
89   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE
90   __atomic_load(const volatile atomic_flag& __a, memory_order __order) {
91     return std::__cxx_atomic_load(&__a.__a_, __order);
92   }
93 
94   static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>*
95   __atomic_contention_address(const atomic_flag& __a) {
96     return std::addressof(__a.__a_);
97   }
98 
99   static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>*
100   __atomic_contention_address(const volatile atomic_flag& __a) {
101     return std::addressof(__a.__a_);
102   }
103 };
104 
105 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
106 
107 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); }
108 
109 inline _LIBCPP_HIDE_FROM_ABI bool
110 atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
111   return __o->test(__m);
112 }
113 
114 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT {
115   return __o->test(__m);
116 }
117 
118 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT {
119   return __o->test_and_set();
120 }
121 
122 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
123 
124 inline _LIBCPP_HIDE_FROM_ABI bool
125 atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
126   return __o->test_and_set(__m);
127 }
128 
129 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
130   return __o->test_and_set(__m);
131 }
132 
133 inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); }
134 
135 inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); }
136 
137 inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
138   __o->clear(__m);
139 }
140 
141 inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
142   __o->clear(__m);
143 }
144 
145 #if _LIBCPP_STD_VER >= 20
146 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
147 atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
148   __o->wait(__v);
149 }
150 
151 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
152 atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT {
153   __o->wait(__v);
154 }
155 
156 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
157 atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
158   __o->wait(__v, __m);
159 }
160 
161 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
162 atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
163   __o->wait(__v, __m);
164 }
165 
166 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
167 atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT {
168   __o->notify_one();
169 }
170 
171 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT {
172   __o->notify_one();
173 }
174 
175 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
176 atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT {
177   __o->notify_all();
178 }
179 
180 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT {
181   __o->notify_all();
182 }
183 #endif // _LIBCPP_STD_VER >= 20
184 
185 _LIBCPP_END_NAMESPACE_STD
186 
187 #endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H
188