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 __FreeBSD__ && __SIZEOF_LONG__ == 8
75 using __platform_wait_t = __UINT64_TYPE__;
76 inline constexpr size_t __platform_wait_alignment = 8;
78 template<
typename _Tp>
79 inline constexpr bool __platform_wait_uses_type
80 = __detail::__waitable<_Tp>
81 && ((
sizeof(_Tp) == 4 &&
alignof(_Tp) >= 4)
82 || (
sizeof(_Tp) == 8 &&
alignof(_Tp) >= 8));
90# if ATOMIC_LONG_LOCK_FREE == 2
91 using __platform_wait_t =
unsigned long;
93 using __platform_wait_t =
unsigned int;
95 inline constexpr size_t __platform_wait_alignment
96 =
sizeof(__platform_wait_t) < __alignof__(__platform_wait_t)
97 ? __alignof__(__platform_wait_t) : sizeof(__platform_wait_t);
103 inline constexpr bool __platform_wait_uses_type =
false;
109 __thread_yield() noexcept
111#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
117 __thread_relax() noexcept
119#if defined __i386__ || defined __x86_64__
120 __builtin_ia32_pause();
127 template<
typename _Tp>
129 __atomic_eq(
const _Tp& __a,
const _Tp& __b)
137 using __wait_value_type = __UINT64_TYPE__;
140 struct __wait_result_type
142 __wait_value_type _M_val;
143 unsigned char _M_has_val : 1;
144 unsigned char _M_timeout : 1;
145 unsigned char _M_unused : 6;
148 enum class __wait_flags : __UINT_LEAST32_TYPE__
150 __abi_version = 0x00000000,
152 __track_contention = 2,
158 [[__gnu__::__always_inline__]]
159 constexpr __wait_flags
160 operator|(__wait_flags __l, __wait_flags __r)
noexcept
163 return static_cast<__wait_flags
>(
static_cast<_Ut
>(__l)
164 |
static_cast<_Ut
>(__r));
167 [[__gnu__::__always_inline__]]
168 constexpr __wait_flags&
169 operator|=(__wait_flags& __l, __wait_flags __r)
noexcept
170 {
return __l = __l | __r; }
173 struct __wait_args_base
175 __wait_flags _M_flags;
176 int _M_order = __ATOMIC_ACQUIRE;
177 __wait_value_type _M_old = 0;
178 void* _M_wait_state =
nullptr;
179 const void* _M_obj =
nullptr;
180 unsigned char _M_obj_size = 0;
184 operator&(__wait_flags __flags)
const noexcept
186 using _Ut = underlying_type_t<__wait_flags>;
187 return static_cast<_Ut
>(_M_flags) &
static_cast<_Ut
>(__flags);
192 struct __wait_args : __wait_args_base
194 template<
typename _Tp>
requires (!is_same_v<_Tp, __wait_args>)
196 __wait_args(
const _Tp* __addr,
bool __bare_wait =
false) noexcept
197 : __wait_args_base{ _S_flags_for(__addr, __bare_wait) }
200 if constexpr (__waitable<_Tp>)
203 _M_obj_size =
sizeof(_Tp);
206 __wait_args(
const __platform_wait_t* __addr, __platform_wait_t __old,
207 int __order,
bool __bare_wait =
false) noexcept
208 : __wait_args(__addr, __bare_wait)
214 __wait_args(
const __wait_args&)
noexcept =
default;
215 __wait_args& operator=(
const __wait_args&)
noexcept =
default;
217 template<
typename _Tp,
typename _ValFn>
219 _M_setup_wait(
const _Tp* __addr, _ValFn __vfn)
221 static_assert(is_same_v<_Tp,
decay_t<
decltype(__vfn())>>);
223 if constexpr (!__platform_wait_uses_type<_Tp>)
224 if (_M_setup_proxy_wait(__addr))
236 return _M_store(__vfn());
240 template<
typename _Tp,
typename _ValFn>
242 _M_on_wake(
const _Tp* __addr, _ValFn __vfn, __wait_result_type __res)
244 if constexpr (!__platform_wait_uses_type<_Tp>)
245 if (_M_obj != __addr)
247 if (__res._M_has_val)
249 _M_old = __res._M_val;
251 (void) _M_setup_proxy_wait(
nullptr);
256 if (__res._M_has_val)
258 _M_old = __res._M_val;
262 if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
263 return __builtin_bit_cast(_Tp, (__UINT64_TYPE__)_M_old);
264 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
265 return __builtin_bit_cast(_Tp, (__UINT32_TYPE__)_M_old);
266 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT16_TYPE__))
267 return __builtin_bit_cast(_Tp, (__UINT16_TYPE__)_M_old);
268 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT8_TYPE__))
269 return __builtin_bit_cast(_Tp, (__UINT8_TYPE__)_M_old);
271 __glibcxx_assert(
false);
274 return _M_store(__vfn());
280 template<
typename _Tp>
281 [[__gnu__::__always_inline__]]
287 if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
288 _M_old = __builtin_bit_cast(__UINT64_TYPE__, __val);
289 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
290 _M_old = __builtin_bit_cast(__UINT32_TYPE__, __val);
291 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT16_TYPE__))
292 _M_old = __builtin_bit_cast(__UINT16_TYPE__, __val);
293 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT8_TYPE__))
294 _M_old = __builtin_bit_cast(__UINT8_TYPE__, __val);
296 __glibcxx_assert(
false);
303 _M_setup_proxy_wait(
const void* __addr);
305 template<
typename _Tp>
306 static constexpr __wait_flags
307 _S_flags_for(
const _Tp*,
bool __bare_wait)
noexcept
309 using enum __wait_flags;
310 __wait_flags __res = __abi_version | __do_spin;
312 __res |= __track_contention;
318 __wait_impl(
const void* __addr, __wait_args_base&);
321 __notify_impl(
const void* __addr,
bool __all,
const __wait_args_base&);
328 template<
typename _Tp,
typename _Pred,
typename _ValFn>
330 __atomic_wait_address(
const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn,
331 bool __bare_wait =
false) noexcept
333 __detail::__wait_args __args{ __addr, __bare_wait };
334 _Tp __val = __args._M_setup_wait(__addr, __vfn);
335 while (!__pred(__val))
337 auto __res = __detail::__wait_impl(__addr, __args);
338 __val = __args._M_on_wake(__addr, __vfn, __res);
345 __atomic_wait_address_v(
const __detail::__platform_wait_t* __addr,
346 __detail::__platform_wait_t __old,
347 int __order,
bool __bare_wait =
false)
350 __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
352 __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
354 __detail::__wait_impl(__addr, __args);
358 template<
typename _Tp,
typename _ValFn>
360 __atomic_wait_address_v(
const _Tp* __addr, _Tp __old,
361 _ValFn __vfn)
noexcept
363 auto __pfn = [&](
const _Tp& __val)
364 {
return !__detail::__atomic_eq(__old, __val); };
368 template<
typename _Tp>
370 __atomic_notify_address(
const _Tp* __addr,
bool __all,
371 bool __bare_wait =
false) noexcept
373 __detail::__wait_args __args{ __addr, __bare_wait };
374 __detail::__notify_impl(__addr, __all, __args);
377_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.