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();
85 return _NEFORCE
futex_wait_until(
const_cast<void*
>(
static_cast<const void*
>(addr)), old,
true, sec.count(),
89template <
typename Clock,
typename Dur>
93 return inner::__platform_wait_until_impl(addr, old,
timeout);
96template <
typename Clock,
typename Dur>
100 if (!inner::__platform_wait_until_impl(addr, old, inner::to_wait_clock(
timeout))) {
128template <
typename Clock,
typename Dur>
130 return inner::__platform_wait_until_dispatch(addr, old,
timeout);
150struct timed_backoff_spin_policy {
151 inner::wait_clock_t::time_point deadline;
152 inner::wait_clock_t::time_point start_time;
154 template <
typename Clock,
typename Dur>
157 deadline(inner::to_wait_clock(deadline_time)),
158 start_time(inner::to_wait_clock(start_time_point)) {}
160 bool operator()()
const noexcept {
161 const auto now = inner::wait_clock_t::now();
162 if (deadline <= now) {
166 const auto elapsed = now - start_time;
167 if (elapsed > 128_ms) {
168 this_thread::sleep_for(64_ms);
169 }
else if (elapsed > 64_us) {
170 this_thread::sleep_for(elapsed / 2);
171 }
else if (elapsed > 4_us) {
172 this_thread::yield();
189struct timed_waiter_pool : waiter_pool_base {
199 template <
typename Clock,
typename Dur>
212template <
typename EntersWait>
213struct timed_waiter : waiter_base<timed_waiter_pool> {
214 using base_type = waiter_base<timed_waiter_pool>;
217 template <
bool Wait = EntersWait::value, enable_if_t<Wait,
int> = 0>
218 NEFORCE_ALWAYS_INLINE
void enter() const noexcept {
219 waiter_.waiter_enter_wait();
221 template <
bool Wait = EntersWait::value, enable_if_t<!Wait,
int> = 0>
222 NEFORCE_ALWAYS_INLINE
void enter() const noexcept {}
224 template <
bool Wait = EntersWait::value, enable_if_t<Wait,
int> = 0>
225 NEFORCE_ALWAYS_INLINE
void leave() const noexcept {
226 waiter_.waiter_leave_wait();
228 template <
bool Wait = EntersWait::value, enable_if_t<!Wait,
int> = 0>
229 NEFORCE_ALWAYS_INLINE
void leave() const noexcept {}
237 template <
typename T>
238 explicit timed_waiter(
const T* addr) noexcept :
246 ~timed_waiter() { leave(); }
259 template <
typename T,
typename Func,
typename Clock,
typename Dur>
260 bool waiter_do_wait_until_v(T old, Func func,
const time_point<Clock, Dur>&
timeout)
noexcept {
262 if (base_type::waiter_do_spin(old, _NEFORCE
move(func), value, timed_backoff_spin_policy(
timeout))) {
265 return base_type::waiter_.do_wait_until(base_type::addr_, value,
timeout);
278 template <
typename Pred,
typename Clock,
typename Dur>
279 bool waiter_do_wait_until(Pred pred,
platform_wait_t value,
const time_point<Clock, Dur>&
timeout)
noexcept {
280 for (
auto now = Clock::now(); now <
timeout; now = Clock::now()) {
281 if (base_type::waiter_.do_wait_until(base_type::addr_, value,
timeout) && pred()) {
284 if (base_type::waiter_do_spin(pred, value, timed_backoff_spin_policy(
timeout, now))) {
300 template <
typename Pred,
typename Clock,
typename Dur>
301 bool waiter_do_wait_until(Pred pred,
const time_point<Clock, Dur>&
timeout)
noexcept {
303 if (this->waiter_do_spin(pred, value, timed_backoff_spin_policy(
timeout))) {
306 return this->waiter_do_wait_until(pred, value,
timeout);
320 template <
typename T,
typename Func,
typename Rep,
typename Period>
321 bool waiter_do_wait_for_v(T old, Func func,
const duration<Rep, Period>& rt)
noexcept {
323 if (base_type::waiter_do_spin_v(old, _NEFORCE
move(func), value)) {
330 return base_type::waiter_.do_wait_until(base_type::addr_, value,
steady_clock::now() + rtc);
342 template <
typename Pred,
typename Rep,
typename Period>
343 bool waiter_do_wait_for(Pred pred,
const duration<Rep, Period>& rt)
noexcept {
345 if (base_type::waiter_do_spin(pred, value)) {
357using enters_timed_wait = timed_waiter<true_type>;
360using bare_timed_wait = timed_waiter<false_type>;
379template <
typename T,
typename Func,
typename Clock,
typename Dur>
381 inner::enters_timed_wait waiter{addr};
382 return waiter.waiter_do_wait_until_v(old, func,
timeout);
398template <
typename T,
typename Pred,
typename Clock,
typename Dur>
400 inner::enters_timed_wait waiter{addr};
401 return waiter.waiter_do_wait_until(pred,
timeout);
416template <
typename Pred,
typename Clock,
typename Dur>
418 inner::bare_timed_wait waiter{addr};
419 return waiter.waiter_do_wait_until(pred,
timeout);
436template <
typename T,
typename Func,
typename Rep,
typename Period>
438 inner::enters_timed_wait waiter{addr};
439 return waiter.waiter_do_wait_for_v(old, func, rt);
455template <
typename T,
typename Pred,
typename Rep,
typename Period>
457 inner::enters_timed_wait waiter{addr};
458 return waiter.waiter_do_wait_for(pred, rt);
473template <
typename Pred,
typename Rep,
typename Period>
475 inner::bare_timed_wait waiter{addr};
476 return waiter.waiter_do_wait_for(pred, rt);
483NEFORCE_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 futex_wait(void *addr, platform_wait_t value) noexcept
无限期等待FUTEX
long platform_wait_t
平台等待类型别名
bool futex_wait_until(const platform_wait_t *addr, platform_wait_t old, const time_point< Clock, Dur > &timeout)
FUTEX定时等待函数
constexpr 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
获取当前时间点