30#ifndef _GLIBCXX_ATOMIC_FUTEX_H
31#define _GLIBCXX_ATOMIC_FUTEX_H 1
33#pragma GCC system_header
38#if ! (defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1)
43#ifndef _GLIBCXX_ALWAYS_INLINE
44#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
47namespace std _GLIBCXX_VISIBILITY(default)
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
51#ifdef _GLIBCXX_HAS_GTHREADS
52#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1
53 struct __atomic_futex_unsigned_base
58 _M_futex_wait_until(
unsigned *__addr,
unsigned __val,
bool __has_timeout,
59 chrono::seconds __s, chrono::nanoseconds __ns);
64 _M_futex_wait_until_steady(
unsigned *__addr,
unsigned __val,
65 bool __has_timeout, chrono::seconds __s, chrono::nanoseconds __ns);
68 static void _M_futex_notify_all(
unsigned* __addr);
71 template <
unsigned _Waiter_bit = 0x80000000>
72 class __atomic_futex_unsigned : __atomic_futex_unsigned_base
74 typedef chrono::steady_clock __clock_t;
77 atomic<unsigned> _M_data;
81 __atomic_futex_unsigned(
unsigned __data) : _M_data(__data)
84 _GLIBCXX_ALWAYS_INLINE
unsigned
87 return _M_data.load(__mo) & ~_Waiter_bit;
98 _M_load_and_test_until(
unsigned __assumed,
unsigned __operand,
109 _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);
110 bool __ret = _M_futex_wait_until((
unsigned*)(
void*)&_M_data,
111 __assumed | _Waiter_bit,
112 __has_timeout, __s, __ns);
114 __assumed = _M_load(__mo);
115 if (!__ret || ((__operand == __assumed) == __equal))
128 _M_load_and_test_until_steady(
unsigned __assumed,
unsigned __operand,
139 _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);
140 bool __ret = _M_futex_wait_until_steady((
unsigned*)(
void*)&_M_data,
141 __assumed | _Waiter_bit,
142 __has_timeout, __s, __ns);
144 __assumed = _M_load(__mo);
145 if (!__ret || ((__operand == __assumed) == __equal))
156 _M_load_and_test(
unsigned __assumed,
unsigned __operand,
159 return _M_load_and_test_until(__assumed, __operand, __equal, __mo,
168 template<
typename _Dur>
170 _M_load_and_test_until_impl(
unsigned __assumed,
unsigned __operand,
172 const chrono::time_point<std::chrono::system_clock, _Dur>& __atime)
174 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
175 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
177 return _M_load_and_test_until(__assumed, __operand, __equal, __mo,
178 true, __s.time_since_epoch(), __ns);
181 template<
typename _Dur>
183 _M_load_and_test_until_impl(
unsigned __assumed,
unsigned __operand,
185 const chrono::time_point<std::chrono::steady_clock, _Dur>& __atime)
187 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
188 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
190 return _M_load_and_test_until_steady(__assumed, __operand, __equal, __mo,
191 true, __s.time_since_epoch(), __ns);
196 _GLIBCXX_ALWAYS_INLINE
unsigned
197 _M_load_when_not_equal(
unsigned __val,
memory_order __mo)
199 unsigned __i = _M_load(__mo);
200 if ((__i & ~_Waiter_bit) != __val)
201 return (__i & ~_Waiter_bit);
203 return _M_load_and_test(__i, __val,
false, __mo);
206 _GLIBCXX_ALWAYS_INLINE
void
209 unsigned __i = _M_load(__mo);
210 if ((__i & ~_Waiter_bit) == __val)
213 _M_load_and_test(__i, __val,
true, __mo);
217 template<
typename _Rep,
typename _Period>
218 _GLIBCXX_ALWAYS_INLINE
bool
219 _M_load_when_equal_for(
unsigned __val,
memory_order __mo,
220 const chrono::duration<_Rep, _Period>& __rtime)
222 using __dur =
typename __clock_t::duration;
223 return _M_load_when_equal_until(__val, __mo,
224 __clock_t::now() + chrono::__detail::ceil<__dur>(__rtime));
228 template<
typename _Clock,
typename _Duration>
229 _GLIBCXX_ALWAYS_INLINE
bool
230 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
231 const chrono::time_point<_Clock, _Duration>& __atime)
233 typename _Clock::time_point __c_entry = _Clock::now();
235 const __clock_t::time_point __s_entry = __clock_t::now();
236 const auto __delta = __atime - __c_entry;
237 const auto __s_atime = __s_entry +
238 chrono::__detail::ceil<__clock_t::duration>(__delta);
239 if (_M_load_when_equal_until(__val, __mo, __s_atime))
241 __c_entry = _Clock::now();
242 }
while (__c_entry < __atime);
247 template<
typename _Duration>
248 _GLIBCXX_ALWAYS_INLINE
bool
249 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
250 const chrono::time_point<std::chrono::system_clock, _Duration>& __atime)
252 unsigned __i = _M_load(__mo);
253 if ((__i & ~_Waiter_bit) == __val)
256 __i = _M_load_and_test_until_impl(__i, __val,
true, __mo, __atime);
257 return (__i & ~_Waiter_bit) == __val;
261 template<
typename _Duration>
262 _GLIBCXX_ALWAYS_INLINE
bool
263 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
264 const chrono::time_point<std::chrono::steady_clock, _Duration>& __atime)
266 unsigned __i = _M_load(__mo);
267 if ((__i & ~_Waiter_bit) == __val)
270 __i = _M_load_and_test_until_impl(__i, __val,
true, __mo, __atime);
271 return (__i & ~_Waiter_bit) == __val;
274 _GLIBCXX_ALWAYS_INLINE
void
277 unsigned* __futex = (
unsigned *)(
void *)&_M_data;
278 if (_M_data.exchange(__val, __mo) & _Waiter_bit)
279 _M_futex_notify_all(__futex);
288 template <
unsigned _Waiter_bit = 0x80000000>
289 class __atomic_futex_unsigned
291 typedef chrono::system_clock __clock_t;
295 condition_variable _M_condvar;
299 __atomic_futex_unsigned(
unsigned __data) : _M_data(__data)
302 _GLIBCXX_ALWAYS_INLINE
unsigned
305 unique_lock<mutex> __lock(_M_mutex);
309 _GLIBCXX_ALWAYS_INLINE
unsigned
310 _M_load_when_not_equal(
unsigned __val,
memory_order __mo)
312 unique_lock<mutex> __lock(_M_mutex);
313 while (_M_data == __val)
314 _M_condvar.wait(__lock);
318 _GLIBCXX_ALWAYS_INLINE
void
321 unique_lock<mutex> __lock(_M_mutex);
322 while (_M_data != __val)
323 _M_condvar.wait(__lock);
326 template<
typename _Rep,
typename _Period>
327 _GLIBCXX_ALWAYS_INLINE
bool
328 _M_load_when_equal_for(
unsigned __val,
memory_order __mo,
329 const chrono::duration<_Rep, _Period>& __rtime)
331 unique_lock<mutex> __lock(_M_mutex);
332 return _M_condvar.wait_for(__lock, __rtime,
333 [&] {
return _M_data == __val;});
336 template<
typename _Clock,
typename _Duration>
337 _GLIBCXX_ALWAYS_INLINE
bool
338 _M_load_when_equal_until(
unsigned __val,
memory_order __mo,
339 const chrono::time_point<_Clock, _Duration>& __atime)
341 unique_lock<mutex> __lock(_M_mutex);
342 return _M_condvar.wait_until(__lock, __atime,
343 [&] {
return _M_data == __val;});
346 _GLIBCXX_ALWAYS_INLINE
void
349 unique_lock<mutex> __lock(_M_mutex);
351 _M_condvar.notify_all();
358_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.