30 #ifndef _GLIBCXX_ATOMIC_TIMED_WAIT_H
31 #define _GLIBCXX_ATOMIC_TIMED_WAIT_H 1
33 #pragma GCC system_header
37 #if __cpp_lib_atomic_wait
42 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
47 namespace std _GLIBCXX_VISIBILITY(default)
49 _GLIBCXX_BEGIN_NAMESPACE_VERSION
51 enum class __atomic_wait_status { no_timeout, timeout };
55 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
56 using __platform_wait_clock_t = chrono::steady_clock;
58 template<
typename _Duration>
60 __platform_wait_until_impl(__platform_wait_t* __addr,
61 __platform_wait_t __val,
62 const chrono::time_point<
63 __platform_wait_clock_t, _Duration>&
66 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
67 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
69 struct timespec __rt =
71 static_cast<std::time_t
>(__s.time_since_epoch().count()),
72 static_cast<long>(__ns.count())
75 auto __e = syscall (SYS_futex, __addr,
76 static_cast<int>(__futex_wait_flags::
77 __wait_bitset_private),
78 __val, &__rt,
nullptr,
79 static_cast<int>(__futex_wait_flags::
81 if (__e && !(errno == EINTR || errno == EAGAIN || errno == ETIMEDOUT))
83 return (__platform_wait_clock_t::now() < __atime)
84 ? __atomic_wait_status::no_timeout
85 : __atomic_wait_status::timeout;
88 template<
typename _Clock,
typename _Duration>
90 __platform_wait_until(__platform_wait_t* __addr, __platform_wait_t __val,
91 const chrono::time_point<_Clock, _Duration>&
94 if constexpr (is_same_v<__platform_wait_clock_t, _Clock>)
96 return __detail::__platform_wait_until_impl(__addr, __val, __atime);
100 const typename _Clock::time_point __c_entry = _Clock::now();
101 const __platform_wait_clock_t::time_point __s_entry =
102 __platform_wait_clock_t::now();
103 const auto __delta = __atime - __c_entry;
104 const auto __s_atime = __s_entry + __delta;
105 if (__detail::__platform_wait_until_impl(__addr, __val, __s_atime)
106 == __atomic_wait_status::no_timeout)
107 return __atomic_wait_status::no_timeout;
112 if (_Clock::now() < __atime)
113 return __atomic_wait_status::no_timeout;
114 return __atomic_wait_status::timeout;
119 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
120 template<
typename _Duration>
122 __cond_wait_until_impl(__condvar& __cv, mutex& __mx,
123 const chrono::time_point<chrono::steady_clock, _Duration>& __atime)
125 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
126 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
128 __gthread_time_t __ts =
130 static_cast<std::time_t
>(__s.time_since_epoch().count()),
131 static_cast<long>(__ns.count())
134 __cv.wait_until(__mx, CLOCK_MONOTONIC, __ts);
136 return (chrono::steady_clock::now() < __atime)
137 ? __atomic_wait_status::no_timeout
138 : __atomic_wait_status::timeout;
142 template<
typename _Duration>
144 __cond_wait_until_impl(__condvar& __cv, mutex& __mx,
145 const chrono::time_point<chrono::system_clock, _Duration>& __atime)
147 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
148 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
150 __gthread_time_t __ts =
152 static_cast<std::time_t
>(__s.time_since_epoch().count()),
153 static_cast<long>(__ns.count())
156 __cv.wait_until(__mx, __ts);
158 return (chrono::system_clock::now() < __atime)
159 ? __atomic_wait_status::no_timeout
160 : __atomic_wait_status::timeout;
164 template<
typename _Clock,
typename _Duration>
166 __cond_wait_until(__condvar& __cv, mutex& __mx,
167 const chrono::time_point<_Clock, _Duration>& __atime)
169 #ifndef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
170 using __clock_t = chrono::system_clock;
172 using __clock_t = chrono::steady_clock;
173 if constexpr (is_same_v<_Clock, chrono::steady_clock>)
174 return __detail::__cond_wait_until_impl(__cv, __mx, __atime);
177 if constexpr (is_same_v<_Clock, chrono::system_clock>)
178 return __detail::__cond_wait_until_impl(__cv, __mx, __atime);
181 const typename _Clock::time_point __c_entry = _Clock::now();
182 const __clock_t::time_point __s_entry = __clock_t::now();
183 const auto __delta = __atime - __c_entry;
184 const auto __s_atime = __s_entry + __delta;
185 if (__detail::__cond_wait_until_impl(__cv, __mx, __s_atime)
186 == __atomic_wait_status::no_timeout)
187 return __atomic_wait_status::no_timeout;
191 if (_Clock::now() < __atime)
192 return __atomic_wait_status::no_timeout;
193 return __atomic_wait_status::timeout;
198 struct __timed_waiters : __waiters
200 template<
typename _Clock,
typename _Duration>
202 _M_do_wait_until(__platform_wait_t __version,
203 const chrono::time_point<_Clock, _Duration>& __atime)
205 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
206 return __detail::__platform_wait_until(&_M_ver, __version, __atime);
208 __platform_wait_t __cur = 0;
209 __waiters::__lock_t __l(_M_mtx);
210 while (__cur <= __version)
212 if (__detail::__cond_wait_until(_M_cv, _M_mtx, __atime)
213 == __atomic_wait_status::timeout)
214 return __atomic_wait_status::timeout;
216 __platform_wait_t __last = __cur;
217 __atomic_load(&_M_ver, &__cur, __ATOMIC_ACQUIRE);
221 return __atomic_wait_status::no_timeout;
225 static __timed_waiters&
226 _S_timed_for(
void* __t)
228 static_assert(
sizeof(__timed_waiters) ==
sizeof(__waiters));
229 return static_cast<__timed_waiters&
>(__waiters::_S_for(__t));
234 template<
typename _Tp,
typename _Pred,
235 typename _Clock,
typename _Duration>
237 __atomic_wait_until(
const _Tp* __addr, _Tp __old, _Pred __pred,
238 const chrono::time_point<_Clock, _Duration>&
241 using namespace __detail;
243 if (std::__atomic_spin(__pred))
246 auto& __w = __timed_waiters::_S_timed_for((
void*)__addr);
247 auto __version = __w._M_enter_wait();
250 __atomic_wait_status __res;
251 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
252 if constexpr (__platform_wait_uses_type<_Tp>)
254 __res = __detail::__platform_wait_until((__platform_wait_t*)(
void*) __addr,
260 __res = __w._M_do_wait_until(__version, __atime);
262 if (__res == __atomic_wait_status::timeout)
265 while (!__pred() && __atime < _Clock::now());
269 return (_Clock::now() < __atime);
272 template<
typename _Tp,
typename _Pred,
273 typename _Rep,
typename _Period>
275 __atomic_wait_for(
const _Tp* __addr, _Tp __old, _Pred __pred,
276 const chrono::duration<_Rep, _Period>& __rtime) noexcept
278 using namespace __detail;
280 if (std::__atomic_spin(__pred))
283 if (!__rtime.count())
286 using __dur = chrono::steady_clock::duration;
287 auto __reltime = chrono::duration_cast<__dur>(__rtime);
288 if (__reltime < __rtime)
291 return __atomic_wait_until(__addr, __old,
std::move(__pred),
292 chrono::steady_clock::now() + __reltime);
294 _GLIBCXX_END_NAMESPACE_VERSION
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
void terminate() noexcept
ISO C++ entities toplevel namespace is std.