30#ifndef _GLIBCXX_ATOMIC_WAIT_H
31#define _GLIBCXX_ATOMIC_WAIT_H 1
34#pragma GCC system_header
39#if __glibcxx_atomic_wait
45namespace std _GLIBCXX_VISIBILITY(default)
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
50#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
51#define _GLIBCXX_HAVE_PLATFORM_WAIT 1
52 using __platform_wait_t = int;
53 inline constexpr size_t __platform_wait_alignment = 4;
59# if ATOMIC_LONG_LOCK_FREE == 2
60 using __platform_wait_t =
unsigned long;
62 using __platform_wait_t =
unsigned int;
64 inline constexpr size_t __platform_wait_alignment
65 = __alignof__(__platform_wait_t);
69 template<
typename _Tp>
70 inline constexpr bool __platform_wait_uses_type
71#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
73 && ((
sizeof(_Tp) ==
sizeof(__detail::__platform_wait_t))
74 && (
alignof(_Tp) >= __detail::__platform_wait_alignment));
82 __thread_yield() noexcept
84#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
90 __thread_relax() noexcept
92#if defined __i386__ || defined __x86_64__
93 __builtin_ia32_pause();
100 template<
typename _Tp>
102 __atomic_eq(
const _Tp& __a,
const _Tp& __b)
105 return __builtin_memcmp(&__a, &__b,
sizeof(_Tp)) == 0;
109 struct __wait_result_type
111 __platform_wait_t _M_val;
112 unsigned char _M_has_val : 1;
113 unsigned char _M_timeout : 1;
114 unsigned char _M_unused : 6;
117 enum class __wait_flags : __UINT_LEAST32_TYPE__
121 __track_contention = 2,
127 [[__gnu__::__always_inline__]]
128 constexpr __wait_flags
129 operator|(__wait_flags __l, __wait_flags __r)
noexcept
132 return static_cast<__wait_flags
>(
static_cast<_Ut
>(__l)
133 |
static_cast<_Ut
>(__r));
136 [[__gnu__::__always_inline__]]
137 constexpr __wait_flags&
138 operator|=(__wait_flags& __l, __wait_flags __r)
noexcept
139 {
return __l = __l | __r; }
142 struct __wait_args_base
144 __wait_flags _M_flags;
145 int _M_order = __ATOMIC_ACQUIRE;
146 __platform_wait_t _M_old = 0;
147 void* _M_wait_state =
nullptr;
151 operator&(__wait_flags __flags)
const noexcept
153 using _Ut = underlying_type_t<__wait_flags>;
154 return static_cast<_Ut
>(_M_flags) &
static_cast<_Ut
>(__flags);
159 struct __wait_args : __wait_args_base
161 template<
typename _Tp>
requires (!is_same_v<_Tp, __wait_args>)
163 __wait_args(
const _Tp* __addr,
bool __bare_wait =
false) noexcept
164 : __wait_args_base{ _S_flags_for(__addr, __bare_wait) }
167 __wait_args(
const __platform_wait_t* __addr, __platform_wait_t __old,
168 int __order,
bool __bare_wait =
false) noexcept
169 : __wait_args_base{ _S_flags_for(__addr, __bare_wait), __order, __old }
172 __wait_args(
const __wait_args&)
noexcept =
default;
173 __wait_args& operator=(
const __wait_args&)
noexcept =
default;
175 template<
typename _ValFn,
176 typename _Tp = decay_t<decltype(std::declval<_ValFn&>()())>>
178 _M_setup_wait(
const void* __addr, _ValFn __vfn,
179 __wait_result_type __res = {})
181 if constexpr (__platform_wait_uses_type<_Tp>)
186 if (__res._M_has_val)
188 _M_old = __res._M_val;
189 return __builtin_bit_cast(_Tp, __res._M_val);
194 _M_old = __builtin_bit_cast(__platform_wait_t, __val);
200 if (__res._M_has_val)
201 _M_old = __res._M_val;
203 _M_load_proxy_wait_val(__addr);
211 _M_load_proxy_wait_val(
const void* __addr);
213 template<
typename _Tp>
214 static constexpr __wait_flags
215 _S_flags_for(
const _Tp*,
bool __bare_wait)
noexcept
217 using enum __wait_flags;
218 __wait_flags __res = __abi_version | __do_spin;
220 __res |= __track_contention;
221 if constexpr (!__platform_wait_uses_type<_Tp>)
222 __res |= __proxy_wait;
228 __wait_impl(
const void* __addr, __wait_args_base&);
231 __notify_impl(
const void* __addr,
bool __all,
const __wait_args_base&);
237 template<
typename _Tp,
typename _Pred,
typename _ValFn>
239 __atomic_wait_address(
const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn,
240 bool __bare_wait =
false) noexcept
242 __detail::__wait_args __args{ __addr, __bare_wait };
243 _Tp __val = __args._M_setup_wait(__addr, __vfn);
244 while (!__pred(__val))
246 auto __res = __detail::__wait_impl(__addr, __args);
247 __val = __args._M_setup_wait(__addr, __vfn, __res);
254 __atomic_wait_address_v(
const __detail::__platform_wait_t* __addr,
255 __detail::__platform_wait_t __old,
256 int __order,
bool __bare_wait =
false)
258#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
259 __glibcxx_assert(
false);
261 __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
263 __detail::__wait_impl(__addr, __args);
267 template<
typename _Tp,
typename _ValFn>
269 __atomic_wait_address_v(
const _Tp* __addr, _Tp __old,
270 _ValFn __vfn)
noexcept
272 auto __pfn = [&](
const _Tp& __val)
273 {
return !__detail::__atomic_eq(__old, __val); };
277 template<
typename _Tp>
279 __atomic_notify_address(
const _Tp* __addr,
bool __all,
280 bool __bare_wait =
false) noexcept
282 __detail::__wait_args __args{ __addr, __bare_wait };
283 __detail::__notify_impl(__addr, __all, __args);
286_GLIBCXX_END_NAMESPACE_VERSION
typename underlying_type< _Tp >::type underlying_type_t
Alias template for underlying_type.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
ISO C++ entities toplevel namespace is std.
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
constexpr bitset< _Nb > operator&(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Implementation details not part of the namespace std interface.