NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
atomic_timed_wait.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
2#define NEFORCE_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
3
10
13NEFORCE_BEGIN_NAMESPACE__
14
20
22NEFORCE_BEGIN_INNER__
23
24using wait_clock_t = steady_clock;
25
35template <typename Clock, typename Dur>
36wait_clock_t::time_point to_wait_clock(const time_point<Clock, Dur>& time_point) noexcept {
37 const typename Clock::time_point clock_entry = Clock::now();
38 const wait_clock_t::time_point wait_entry = wait_clock_t::now();
39 const auto delta = time_point - clock_entry;
40 return wait_entry + ceil<wait_clock_t::duration>(delta);
41}
42
51template <typename Dur>
52wait_clock_t::time_point to_wait_clock(const time_point<wait_clock_t, Dur>& time_point) noexcept {
54}
55
66template <typename Dur>
67bool __platform_wait_until_impl(const platform_wait_t* addr, const platform_wait_t old,
68 const time_point<wait_clock_t, Dur>& timeout) noexcept {
69 const bool has_timeout = (timeout != wait_clock_t::time_point::max());
70
71 if (!has_timeout) {
72 futex_wait(const_cast<void*>(static_cast<const void*>(addr)), old);
73 return true;
74 }
75
76 const auto now = wait_clock_t::now();
77 if (timeout <= now) {
78 return false;
79 }
80
81 const auto dur = timeout - now;
82 const auto sec = _NEFORCE time_cast<seconds>(dur);
83 const auto ns = _NEFORCE time_cast<nanoseconds>(dur - sec);
84
85 return _NEFORCE futex_wait_until(const_cast<void*>(static_cast<const void*>(addr)), old, true, sec.count(),
86 ns.count(), true);
87}
88
89template <typename Clock, typename Dur>
91__platform_wait_until_dispatch(const platform_wait_t* addr, platform_wait_t old,
93 return inner::__platform_wait_until_impl(addr, old, timeout);
94}
95
96template <typename Clock, typename Dur>
98__platform_wait_until_dispatch(const platform_wait_t* addr, platform_wait_t old,
100 if (!inner::__platform_wait_until_impl(addr, old, inner::to_wait_clock(timeout))) {
101 if (Clock::now() < timeout) {
102 return true;
103 }
104 }
105 return false;
106}
107
108NEFORCE_END_INNER__
110
116
128template <typename Clock, typename Dur>
130 return inner::__platform_wait_until_dispatch(addr, old, timeout);
131}
132 // Futex
134
140
150struct timed_backoff_spin_policy {
151 inner::wait_clock_t::time_point deadline;
152 inner::wait_clock_t::time_point start_time;
153
154 template <typename Clock, typename Dur>
155 timed_backoff_spin_policy(time_point<Clock, Dur> deadline_time = Clock::time_point::max(),
156 time_point<Clock, Dur> start_time_point = Clock::now()) noexcept :
157 deadline(inner::to_wait_clock(deadline_time)),
158 start_time(inner::to_wait_clock(start_time_point)) {}
159
160 bool operator()() const noexcept {
161 const auto now = inner::wait_clock_t::now();
162 if (deadline <= now) {
163 return false;
164 }
165
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();
173 } else {
174 return false;
175 }
176 return true;
177 }
178};
179
181NEFORCE_BEGIN_INNER__
182
189struct timed_waiter_pool : waiter_pool_base {
199 template <typename Clock, typename Dur>
200 bool do_wait_until(platform_wait_t* addr, platform_wait_t old, const time_point<Clock, Dur>& timeout) {
201 return _NEFORCE futex_wait_until(addr, old, timeout);
202 }
203};
204
212template <typename EntersWait>
213struct timed_waiter : waiter_base<timed_waiter_pool> {
214 using base_type = waiter_base<timed_waiter_pool>;
215
216private:
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();
220 }
221 template <bool Wait = EntersWait::value, enable_if_t<!Wait, int> = 0>
222 NEFORCE_ALWAYS_INLINE void enter() const noexcept {}
223
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();
227 }
228 template <bool Wait = EntersWait::value, enable_if_t<!Wait, int> = 0>
229 NEFORCE_ALWAYS_INLINE void leave() const noexcept {}
230
231public:
237 template <typename T>
238 explicit timed_waiter(const T* addr) noexcept :
239 base_type(addr) {
240 enter();
241 }
242
246 ~timed_waiter() { leave(); }
247
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 {
261 platform_wait_t value = 0;
262 if (base_type::waiter_do_spin(old, _NEFORCE move(func), value, timed_backoff_spin_policy(timeout))) {
263 return true;
264 }
265 return base_type::waiter_.do_wait_until(base_type::addr_, value, timeout);
266 }
267
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()) {
282 return true;
283 }
284 if (base_type::waiter_do_spin(pred, value, timed_backoff_spin_policy(timeout, now))) {
285 return true;
286 }
287 }
288 return false;
289 }
290
300 template <typename Pred, typename Clock, typename Dur>
301 bool waiter_do_wait_until(Pred pred, const time_point<Clock, Dur>& timeout) noexcept {
302 platform_wait_t value = 0;
303 if (this->waiter_do_spin(pred, value, timed_backoff_spin_policy(timeout))) {
304 return true;
305 }
306 return this->waiter_do_wait_until(pred, value, timeout);
307 }
308
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 {
322 platform_wait_t value = 0;
323 if (base_type::waiter_do_spin_v(old, _NEFORCE move(func), value)) {
324 return true;
325 }
326 if (!rt.count()) {
327 return false;
328 }
329 auto rtc = ceil<wait_clock_t::duration>(rt);
330 return base_type::waiter_.do_wait_until(base_type::addr_, value, steady_clock::now() + rtc);
331 }
332
342 template <typename Pred, typename Rep, typename Period>
343 bool waiter_do_wait_for(Pred pred, const duration<Rep, Period>& rt) noexcept {
344 platform_wait_t value = 0;
345 if (base_type::waiter_do_spin(pred, value)) {
346 return true;
347 }
348 if (!rt.count()) {
349 return false;
350 }
351 auto rtc = ceil<wait_clock_t::duration>(rt);
352 return this->waiter_do_wait_until(pred, value, steady_clock::now() + rtc);
353 }
354};
355
357using enters_timed_wait = timed_waiter<true_type>;
358
360using bare_timed_wait = timed_waiter<false_type>;
361
362NEFORCE_END_INNER__
364
379template <typename T, typename Func, typename Clock, typename Dur>
380bool atomic_wait_address_until_v(const T* addr, T&& old, Func&& func, const time_point<Clock, Dur>& timeout) noexcept {
381 inner::enters_timed_wait waiter{addr};
382 return waiter.waiter_do_wait_until_v(old, func, timeout);
383}
384
398template <typename T, typename Pred, typename Clock, typename Dur>
399bool atomic_wait_address_until(const T* addr, Pred pred, const time_point<Clock, Dur>& timeout) noexcept {
400 inner::enters_timed_wait waiter{addr};
401 return waiter.waiter_do_wait_until(pred, timeout);
402}
403
416template <typename Pred, typename Clock, typename Dur>
417bool atomic_wait_address_until(const platform_wait_t* addr, Pred pred, const time_point<Clock, Dur>& timeout) noexcept {
418 inner::bare_timed_wait waiter{addr};
419 return waiter.waiter_do_wait_until(pred, timeout);
420}
421
436template <typename T, typename Func, typename Rep, typename Period>
437bool atomic_wait_address_for_v(const T* addr, T&& old, Func&& func, const duration<Rep, Period>& rt) noexcept {
438 inner::enters_timed_wait waiter{addr};
439 return waiter.waiter_do_wait_for_v(old, func, rt);
440}
441
455template <typename T, typename Pred, typename Rep, typename Period>
456bool atomic_wait_address_for(const T* addr, Pred pred, const duration<Rep, Period>& rt) noexcept {
457 inner::enters_timed_wait waiter{addr};
458 return waiter.waiter_do_wait_for(pred, rt);
459}
460
473template <typename Pred, typename Rep, typename Period>
474bool atomic_wait_address_for(const platform_wait_t* addr, Pred pred, const duration<Rep, Period>& rt) noexcept {
475 inner::bare_timed_wait waiter{addr};
476 return waiter.waiter_do_wait_for(pred, rt);
477}
478 // AtomicOperations
480 // AsyncComponents
482
483NEFORCE_END_NAMESPACE__
484#endif // NEFORCE_CORE_ASYNC_ATOMIC_TIMED_WAIT_HPP__
原子等待/通知机制
时钟类型
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
获取当前时间点
时间点类模板