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;
72#elif defined __APPLE__ \
73 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
76 using __platform_wait_t = __INT32_TYPE__;
77 inline constexpr size_t __platform_wait_alignment = 4;
84 template<
typename _Tp>
85 inline constexpr bool __platform_wait_uses_type
86 = __detail::__waitable<_Tp>
87# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500
88 &&
sizeof(_Tp) == 4 &&
alignof(_Tp) >= 4;
90 && ((
sizeof(_Tp) == 4 &&
alignof(_Tp) >= 4)
91 || (
sizeof(_Tp) == 8 &&
alignof(_Tp) >= 8));
93#elif defined __FreeBSD__ && __SIZEOF_LONG__ == 8
96 using __platform_wait_t = __UINT64_TYPE__;
97 inline constexpr size_t __platform_wait_alignment = 8;
99 template<
typename _Tp>
100 inline constexpr bool __platform_wait_uses_type
101 = __detail::__waitable<_Tp>
102 && ((
sizeof(_Tp) == 4 &&
alignof(_Tp) >= 4)
103 || (
sizeof(_Tp) == 8 &&
alignof(_Tp) >= 8));
111# if defined __OpenBSD__ || defined __DragonFly__
114 using __platform_wait_t =
unsigned int;
115# elif ATOMIC_LONG_LOCK_FREE == 2
116 using __platform_wait_t =
unsigned long;
118 using __platform_wait_t =
unsigned int;
120 inline constexpr size_t __platform_wait_alignment
121 =
sizeof(__platform_wait_t) < __alignof__(__platform_wait_t)
122 ? __alignof__(__platform_wait_t) : sizeof(__platform_wait_t);
128 inline constexpr bool __platform_wait_uses_type =
false;
134 __thread_yield() noexcept
136#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
142 __thread_relax() noexcept
144#if defined __i386__ || defined __x86_64__
145 __builtin_ia32_pause();
152 template<
typename _Tp>
154 __atomic_eq(
const _Tp& __a,
const _Tp& __b)
162 using __wait_value_type = __UINT64_TYPE__;
165 struct __wait_result_type
167 __wait_value_type _M_val;
168 unsigned char _M_has_val : 1;
169 unsigned char _M_timeout : 1;
170 unsigned char _M_unused : 6;
173 enum class __wait_flags : __UINT_LEAST32_TYPE__
175 __abi_version = 0x00000000,
177 __track_contention = 2,
183 [[__gnu__::__always_inline__]]
184 constexpr __wait_flags
185 operator|(__wait_flags __l, __wait_flags __r)
noexcept
188 return static_cast<__wait_flags
>(
static_cast<_Ut
>(__l)
189 |
static_cast<_Ut
>(__r));
192 [[__gnu__::__always_inline__]]
193 constexpr __wait_flags&
194 operator|=(__wait_flags& __l, __wait_flags __r)
noexcept
195 {
return __l = __l | __r; }
198 struct __wait_args_base
200 __wait_flags _M_flags;
201 int _M_order = __ATOMIC_ACQUIRE;
202 __wait_value_type _M_old = 0;
203 void* _M_wait_state =
nullptr;
204 const void* _M_obj =
nullptr;
205 unsigned char _M_obj_size = 0;
209 operator&(__wait_flags __flags)
const noexcept
211 using _Ut = underlying_type_t<__wait_flags>;
212 return static_cast<_Ut
>(_M_flags) &
static_cast<_Ut
>(__flags);
217 struct __wait_args : __wait_args_base
219 template<
typename _Tp>
requires (!is_same_v<_Tp, __wait_args>)
221 __wait_args(
const _Tp* __addr,
bool __bare_wait =
false) noexcept
222 : __wait_args_base{ _S_flags_for(__addr, __bare_wait) }
225 if constexpr (__waitable<_Tp>)
228 _M_obj_size =
sizeof(_Tp);
231 __wait_args(
const __platform_wait_t* __addr, __platform_wait_t __old,
232 int __order,
bool __bare_wait =
false) noexcept
233 : __wait_args(__addr, __bare_wait)
239 __wait_args(
const __wait_args&)
noexcept =
default;
240 __wait_args& operator=(
const __wait_args&)
noexcept =
default;
242 template<
typename _Tp,
typename _ValFn>
244 _M_setup_wait(
const _Tp* __addr, _ValFn __vfn)
246 static_assert(is_same_v<_Tp,
decay_t<
decltype(__vfn())>>);
248 if constexpr (!__platform_wait_uses_type<_Tp>)
249 if (_M_setup_proxy_wait(__addr))
261 return _M_store(__vfn());
265 template<
typename _Tp,
typename _ValFn>
267 _M_on_wake(
const _Tp* __addr, _ValFn __vfn, __wait_result_type __res)
269 if constexpr (!__platform_wait_uses_type<_Tp>)
270 if (_M_obj != __addr)
272 if (__res._M_has_val)
274 _M_old = __res._M_val;
276 (void) _M_setup_proxy_wait(
nullptr);
281 if (__res._M_has_val)
283 _M_old = __res._M_val;
287 if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
288 return __builtin_bit_cast(_Tp, (__UINT64_TYPE__)_M_old);
289 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
290 return __builtin_bit_cast(_Tp, (__UINT32_TYPE__)_M_old);
291 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT16_TYPE__))
292 return __builtin_bit_cast(_Tp, (__UINT16_TYPE__)_M_old);
293 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT8_TYPE__))
294 return __builtin_bit_cast(_Tp, (__UINT8_TYPE__)_M_old);
296 __glibcxx_assert(
false);
299 return _M_store(__vfn());
305 template<
typename _Tp>
306 [[__gnu__::__always_inline__]]
312 if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
313 _M_old = __builtin_bit_cast(__UINT64_TYPE__, __val);
314 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
315 _M_old = __builtin_bit_cast(__UINT32_TYPE__, __val);
316 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT16_TYPE__))
317 _M_old = __builtin_bit_cast(__UINT16_TYPE__, __val);
318 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT8_TYPE__))
319 _M_old = __builtin_bit_cast(__UINT8_TYPE__, __val);
321 __glibcxx_assert(
false);
328 _M_setup_proxy_wait(
const void* __addr);
330 template<
typename _Tp>
331 static constexpr __wait_flags
332 _S_flags_for(
const _Tp*,
bool __bare_wait)
noexcept
334 using enum __wait_flags;
335 __wait_flags __res = __abi_version | __do_spin;
337 __res |= __track_contention;
343 __wait_impl(
const void* __addr, __wait_args_base&);
346 __notify_impl(
const void* __addr,
bool __all,
const __wait_args_base&);
353 template<
typename _Tp,
typename _Pred,
typename _ValFn>
355 __atomic_wait_address(
const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn,
356 bool __bare_wait =
false) noexcept
358 __detail::__wait_args __args{ __addr, __bare_wait };
359 _Tp __val = __args._M_setup_wait(__addr, __vfn);
360 while (!__pred(__val))
362 auto __res = __detail::__wait_impl(__addr, __args);
363 __val = __args._M_on_wake(__addr, __vfn, __res);
370 __atomic_wait_address_v(
const __detail::__platform_wait_t* __addr,
371 __detail::__platform_wait_t __old,
372 int __order,
bool __bare_wait =
false)
375 __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
377 __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
379 __detail::__wait_impl(__addr, __args);
383 template<
typename _Tp,
typename _ValFn>
385 __atomic_wait_address_v(
const _Tp* __addr, _Tp __old,
386 _ValFn __vfn)
noexcept
388 auto __pfn = [&](
const _Tp& __val)
389 {
return !__detail::__atomic_eq(__old, __val); };
393 template<
typename _Tp>
395 __atomic_notify_address(
const _Tp* __addr,
bool __all,
396 bool __bare_wait =
false) noexcept
398 __detail::__wait_args __args{ __addr, __bare_wait };
399 __detail::__notify_impl(__addr, __all, __args);
402_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 * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
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.