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<_LIBCPP_ATOMIC_FLAG_TYPE> __a_;
27
28 _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT {
29 return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __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 _LIBCPP_ATOMIC_FLAG_TYPE(true) == __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_, _LIBCPP_ATOMIC_FLAG_TYPE(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_, _LIBCPP_ATOMIC_FLAG_TYPE(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_, _LIBCPP_ATOMIC_FLAG_TYPE(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_, _LIBCPP_ATOMIC_FLAG_TYPE(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, _LIBCPP_ATOMIC_FLAG_TYPE(__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, _LIBCPP_ATOMIC_FLAG_TYPE(__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 = _LIBCPP_ATOMIC_FLAG_TYPE;
78
79 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE __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 _LIBCPP_ATOMIC_FLAG_TYPE
84 __atomic_load(const volatile atomic_flag& __a, memory_order __order) {
85 return std::__cxx_atomic_load(a: &__a.__a_, __order);
86 }
87
88 static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>*
89 __atomic_contention_address(const atomic_flag& __a) {
90 return std::addressof(x: __a.__a_);
91 }
92
93 static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>*
94 __atomic_contention_address(const volatile atomic_flag& __a) {
95 return std::addressof(x: __a.__a_);
96 }
97};
98#endif // _LIBCPP_STD_VER >= 20
99
100inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
101
102inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); }
103
104inline _LIBCPP_HIDE_FROM_ABI bool
105atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
106 return __o->test(__m);
107}
108
109inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT {
110 return __o->test(__m);
111}
112
113inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT {
114 return __o->test_and_set();
115}
116
117inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
118
119inline _LIBCPP_HIDE_FROM_ABI bool
120atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
121 return __o->test_and_set(__m);
122}
123
124inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
125 return __o->test_and_set(__m);
126}
127
128inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); }
129
130inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); }
131
132inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
133 __o->clear(__m);
134}
135
136inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
137 __o->clear(__m);
138}
139
140#if _LIBCPP_STD_VER >= 20
141inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT {
142 __o->wait(__v);
143}
144
145inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); }
146
147inline _LIBCPP_HIDE_FROM_ABI void
148atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
149 __o->wait(__v, __m);
150}
151
152inline _LIBCPP_HIDE_FROM_ABI void
153atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT {
154 __o->wait(__v, __m);
155}
156
157inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_one(); }
158inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { __o->notify_one(); }
159inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_all(); }
160inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { __o->notify_all(); }
161#endif // _LIBCPP_STD_VER >= 20
162
163_LIBCPP_END_NAMESPACE_STD
164
165#endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H
166