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 bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT { return __cxx_atomic_load(a: &__a_, order: __m); }
29 bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT { return __cxx_atomic_load(a: &__a_, order: __m); }
30
31 bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
32 return __cxx_atomic_exchange(a: &__a_, value: true, order: __m);
33 }
34 bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT {
35 return __cxx_atomic_exchange(a: &__a_, value: true, order: __m);
36 }
37 void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { __cxx_atomic_store(a: &__a_, val: false, order: __m); }
38 void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT { __cxx_atomic_store(a: &__a_, val: false, order: __m); }
39
40#if _LIBCPP_STD_VER >= 20
41 void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile noexcept {
42 std::__atomic_wait(a: *this, val: __v, order: __m);
43 }
44 void wait(bool __v, memory_order __m = memory_order_seq_cst) const noexcept { std::__atomic_wait(a: *this, val: __v, order: __m); }
45 void notify_one() volatile noexcept { std::__atomic_notify_one(a: *this); }
46 void notify_one() noexcept { std::__atomic_notify_one(a: *this); }
47 void notify_all() volatile noexcept { std::__atomic_notify_all(a: *this); }
48 void notify_all() noexcept { std::__atomic_notify_all(a: *this); }
49#endif
50
51#if _LIBCPP_STD_VER >= 20
52 constexpr atomic_flag() noexcept : __a_(false) {}
53#else
54 atomic_flag() _NOEXCEPT = default;
55#endif
56
57 _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION
58
59 atomic_flag(const atomic_flag&) = delete;
60 atomic_flag& operator=(const atomic_flag&) = delete;
61 atomic_flag& operator=(const atomic_flag&) volatile = delete;
62};
63
64#if _LIBCPP_STD_VER >= 20
65template <>
66struct __atomic_waitable_traits<atomic_flag> {
67 using __value_type _LIBCPP_NODEBUG = bool;
68
69 static bool __atomic_load(const atomic_flag& __a, memory_order __order) {
70 return std::__cxx_atomic_load(a: &__a.__a_, __order);
71 }
72
73 static bool __atomic_load(const volatile atomic_flag& __a, memory_order __order) {
74 return std::__cxx_atomic_load(a: &__a.__a_, __order);
75 }
76
77 static const __cxx_atomic_impl<bool>* __atomic_contention_address(const atomic_flag& __a) {
78 return std::addressof(x: __a.__a_);
79 }
80
81 static const volatile __cxx_atomic_impl<bool>* __atomic_contention_address(const volatile atomic_flag& __a) {
82 return std::addressof(x: __a.__a_);
83 }
84};
85#endif // _LIBCPP_STD_VER >= 20
86
87inline bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
88
89inline bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); }
90
91inline bool atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
92 return __o->test(__m);
93}
94
95inline bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test(__m); }
96
97inline bool atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
98
99inline bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); }
100
101inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT {
102 return __o->test_and_set(__m);
103}
104
105inline bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT {
106 return __o->test_and_set(__m);
107}
108
109inline void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); }
110
111inline void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); }
112
113inline void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { __o->clear(__m); }
114
115inline void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { __o->clear(__m); }
116
117#if _LIBCPP_STD_VER >= 20
118inline void atomic_flag_wait(const volatile atomic_flag* __o, bool __v) noexcept { __o->wait(__v); }
119
120inline void atomic_flag_wait(const atomic_flag* __o, bool __v) noexcept { __o->wait(__v); }
121
122inline void atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) noexcept {
123 __o->wait(__v, __m);
124}
125
126inline void atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) noexcept {
127 __o->wait(__v, __m);
128}
129
130inline void atomic_flag_notify_one(volatile atomic_flag* __o) noexcept { __o->notify_one(); }
131inline void atomic_flag_notify_one(atomic_flag* __o) noexcept { __o->notify_one(); }
132inline void atomic_flag_notify_all(volatile atomic_flag* __o) noexcept { __o->notify_all(); }
133inline void atomic_flag_notify_all(atomic_flag* __o) noexcept { __o->notify_all(); }
134#endif // _LIBCPP_STD_VER >= 20
135
136_LIBCPP_END_NAMESPACE_STD
137
138#endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H
139