master
  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_, __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#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(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __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(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);
 59  }
 60  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT {
 61    std::__atomic_notify_one(*this);
 62  }
 63  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); }
 64  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT {
 65    std::__atomic_notify_all(*this);
 66  }
 67  _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*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_, __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_, __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(__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(__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