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
53 template<
typename _Tp>
55 = is_scalar_v<_Tp> && __builtin_popcountg(
sizeof(_Tp)) == 1
56 && (
sizeof(_Tp) <=
sizeof(__UINT64_TYPE__));
59#if defined _GLIBCXX_HAVE_LINUX_FUTEX
63 using __platform_wait_t = int;
64 inline constexpr size_t __platform_wait_alignment = 4;
68 template<
typename _Tp>
69 inline constexpr bool __platform_wait_uses_type
70 = __detail::__waitable<_Tp>
71 &&
sizeof(_Tp) ==
sizeof(
int) &&
alignof(_Tp) >= 4;
79# if ATOMIC_LONG_LOCK_FREE == 2
80 using __platform_wait_t =
unsigned long;
82 using __platform_wait_t =
unsigned int;
84 inline constexpr size_t __platform_wait_alignment
85 =
sizeof(__platform_wait_t) < __alignof__(__platform_wait_t)
86 ? __alignof__(__platform_wait_t) : sizeof(__platform_wait_t);
92 inline constexpr bool __platform_wait_uses_type =
false;
98 __thread_yield() noexcept
100#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
106 __thread_relax() noexcept
108#if defined __i386__ || defined __x86_64__
109 __builtin_ia32_pause();
116 template<
typename _Tp>
118 __atomic_eq(
const _Tp& __a,
const _Tp& __b)
121 return __builtin_memcmp(&__a, &__b,
sizeof(_Tp)) == 0;
125 using __wait_value_type = __UINT64_TYPE__;
128 struct __wait_result_type
130 __wait_value_type _M_val;
131 unsigned char _M_has_val : 1;
132 unsigned char _M_timeout : 1;
133 unsigned char _M_unused : 6;
136 enum class __wait_flags : __UINT_LEAST32_TYPE__
138 __abi_version = 0x00000000,
140 __track_contention = 2,
146 [[__gnu__::__always_inline__]]
147 constexpr __wait_flags
148 operator|(__wait_flags __l, __wait_flags __r)
noexcept
151 return static_cast<__wait_flags
>(
static_cast<_Ut
>(__l)
152 |
static_cast<_Ut
>(__r));
155 [[__gnu__::__always_inline__]]
156 constexpr __wait_flags&
157 operator|=(__wait_flags& __l, __wait_flags __r)
noexcept
158 {
return __l = __l | __r; }
161 struct __wait_args_base
163 __wait_flags _M_flags;
164 int _M_order = __ATOMIC_ACQUIRE;
165 __wait_value_type _M_old = 0;
166 void* _M_wait_state =
nullptr;
167 const void* _M_obj =
nullptr;
168 unsigned char _M_obj_size = 0;
172 operator&(__wait_flags __flags)
const noexcept
174 using _Ut = underlying_type_t<__wait_flags>;
175 return static_cast<_Ut
>(_M_flags) &
static_cast<_Ut
>(__flags);
180 struct __wait_args : __wait_args_base
182 template<
typename _Tp>
requires (!is_same_v<_Tp, __wait_args>)
184 __wait_args(
const _Tp* __addr,
bool __bare_wait =
false) noexcept
185 : __wait_args_base{ _S_flags_for(__addr, __bare_wait) }
188 if constexpr (__waitable<_Tp>)
191 _M_obj_size =
sizeof(_Tp);
194 __wait_args(
const __platform_wait_t* __addr, __platform_wait_t __old,
195 int __order,
bool __bare_wait =
false) noexcept
196 : __wait_args(__addr, __bare_wait)
202 __wait_args(
const __wait_args&)
noexcept =
default;
203 __wait_args& operator=(
const __wait_args&)
noexcept =
default;
205 template<
typename _Tp,
typename _ValFn>
207 _M_setup_wait(
const _Tp* __addr, _ValFn __vfn,
208 __wait_result_type __res = {})
210 static_assert(is_same_v<_Tp,
decay_t<
decltype(__vfn())>>);
212 if (__res._M_has_val)
214 _M_old = __res._M_val;
215 if constexpr (!__platform_wait_uses_type<_Tp>)
223 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
224 return __builtin_bit_cast(_Tp, (__UINT32_TYPE__)_M_old);
225 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
226 return __builtin_bit_cast(_Tp, (__UINT64_TYPE__)_M_old);
229 static_assert(
false);
234 if constexpr (!__platform_wait_uses_type<_Tp>)
235 if (_M_setup_proxy_wait(__addr))
246 auto __val = __vfn();
249 if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
250 _M_old = __builtin_bit_cast(__UINT64_TYPE__, __val);
251 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
252 _M_old = __builtin_bit_cast(__UINT32_TYPE__, __val);
253 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT16_TYPE__))
254 _M_old = __builtin_bit_cast(__UINT16_TYPE__, __val);
255 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT8_TYPE__))
256 _M_old = __builtin_bit_cast(__UINT8_TYPE__, __val);
258 __glibcxx_assert(
false);
267 _M_setup_proxy_wait(
const void* __addr);
269 template<
typename _Tp>
270 static constexpr __wait_flags
271 _S_flags_for(
const _Tp*,
bool __bare_wait)
noexcept
273 using enum __wait_flags;
274 __wait_flags __res = __abi_version | __do_spin;
276 __res |= __track_contention;
282 __wait_impl(
const void* __addr, __wait_args_base&);
285 __notify_impl(
const void* __addr,
bool __all,
const __wait_args_base&);
292 template<
typename _Tp,
typename _Pred,
typename _ValFn>
294 __atomic_wait_address(
const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn,
295 bool __bare_wait =
false) noexcept
297 __detail::__wait_args __args{ __addr, __bare_wait };
298 _Tp __val = __args._M_setup_wait(__addr, __vfn);
299 while (!__pred(__val))
301 auto __res = __detail::__wait_impl(__addr, __args);
302 __val = __args._M_setup_wait(__addr, __vfn, __res);
309 __atomic_wait_address_v(
const __detail::__platform_wait_t* __addr,
310 __detail::__platform_wait_t __old,
311 int __order,
bool __bare_wait =
false)
314 __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
316 __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
318 __detail::__wait_impl(__addr, __args);
322 template<
typename _Tp,
typename _ValFn>
324 __atomic_wait_address_v(
const _Tp* __addr, _Tp __old,
325 _ValFn __vfn)
noexcept
327 auto __pfn = [&](
const _Tp& __val)
328 {
return !__detail::__atomic_eq(__old, __val); };
332 template<
typename _Tp>
334 __atomic_notify_address(
const _Tp* __addr,
bool __all,
335 bool __bare_wait =
false) noexcept
337 __detail::__wait_args __args{ __addr, __bare_wait };
338 __detail::__notify_impl(__addr, __all, __args);
341_GLIBCXX_END_NAMESPACE_VERSION
typename underlying_type< _Tp >::type underlying_type_t
Alias template for underlying_type.
typename decay< _Tp >::type decay_t
Alias template for decay.
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.