30#ifndef _GLIBCXX_ATOMIC_FUTEX_H
31#define _GLIBCXX_ATOMIC_FUTEX_H 1
33#pragma GCC system_header
36#if ! (defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1)
42#ifndef _GLIBCXX_ALWAYS_INLINE
43#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
46namespace std _GLIBCXX_VISIBILITY(default)
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
50#ifdef _GLIBCXX_HAS_GTHREADS
51#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1
52 struct __atomic_futex_unsigned_base
57 _M_futex_wait_until(
unsigned *__addr,
unsigned __val,
bool __has_timeout,
58 chrono::seconds __s, chrono::nanoseconds __ns);
63 _M_futex_wait_until_steady(
unsigned *__addr,
unsigned __val,
64 bool __has_timeout, chrono::seconds __s, chrono::nanoseconds __ns);
67 static void _M_futex_notify_all(
unsigned* __addr);
70 template <
unsigned _Waiter_bit = 0x80000000>
71 class __atomic_futex_unsigned : __atomic_futex_unsigned_base
73 typedef chrono::steady_clock __clock_t;
76 atomic<unsigned> _M_data;
80 __atomic_futex_unsigned(
unsigned __data) : _M_data(__data)
83 _GLIBCXX_ALWAYS_INLINE
unsigned
86 return _M_data.load(__mo) & ~_Waiter_bit;
97 _M_load_and_test_until(
unsigned __assumed,
unsigned __operand,
108 _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);
109 bool __ret = _M_futex_wait_until((
unsigned*)(
void*)&_M_data,
110 __assumed | _Waiter_bit,
111 __has_timeout, __s, __ns);
113 __assumed = _M_load(__mo);
114 if (!__ret || ((__operand == __assumed) == __equal))
127 _M_load_and_test_until_steady(
unsigned __assumed,
unsigned __operand,
138 _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);
139 bool __ret = _M_futex_wait_until_steady((
unsigned*)(
void*)&_M_data,
140 __assumed | _Waiter_bit,
141 __has_timeout, __s, __ns);
143 __assumed = _M_load(__mo);
144 if (!__ret || ((__operand == __assumed) == __equal))
155 _M_load_and_test(
unsigned __assumed,
unsigned __operand,
158 return _M_load_and_test_until(__assumed, __operand, __equal, __mo,
167 template<
typename _Dur>
169 _M_load_and_test_until_impl(
unsigned __assumed,
unsigned __operand,
171 const chrono::time_point<std::chrono::system_clock, _Dur>& __atime)
173 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
174 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
176 return _M_load_and_test_until(__assumed, __operand, __equal, __mo,
177 true, __s.time_since_epoch(), __ns);
180 template<
typename _Dur>
182 _M_load_and_test_until_impl(
unsigned __assumed,
unsigned __operand,
184 const chrono::time_point<std::chrono::steady_clock, _Dur>& __atime)
186 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
187 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
189 return _M_load_and_test_until_steady(__assumed, __operand, __equal, __mo,
190 true, __s.time_since_epoch(), __ns);
195 _GLIBCXX_ALWAYS_INLINE
unsigned
196 _M_load_when_not_equal(
unsigned __val,
memory_order __mo)
198 unsigned __i = _M_load(__mo);
199 if ((__i & ~_Waiter_bit) != __val)
200 return (__i & ~_Waiter_bit);
202 return _M_load_and_test(__i, __val,
false, __mo);
205 _GLIBCXX_ALWAYS_INLINE
void
208 unsigned __i = _M_load(__mo);
209 if ((__i & ~_Waiter_bit) == __val)
212 _M_load_and_test(__i, __val,
true, __mo);
216 template<
typename _Rep,
typename _Period>
217 _GLIBCXX_ALWAYS_INLINE
bool
218 _M_load_when_equal_for(
unsigned __val,
memory_order __mo,
219 const chrono::duration<_Rep, _Period>& __rtime)
221 using __dur =
typename __clock_t::duration;
222 return _M_load_when_equal_until(__val, __mo,
223 __clock_t::now() + chrono::__detail::ceil<__dur>(__rtime));
227 template<
typename _Clock,
typename _Duration>
228 _GLIBCXX_ALWAYS_INLINE
bool
229 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
230 const chrono::time_point<_Clock, _Duration>& __atime)
232 typename _Clock::time_point __c_entry = _Clock::now();
234 const __clock_t::time_point __s_entry = __clock_t::now();
235 const auto __delta = __atime - __c_entry;
236 const auto __s_atime = __s_entry +
237 chrono::__detail::ceil<__clock_t::duration>(__delta);
238 if (_M_load_when_equal_until(__val, __mo, __s_atime))
240 __c_entry = _Clock::now();
241 }
while (__c_entry < __atime);
246 template<
typename _Duration>
247 _GLIBCXX_ALWAYS_INLINE
bool
248 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
249 const chrono::time_point<std::chrono::system_clock, _Duration>& __atime)
251 unsigned __i = _M_load(__mo);
252 if ((__i & ~_Waiter_bit) == __val)
255 __i = _M_load_and_test_until_impl(__i, __val,
true, __mo, __atime);
256 return (__i & ~_Waiter_bit) == __val;
260 template<
typename _Duration>
261 _GLIBCXX_ALWAYS_INLINE
bool
262 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
263 const chrono::time_point<std::chrono::steady_clock, _Duration>& __atime)
265 unsigned __i = _M_load(__mo);
266 if ((__i & ~_Waiter_bit) == __val)
269 __i = _M_load_and_test_until_impl(__i, __val,
true, __mo, __atime);
270 return (__i & ~_Waiter_bit) == __val;
273 _GLIBCXX_ALWAYS_INLINE
void
276 unsigned* __futex = (
unsigned *)(
void *)&_M_data;
277 if (_M_data.exchange(__val, __mo) & _Waiter_bit)
278 _M_futex_notify_all(__futex);
287 template <
unsigned _Waiter_bit = 0x80000000>
288 class __atomic_futex_unsigned
290 typedef chrono::system_clock __clock_t;
294 condition_variable _M_condvar;
298 __atomic_futex_unsigned(
unsigned __data) : _M_data(__data)
301 _GLIBCXX_ALWAYS_INLINE
unsigned
304 unique_lock<mutex> __lock(_M_mutex);
308 _GLIBCXX_ALWAYS_INLINE
unsigned
309 _M_load_when_not_equal(
unsigned __val,
memory_order __mo)
311 unique_lock<mutex> __lock(_M_mutex);
312 while (_M_data == __val)
313 _M_condvar.wait(__lock);
317 _GLIBCXX_ALWAYS_INLINE
void
320 unique_lock<mutex> __lock(_M_mutex);
321 while (_M_data != __val)
322 _M_condvar.wait(__lock);
325 template<
typename _Rep,
typename _Period>
326 _GLIBCXX_ALWAYS_INLINE
bool
327 _M_load_when_equal_for(
unsigned __val,
memory_order __mo,
328 const chrono::duration<_Rep, _Period>& __rtime)
330 unique_lock<mutex> __lock(_M_mutex);
331 return _M_condvar.wait_for(__lock, __rtime,
332 [&] {
return _M_data == __val;});
335 template<
typename _Clock,
typename _Duration>
336 _GLIBCXX_ALWAYS_INLINE
bool
337 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
338 const chrono::time_point<_Clock, _Duration>& __atime)
340 unique_lock<mutex> __lock(_M_mutex);
341 return _M_condvar.wait_until(__lock, __atime,
342 [&] {
return _M_data == __val;});
345 _GLIBCXX_ALWAYS_INLINE
void
348 unique_lock<mutex> __lock(_M_mutex);
350 _M_condvar.notify_all();
357_GLIBCXX_END_NAMESPACE_VERSION
duration< int64_t > seconds
seconds
duration< int64_t, nano > nanoseconds
nanoseconds
memory_order
Enumeration for memory_order.
ISO C++ entities toplevel namespace is std.