1#ifndef MSTL_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
2#define MSTL_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
29template <
typename Clock,
typename Dur>
31 const typename Clock::time_point clock_entry = Clock::now();
32 const wait_clock_t::time_point wait_entry = wait_clock_t::now();
45template <
typename Dur>
60template <
typename Dur>
61bool __platform_wait_until_impl(
64 const bool has_timeout = (
timeout != wait_clock_t::time_point::max());
67 _MSTL futex_wait(
const_cast<void*
>(
static_cast<const void*
>(addr)), old);
71 const auto now = wait_clock_t::now();
76#ifdef MSTL_PLATFORM_WINDOWS__
83 if (sys_timeout <= sys_now) {
86 const auto sys_dur = sys_timeout - sys_now;
92 const_cast<void*
>(
static_cast<const void*
>(addr)),
93 old,
true, sec.count(), ns.count(),
true);
96template <
typename Clock,
typename Dur>
100 return _INNER __platform_wait_until_impl(addr, old,
timeout);
103template <
typename Clock,
typename Dur>
108 if (Clock::now() <
timeout)
return true;
133template <
typename Clock,
typename Dur>
137 return _INNER __platform_wait_until_dispatch(addr, old,
timeout);
157struct timed_backoff_spin_policy {
158 _INNER wait_clock_t::time_point deadline;
159 _INNER wait_clock_t::time_point start_time;
161 template <
typename Clock,
typename Dur>
162 timed_backoff_spin_policy(
165 : deadline(
_INNER to_wait_clock(deadline_time)),
166 start_time(
_INNER to_wait_clock(start_time_point)) {}
168 bool operator ()()
const noexcept {
169 const auto now =
_INNER wait_clock_t::now();
170 if (deadline <= now) {
174 const auto elapsed = now - start_time;
175 if (elapsed > 128_ms) {
176 this_thread::sleep_for(64_ms);
177 }
else if (elapsed > 64_us) {
178 this_thread::sleep_for(elapsed / 2);
179 }
else if (elapsed > 4_us) {
180 this_thread::yield();
197struct timed_waiter_pool : waiter_pool_base {
207 template <
typename Clock,
typename Dur>
221template <
typename EntersWait>
222struct timed_waiter : waiter_base<timed_waiter_pool> {
223 using base_type = waiter_base<timed_waiter_pool>;
226 template <
bool Wait = EntersWait::value, enable_if_t<Wait,
int> = 0>
227 MSTL_ALWAYS_INLINE
void enter() const noexcept {
228 waiter_.waiter_enter_wait();
230 template <
bool Wait = EntersWait::value, enable_if_t<!Wait,
int> = 0>
231 MSTL_ALWAYS_INLINE
void enter() const noexcept {}
233 template <
bool Wait = EntersWait::value, enable_if_t<Wait,
int> = 0>
234 MSTL_ALWAYS_INLINE
void leave() const noexcept {
235 waiter_.waiter_leave_wait();
237 template <
bool Wait = EntersWait::value, enable_if_t<!Wait,
int> = 0>
238 MSTL_ALWAYS_INLINE
void leave() const noexcept {}
246 template <
typename T>
247 explicit timed_waiter(
const T* addr) noexcept
270 template <
typename T,
typename Func,
typename Clock,
typename Dur>
271 bool waiter_do_wait_until_v(T old, Func func,
272 const time_point<Clock, Dur>&
timeout)
noexcept {
274 if (base_type::waiter_do_spin(old,
_MSTL move(func), value,
275 timed_backoff_spin_policy(
timeout))) {
278 return base_type::waiter_.do_wait_until(base_type::addr_, value,
timeout);
291 template <
typename Pred,
typename Clock,
typename Dur>
293 const time_point<Clock, Dur>&
timeout)
noexcept {
294 for (
auto now = Clock::now(); now <
timeout; now = Clock::now()) {
295 if (base_type::waiter_.do_wait_until(base_type::addr_, value,
timeout) && pred()) {
298 if (base_type::waiter_do_spin(pred, value, timed_backoff_spin_policy(
timeout, now)))
313 template <
typename Pred,
typename Clock,
typename Dur>
314 bool waiter_do_wait_until(Pred pred,
const time_point<Clock, Dur>&
timeout)
noexcept {
316 if (this->waiter_do_spin(pred, value, timed_backoff_spin_policy(
timeout))) {
319 return this->waiter_do_wait_until(pred, value,
timeout);
333 template <
typename T,
typename Func,
typename Rep,
typename Period>
334 bool waiter_do_wait_for_v(T old, Func func,
const duration<Rep, Period>& rt)
noexcept {
336 if (base_type::waiter_do_spin_v(old,
_MSTL move(func), value)) {
343 return base_type::waiter_.do_wait_until(base_type::addr_, value,
steady_clock::now() + rtc);
355 template <
typename Pred,
typename Rep,
typename Period>
356 bool waiter_do_wait_for(Pred pred,
const duration<Rep, Period>& rt)
noexcept {
358 if (base_type::waiter_do_spin(pred, value)) {
370using enters_timed_wait = timed_waiter<true_type>;
373using bare_timed_wait = timed_waiter<false_type>;
392template <
typename T,
typename Func,
typename Clock,
typename Dur>
395 _INNER enters_timed_wait waiter{addr};
396 return waiter.waiter_do_wait_until_v(old, func,
timeout);
412template <
typename T,
typename Pred,
typename Clock,
typename Dur>
415 _INNER enters_timed_wait waiter{addr};
416 return waiter.waiter_do_wait_until(pred,
timeout);
431template <
typename Pred,
typename Clock,
typename Dur>
434 _INNER bare_timed_wait waiter{addr};
435 return waiter.waiter_do_wait_until(pred,
timeout);
452template <
typename T,
typename Func,
typename Rep,
typename Period>
455 _INNER enters_timed_wait waiter{addr};
456 return waiter.waiter_do_wait_for_v(old, func, rt);
472template <
typename T,
typename Pred,
typename Rep,
typename Period>
475 _INNER enters_timed_wait waiter{addr};
476 return waiter.waiter_do_wait_for(pred, rt);
491template <
typename Pred,
typename Rep,
typename Period>
494 _INNER bare_timed_wait waiter{addr};
495 return waiter.waiter_do_wait_for(pred, rt);
bool atomic_wait_address_until_v(const T *addr, T &&old, Func &&func, const time_point< Clock, Dur > &timeout) noexcept
基于值的原子定时等待(绝对时间)
bool atomic_wait_address_until(const T *addr, Pred pred, const time_point< Clock, Dur > &timeout) noexcept
基于谓词的原子定时等待(绝对时间)
bool atomic_wait_address_for_v(const T *addr, T &&old, Func &&func, const duration< Rep, Period > &rt) noexcept
基于值的原子定时等待(相对时间)
bool atomic_wait_address_for(const T *addr, Pred pred, const duration< Rep, Period > &rt) noexcept
基于谓词的原子定时等待(相对时间)
constexpr ToDur time_cast(const duration< Rep, Period > &value)
持续时间类型转换
int platform_wait_t
平台等待类型别名
bool futex_wait_until(const platform_wait_t *addr, platform_wait_t old, const time_point< Clock, Dur > &timeout)
FUTEX定时等待函数
void MSTL_API futex_wait(void *addr, platform_wait_t value) noexcept
无限期等待FUTEX
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 decimal_t ceil(const decimal_t x) noexcept
向上取整
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
static time_point now() noexcept
获取当前时间点
static system_clock::time_point to_system(const _MSTL time_point< steady_clock, Dur > &tp)
将稳定时钟转为系统时钟
static time_point now() noexcept
获取当前时间点