1#ifndef NEFORCE_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
2#define NEFORCE_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
13NEFORCE_BEGIN_NAMESPACE__
35template <
typename Clock,
typename Dur>
37 const typename Clock::time_point clock_entry = Clock::now();
38 const wait_clock_t::time_point wait_entry = wait_clock_t::now();
51template <
typename Dur>
66template <
typename Dur>
69 const bool has_timeout = (
timeout != wait_clock_t::time_point::max());
72 futex_wait(
const_cast<void*
>(
static_cast<const void*
>(addr)), old);
76 const auto now = wait_clock_t::now();
81#ifdef NEFORCE_PLATFORM_WINDOWS
88 if (sys_timeout <= sys_now) {
91 const auto sys_dur = sys_timeout - sys_now;
96 return _NEFORCE
futex_wait_until(
const_cast<void*
>(
static_cast<const void*
>(addr)), old,
true, sec.count(),
100template <
typename Clock,
typename Dur>
104 return inner::__platform_wait_until_impl(addr, old,
timeout);
107template <
typename Clock,
typename Dur>
111 if (!inner::__platform_wait_until_impl(addr, old, inner::to_wait_clock(
timeout))) {
139template <
typename Clock,
typename Dur>
141 return inner::__platform_wait_until_dispatch(addr, old,
timeout);
161struct timed_backoff_spin_policy {
162 inner::wait_clock_t::time_point deadline;
163 inner::wait_clock_t::time_point start_time;
165 template <
typename Clock,
typename Dur>
168 deadline(inner::to_wait_clock(deadline_time)),
169 start_time(inner::to_wait_clock(start_time_point)) {}
171 bool operator()()
const noexcept {
172 const auto now = inner::wait_clock_t::now();
173 if (deadline <= now) {
177 const auto elapsed = now - start_time;
178 if (elapsed > 128_ms) {
179 this_thread::sleep_for(64_ms);
180 }
else if (elapsed > 64_us) {
181 this_thread::sleep_for(elapsed / 2);
182 }
else if (elapsed > 4_us) {
183 this_thread::yield();
200struct timed_waiter_pool : waiter_pool_base {
210 template <
typename Clock,
typename Dur>
223template <
typename EntersWait>
224struct timed_waiter : waiter_base<timed_waiter_pool> {
225 using base_type = waiter_base<timed_waiter_pool>;
228 template <
bool Wait = EntersWait::value, enable_if_t<Wait,
int> = 0>
229 NEFORCE_ALWAYS_INLINE
void enter() const noexcept {
230 waiter_.waiter_enter_wait();
232 template <
bool Wait = EntersWait::value, enable_if_t<!Wait,
int> = 0>
233 NEFORCE_ALWAYS_INLINE
void enter() const noexcept {}
235 template <
bool Wait = EntersWait::value, enable_if_t<Wait,
int> = 0>
236 NEFORCE_ALWAYS_INLINE
void leave() const noexcept {
237 waiter_.waiter_leave_wait();
239 template <
bool Wait = EntersWait::value, enable_if_t<!Wait,
int> = 0>
240 NEFORCE_ALWAYS_INLINE
void leave() const noexcept {}
248 template <
typename T>
249 explicit timed_waiter(
const T* addr) noexcept :
257 ~timed_waiter() { leave(); }
270 template <
typename T,
typename Func,
typename Clock,
typename Dur>
271 bool waiter_do_wait_until_v(T old, Func func,
const time_point<Clock, Dur>&
timeout)
noexcept {
273 if (base_type::waiter_do_spin(old, _NEFORCE
move(func), value, timed_backoff_spin_policy(
timeout))) {
276 return base_type::waiter_.do_wait_until(base_type::addr_, value,
timeout);
289 template <
typename Pred,
typename Clock,
typename Dur>
290 bool waiter_do_wait_until(Pred pred,
platform_wait_t value,
const time_point<Clock, Dur>&
timeout)
noexcept {
291 for (
auto now = Clock::now(); now <
timeout; now = Clock::now()) {
292 if (base_type::waiter_.do_wait_until(base_type::addr_, value,
timeout) && pred()) {
295 if (base_type::waiter_do_spin(pred, value, timed_backoff_spin_policy(
timeout, now))) {
311 template <
typename Pred,
typename Clock,
typename Dur>
312 bool waiter_do_wait_until(Pred pred,
const time_point<Clock, Dur>&
timeout)
noexcept {
314 if (this->waiter_do_spin(pred, value, timed_backoff_spin_policy(
timeout))) {
317 return this->waiter_do_wait_until(pred, value,
timeout);
331 template <
typename T,
typename Func,
typename Rep,
typename Period>
332 bool waiter_do_wait_for_v(T old, Func func,
const duration<Rep, Period>& rt)
noexcept {
334 if (base_type::waiter_do_spin_v(old, _NEFORCE
move(func), value)) {
341 return base_type::waiter_.do_wait_until(base_type::addr_, value,
steady_clock::now() + rtc);
353 template <
typename Pred,
typename Rep,
typename Period>
354 bool waiter_do_wait_for(Pred pred,
const duration<Rep, Period>& rt)
noexcept {
356 if (base_type::waiter_do_spin(pred, value)) {
368using enters_timed_wait = timed_waiter<true_type>;
371using bare_timed_wait = timed_waiter<false_type>;
390template <
typename T,
typename Func,
typename Clock,
typename Dur>
392 inner::enters_timed_wait waiter{addr};
393 return waiter.waiter_do_wait_until_v(old, func,
timeout);
409template <
typename T,
typename Pred,
typename Clock,
typename Dur>
411 inner::enters_timed_wait waiter{addr};
412 return waiter.waiter_do_wait_until(pred,
timeout);
427template <
typename Pred,
typename Clock,
typename Dur>
429 inner::bare_timed_wait waiter{addr};
430 return waiter.waiter_do_wait_until(pred,
timeout);
447template <
typename T,
typename Func,
typename Rep,
typename Period>
449 inner::enters_timed_wait waiter{addr};
450 return waiter.waiter_do_wait_for_v(old, func, rt);
466template <
typename T,
typename Pred,
typename Rep,
typename Period>
468 inner::enters_timed_wait waiter{addr};
469 return waiter.waiter_do_wait_for(pred, rt);
484template <
typename Pred,
typename Rep,
typename Period>
486 inner::bare_timed_wait waiter{addr};
487 return waiter.waiter_do_wait_for(pred, rt);
494NEFORCE_END_NAMESPACE__
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)
持续时间类型转换
void NEFORCE_API futex_wait(void *addr, platform_wait_t value) noexcept
无限期等待FUTEX
int platform_wait_t
平台等待类型别名
bool futex_wait_until(const platform_wait_t *addr, platform_wait_t old, const time_point< Clock, Dur > &timeout)
FUTEX定时等待函数
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 decimal_t ceil(const decimal_t x) noexcept
向上取整
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, 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 _NEFORCE time_point< steady_clock, Dur > &tp)
将稳定时钟转为系统时钟
static time_point now() noexcept
获取当前时间点