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)
126 using __wait_value_type = __UINT64_TYPE__;
129 struct __wait_result_type
131 __wait_value_type _M_val;
132 unsigned char _M_has_val : 1;
133 unsigned char _M_timeout : 1;
134 unsigned char _M_unused : 6;
137 enum class __wait_flags : __UINT_LEAST32_TYPE__
139 __abi_version = 0x00000000,
141 __track_contention = 2,
147 [[__gnu__::__always_inline__]]
148 constexpr __wait_flags
149 operator|(__wait_flags __l, __wait_flags __r)
noexcept
152 return static_cast<__wait_flags
>(
static_cast<_Ut
>(__l)
153 |
static_cast<_Ut
>(__r));
156 [[__gnu__::__always_inline__]]
157 constexpr __wait_flags&
158 operator|=(__wait_flags& __l, __wait_flags __r)
noexcept
159 {
return __l = __l | __r; }
162 struct __wait_args_base
164 __wait_flags _M_flags;
165 int _M_order = __ATOMIC_ACQUIRE;
166 __wait_value_type _M_old = 0;
167 void* _M_wait_state =
nullptr;
168 const void* _M_obj =
nullptr;
169 unsigned char _M_obj_size = 0;
173 operator&(__wait_flags __flags)
const noexcept
175 using _Ut = underlying_type_t<__wait_flags>;
176 return static_cast<_Ut
>(_M_flags) &
static_cast<_Ut
>(__flags);
181 struct __wait_args : __wait_args_base
183 template<
typename _Tp>
requires (!is_same_v<_Tp, __wait_args>)
185 __wait_args(
const _Tp* __addr,
bool __bare_wait =
false) noexcept
186 : __wait_args_base{ _S_flags_for(__addr, __bare_wait) }
189 if constexpr (__waitable<_Tp>)
192 _M_obj_size =
sizeof(_Tp);
195 __wait_args(
const __platform_wait_t* __addr, __platform_wait_t __old,
196 int __order,
bool __bare_wait =
false) noexcept
197 : __wait_args(__addr, __bare_wait)
203 __wait_args(
const __wait_args&)
noexcept =
default;
204 __wait_args& operator=(
const __wait_args&)
noexcept =
default;
206 template<
typename _Tp,
typename _ValFn>
208 _M_setup_wait(
const _Tp* __addr, _ValFn __vfn,
209 __wait_result_type __res = {})
211 static_assert(is_same_v<_Tp,
decay_t<
decltype(__vfn())>>);
213 if (__res._M_has_val)
215 _M_old = __res._M_val;
216 if constexpr (!__platform_wait_uses_type<_Tp>)
224 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
225 return __builtin_bit_cast(_Tp, (__UINT32_TYPE__)_M_old);
226 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
227 return __builtin_bit_cast(_Tp, (__UINT64_TYPE__)_M_old);
230 static_assert(
false);
235 if constexpr (!__platform_wait_uses_type<_Tp>)
236 if (_M_setup_proxy_wait(__addr))
247 auto __val = __vfn();
250 if constexpr (
sizeof(_Tp) ==
sizeof(__UINT64_TYPE__))
251 _M_old = __builtin_bit_cast(__UINT64_TYPE__, __val);
252 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT32_TYPE__))
253 _M_old = __builtin_bit_cast(__UINT32_TYPE__, __val);
254 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT16_TYPE__))
255 _M_old = __builtin_bit_cast(__UINT16_TYPE__, __val);
256 else if constexpr (
sizeof(_Tp) ==
sizeof(__UINT8_TYPE__))
257 _M_old = __builtin_bit_cast(__UINT8_TYPE__, __val);
259 __glibcxx_assert(
false);
268 _M_setup_proxy_wait(
const void* __addr);
270 template<
typename _Tp>
271 static constexpr __wait_flags
272 _S_flags_for(
const _Tp*,
bool __bare_wait)
noexcept
274 using enum __wait_flags;
275 __wait_flags __res = __abi_version | __do_spin;
277 __res |= __track_contention;
283 __wait_impl(
const void* __addr, __wait_args_base&);
286 __notify_impl(
const void* __addr,
bool __all,
const __wait_args_base&);
293 template<
typename _Tp,
typename _Pred,
typename _ValFn>
295 __atomic_wait_address(
const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn,
296 bool __bare_wait =
false) noexcept
298 __detail::__wait_args __args{ __addr, __bare_wait };
299 _Tp __val = __args._M_setup_wait(__addr, __vfn);
300 while (!__pred(__val))
302 auto __res = __detail::__wait_impl(__addr, __args);
303 __val = __args._M_setup_wait(__addr, __vfn, __res);
310 __atomic_wait_address_v(
const __detail::__platform_wait_t* __addr,
311 __detail::__platform_wait_t __old,
312 int __order,
bool __bare_wait =
false)
315 __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>);
317 __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
319 __detail::__wait_impl(__addr, __args);
323 template<
typename _Tp,
typename _ValFn>
325 __atomic_wait_address_v(
const _Tp* __addr, _Tp __old,
326 _ValFn __vfn)
noexcept
328 auto __pfn = [&](
const _Tp& __val)
329 {
return !__detail::__atomic_eq(__old, __val); };
333 template<
typename _Tp>
335 __atomic_notify_address(
const _Tp* __addr,
bool __all,
336 bool __bare_wait =
false) noexcept
338 __detail::__wait_args __args{ __addr, __bare_wait };
339 __detail::__notify_impl(__addr, __all, __args);
342_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.