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
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: &__a_, order: __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: &__a_, order: __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: &__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), order: __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: &__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), order: __m);
43 }
44 _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
45 __cxx_atomic_store(a: &__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), order: __m);
46 }
47 _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT {
48 __cxx_atomic_store(a: &__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), order: __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(a: *this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), order: __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(a: *this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), order: __m);
59 }
60 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT {
61 std::__atomic_notify_one(a: *this);
62 }
63 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(a: *this); }
64 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
65 std::__atomic_notify_all(a: *this);
66 }
67 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(a: *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
83template <>
84struct __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.__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.__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(x: __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(x: __a.__a_);
102 }
103};
104
105inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
106
107inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); }
108
109inline _LIBCPP_HIDE_FROM_ABI bool
110atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
111 return __o->test(__m);
112}
113
114inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT {
115 return __o->test(__m);
116}
117
118inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT {
119 return __o->test_and_set();
120}
121
122inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
123
124inline _LIBCPP_HIDE_FROM_ABI bool
125atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
126 return __o->test_and_set(__m);
127}
128
129inline _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
133inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); }
134
135inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); }
136
137inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
138 __o->clear(__m);
139}
140
141inline _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
146inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
147atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
148 __o->wait(__v);
149}
150
151inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
152atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT {
153 __o->wait(__v);
154}
155
156inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
157atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
158 __o->wait(__v, __m);
159}
160
161inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
162atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
163 __o->wait(__v, __m);
164}
165
166inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
167atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT {
168 __o->notify_one();
169}
170
171inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT {
172 __o->notify_one();
173}
174
175inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void
176atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT {
177 __o->notify_all();
178}
179
180inline _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