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/cxx_atomic_impl.h>
15#include <__atomic/memory_order.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
28struct 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 _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
52 wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
53 std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
54 }
55 _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
56 wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
57 std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
58 }
59 _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT {
60 std::__atomic_notify_one(*this);
61 }
62 _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT {
63 std::__atomic_notify_one(*this);
64 }
65 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
66 std::__atomic_notify_all(*this);
67 }
68 _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT {
69 std::__atomic_notify_all(*this);
70 }
71
72#if _LIBCPP_STD_VER >= 20
73 _LIBCPP_HIDE_FROM_ABI constexpr atomic_flag() _NOEXCEPT : __a_(false) {}
74#else
75 atomic_flag() _NOEXCEPT = default;
76#endif
77
78 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION
79
80 atomic_flag(const atomic_flag&) = delete;
81 atomic_flag& operator=(const atomic_flag&) = delete;
82 atomic_flag& operator=(const atomic_flag&) volatile = delete;
83};
84
85template <>
86struct __atomic_waitable_traits<atomic_flag> {
87 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE __atomic_load(const atomic_flag& __a, memory_order __order) {
88 return std::__cxx_atomic_load(&__a.__a_, __order);
89 }
90
91 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE
92 __atomic_load(const volatile atomic_flag& __a, memory_order __order) {
93 return std::__cxx_atomic_load(&__a.__a_, __order);
94 }
95
96 static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>*
97 __atomic_contention_address(const atomic_flag& __a) {
98 return std::addressof(__a.__a_);
99 }
100
101 static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>*
102 __atomic_contention_address(const volatile atomic_flag& __a) {
103 return std::addressof(__a.__a_);
104 }
105};
106
107inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
108
109inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); }
110
111inline _LIBCPP_HIDE_FROM_ABI bool
112atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
113 return __o->test(__m);
114}
115
116inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT {
117 return __o->test(__m);
118}
119
120inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT {
121 return __o->test_and_set();
122}
123
124inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
125
126inline _LIBCPP_HIDE_FROM_ABI bool
127atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
128 return __o->test_and_set(__m);
129}
130
131inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
132 return __o->test_and_set(__m);
133}
134
135inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); }
136
137inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); }
138
139inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
140 __o->clear(__m);
141}
142
143inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
144 __o->clear(__m);
145}
146
147inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
148atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
149 __o->wait(__v);
150}
151
152inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
153atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT {
154 __o->wait(__v);
155}
156
157inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
158atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
159 __o->wait(__v, __m);
160}
161
162inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
163atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
164 __o->wait(__v, __m);
165}
166
167inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
168atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT {
169 __o->notify_one();
170}
171
172inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
173atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT {
174 __o->notify_one();
175}
176
177inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
178atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT {
179 __o->notify_all();
180}
181
182inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
183atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT {
184 __o->notify_all();
185}
186
187_LIBCPP_END_NAMESPACE_STD
188
189#endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H
190