30#ifndef _GLIBCXX_ATOMIC_FUTEX_H
31#define _GLIBCXX_ATOMIC_FUTEX_H 1
34#pragma GCC system_header
38#if ! (defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1)
44#ifndef _GLIBCXX_ALWAYS_INLINE
45#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
48namespace std _GLIBCXX_VISIBILITY(default)
50_GLIBCXX_BEGIN_NAMESPACE_VERSION
52#ifdef _GLIBCXX_HAS_GTHREADS
53#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1
54 struct __atomic_futex_unsigned_base
59 _M_futex_wait_until(
unsigned *__addr,
unsigned __val,
bool __has_timeout,
65 _M_futex_wait_until_steady(
unsigned *__addr,
unsigned __val,
69 static void _M_futex_notify_all(
unsigned* __addr);
72 template <
unsigned _Waiter_bit = 0x80000000>
73 class __atomic_futex_unsigned : __atomic_futex_unsigned_base
75 typedef chrono::steady_clock __clock_t;
78 atomic<unsigned> _M_data;
82 __atomic_futex_unsigned(
unsigned __data) : _M_data(__data)
85 _GLIBCXX_ALWAYS_INLINE
unsigned
88 return _M_data.load(__mo) & ~_Waiter_bit;
99 _M_load_and_test_until(
unsigned __assumed,
unsigned __operand,
110 _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);
111 bool __ret = _M_futex_wait_until((
unsigned*)(
void*)&_M_data,
112 __assumed | _Waiter_bit,
113 __has_timeout, __s, __ns);
115 __assumed = _M_load(__mo);
116 if (!__ret || ((__operand == __assumed) == __equal))
129 _M_load_and_test_until_steady(
unsigned __assumed,
unsigned __operand,
140 _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);
141 bool __ret = _M_futex_wait_until_steady((
unsigned*)(
void*)&_M_data,
142 __assumed | _Waiter_bit,
143 __has_timeout, __s, __ns);
145 __assumed = _M_load(__mo);
146 if (!__ret || ((__operand == __assumed) == __equal))
157 _M_load_and_test(
unsigned __assumed,
unsigned __operand,
160 return _M_load_and_test_until(__assumed, __operand, __equal, __mo,
169 template<
typename _Dur>
171 _M_load_and_test_until_impl(
unsigned __assumed,
unsigned __operand,
173 const chrono::time_point<std::chrono::system_clock, _Dur>& __atime)
178 return _M_load_and_test_until(__assumed, __operand, __equal, __mo,
179 true, __s.time_since_epoch(), __ns);
182 template<
typename _Dur>
184 _M_load_and_test_until_impl(
unsigned __assumed,
unsigned __operand,
186 const chrono::time_point<std::chrono::steady_clock, _Dur>& __atime)
191 return _M_load_and_test_until_steady(__assumed, __operand, __equal, __mo,
192 true, __s.time_since_epoch(), __ns);
197 _GLIBCXX_ALWAYS_INLINE
unsigned
198 _M_load_when_not_equal(
unsigned __val,
memory_order __mo)
200 unsigned __i = _M_load(__mo);
201 if ((__i & ~_Waiter_bit) != __val)
202 return (__i & ~_Waiter_bit);
204 return _M_load_and_test(__i, __val,
false, __mo);
207 _GLIBCXX_ALWAYS_INLINE
void
210 unsigned __i = _M_load(__mo);
211 if ((__i & ~_Waiter_bit) == __val)
214 _M_load_and_test(__i, __val,
true, __mo);
218 template<
typename _Rep,
typename _Period>
219 _GLIBCXX_ALWAYS_INLINE
bool
220 _M_load_when_equal_for(
unsigned __val,
memory_order __mo,
221 const chrono::duration<_Rep, _Period>& __rtime)
223 using __dur =
typename __clock_t::duration;
224 return _M_load_when_equal_until(__val, __mo,
225 __clock_t::now() + chrono::__detail::ceil<__dur>(__rtime));
229 template<
typename _Clock,
typename _Duration>
230 _GLIBCXX_ALWAYS_INLINE
bool
231 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
232 const chrono::time_point<_Clock, _Duration>& __atime)
234 typename _Clock::time_point __c_entry = _Clock::now();
236 const __clock_t::time_point __s_entry = __clock_t::now();
237 const auto __delta = __atime - __c_entry;
238 const auto __s_atime = __s_entry +
239 chrono::__detail::ceil<__clock_t::duration>(__delta);
240 if (_M_load_when_equal_until(__val, __mo, __s_atime))
242 __c_entry = _Clock::now();
243 }
while (__c_entry < __atime);
248 template<
typename _Duration>
249 _GLIBCXX_ALWAYS_INLINE
bool
250 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
251 const chrono::time_point<std::chrono::system_clock, _Duration>& __atime)
253 unsigned __i = _M_load(__mo);
254 if ((__i & ~_Waiter_bit) == __val)
257 __i = _M_load_and_test_until_impl(__i, __val,
true, __mo, __atime);
258 return (__i & ~_Waiter_bit) == __val;
262 template<
typename _Duration>
263 _GLIBCXX_ALWAYS_INLINE
bool
264 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
265 const chrono::time_point<std::chrono::steady_clock, _Duration>& __atime)
267 unsigned __i = _M_load(__mo);
268 if ((__i & ~_Waiter_bit) == __val)
271 __i = _M_load_and_test_until_impl(__i, __val,
true, __mo, __atime);
272 return (__i & ~_Waiter_bit) == __val;
275 _GLIBCXX_ALWAYS_INLINE
void
278 unsigned* __futex = (
unsigned *)(
void *)&_M_data;
279 if (_M_data.exchange(__val, __mo) & _Waiter_bit)
280 _M_futex_notify_all(__futex);
289 template <
unsigned _Waiter_bit = 0x80000000>
290 class __atomic_futex_unsigned
292 typedef chrono::system_clock __clock_t;
296 condition_variable _M_condvar;
300 __atomic_futex_unsigned(
unsigned __data) : _M_data(__data)
303 _GLIBCXX_ALWAYS_INLINE
unsigned
306 unique_lock<mutex> __lock(_M_mutex);
310 _GLIBCXX_ALWAYS_INLINE
unsigned
311 _M_load_when_not_equal(
unsigned __val,
memory_order __mo)
313 unique_lock<mutex> __lock(_M_mutex);
314 while (_M_data == __val)
315 _M_condvar.wait(__lock);
319 _GLIBCXX_ALWAYS_INLINE
void
322 unique_lock<mutex> __lock(_M_mutex);
323 while (_M_data != __val)
324 _M_condvar.wait(__lock);
327 template<
typename _Rep,
typename _Period>
328 _GLIBCXX_ALWAYS_INLINE
bool
329 _M_load_when_equal_for(
unsigned __val,
memory_order __mo,
330 const chrono::duration<_Rep, _Period>& __rtime)
332 unique_lock<mutex> __lock(_M_mutex);
333 return _M_condvar.wait_for(__lock, __rtime,
334 [&] {
return _M_data == __val;});
337 template<
typename _Clock,
typename _Duration>
338 _GLIBCXX_ALWAYS_INLINE
bool
339 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
340 const chrono::time_point<_Clock, _Duration>& __atime)
342 unique_lock<mutex> __lock(_M_mutex);
343 return _M_condvar.wait_until(__lock, __atime,
344 [&] {
return _M_data == __val;});
347 _GLIBCXX_ALWAYS_INLINE
void
350 unique_lock<mutex> __lock(_M_mutex);
352 _M_condvar.notify_all();
359_GLIBCXX_END_NAMESPACE_VERSION
duration< int64_t, nano > nanoseconds
nanoseconds
constexpr __enable_if_t< __is_duration< _ToDur >::value, time_point< _Clock, _ToDur > > time_point_cast(const time_point< _Clock, _Dur > &__t)
duration< int64_t > seconds
seconds
constexpr __enable_if_is_duration< _ToDur > duration_cast(const duration< _Rep, _Period > &__d)
memory_order
Enumeration for memory_order.
ISO C++ entities toplevel namespace is std.