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/atomic_waitable_traits.h>
14#include <__atomic/memory_order.h>
15#include <__atomic/support.h>
16#include <__config>
17#include <__memory/addressof.h>
18
19#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20# pragma GCC system_header
21#endif
22
23_LIBCPP_BEGIN_NAMESPACE_STD
24
25struct atomic_flag {
26 __cxx_atomic_impl<bool> __a_;
27
28 _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
29 return __cxx_atomic_load(a: &__a_, order: __m);
30 }
31 _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
32 return __cxx_atomic_load(a: &__a_, order: __m);
33 }
34
35 _LIBCPP_HIDE_FROM_ABI bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
36 return __cxx_atomic_exchange(a: &__a_, value: true, order: __m);
37 }
38 _LIBCPP_HIDE_FROM_ABI bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT {
39 return __cxx_atomic_exchange(a: &__a_, value: true, order: __m);
40 }
41 _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
42 __cxx_atomic_store(a: &__a_, val: false, order: __m);
43 }
44 _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT {
45 __cxx_atomic_store(a: &__a_, val: false, order: __m);
46 }
47
48#if _LIBCPP_STD_VER >= 20
49 _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
50 std::__atomic_wait(a: *this, val: __v, order: __m);
51 }
52 _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT {
53 std::__atomic_wait(a: *this, val: __v, order: __m);
54 }
55 _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { std::__atomic_notify_one(a: *this); }
56 _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(a: *this); }
57 _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { std::__atomic_notify_all(a: *this); }
58 _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(a: *this); }
59#endif
60
61#if _LIBCPP_STD_VER >= 20
62 _LIBCPP_HIDE_FROM_ABI constexpr atomic_flag() _NOEXCEPT : __a_(false) {}
63#else
64 atomic_flag() _NOEXCEPT = default;
65#endif
66
67 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION
68
69 atomic_flag(const atomic_flag&) = delete;
70 atomic_flag& operator=(const atomic_flag&) = delete;
71 atomic_flag& operator=(const atomic_flag&) volatile = delete;
72};
73
74#if _LIBCPP_STD_VER >= 20
75template <>
76struct __atomic_waitable_traits<atomic_flag> {
77 using __value_type _LIBCPP_NODEBUG = bool;
78
79 static _LIBCPP_HIDE_FROM_ABI bool __atomic_load(const atomic_flag& __a, memory_order __order) {
80 return std::__cxx_atomic_load(a: &__a.__a_, __order);
81 }
82
83 static _LIBCPP_HIDE_FROM_ABI bool __atomic_load(const volatile atomic_flag& __a, memory_order __order) {
84 return std::__cxx_atomic_load(a: &__a.__a_, __order);
85 }
86
87 static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<bool>* __atomic_contention_address(const atomic_flag& __a) {
88 return std::addressof(x: __a.__a_);
89 }
90
91 static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<bool>*
92 __atomic_contention_address(const volatile atomic_flag& __a) {
93 return std::addressof(x: __a.__a_);
94 }
95};
96#endif // _LIBCPP_STD_VER >= 20
97
98inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
99
100inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); }
101
102inline _LIBCPP_HIDE_FROM_ABI bool
103atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
104 return __o->test(__m);
105}
106
107inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT {
108 return __o->test(__m);
109}
110
111inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT {
112 return __o->test_and_set();
113}
114
115inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
116
117inline _LIBCPP_HIDE_FROM_ABI bool
118atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
119 return __o->test_and_set(__m);
120}
121
122inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
123 return __o->test_and_set(__m);
124}
125
126inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); }
127
128inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); }
129
130inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
131 __o->clear(__m);
132}
133
134inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
135 __o->clear(__m);
136}
137
138#if _LIBCPP_STD_VER >= 20
139inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
140 __o->wait(__v);
141}
142
143inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); }
144
145inline _LIBCPP_HIDE_FROM_ABI void
146atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
147 __o->wait(__v, __m);
148}
149
150inline _LIBCPP_HIDE_FROM_ABI void
151atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
152 __o->wait(__v, __m);
153}
154
155inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_one(); }
156inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { __o->notify_one(); }
157inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_all(); }
158inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { __o->notify_all(); }
159#endif // _LIBCPP_STD_VER >= 20
160
161_LIBCPP_END_NAMESPACE_STD
162
163#endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H
164