1use std::num::NonZeroUsize;
65use std::time::{Duration, Instant, SystemTime};
66use std::{cell::Cell, cmp, future::Future, mem, pin::Pin, rc::Rc, task, task::Poll};
67
68use futures_timer::Delay;
69use slab::Slab;
70
71use super::callbacks::Callbacks;
72use crate::task::LocalWaker;
73
74const UNITS: u64 = 4;
76
77const LVL_CLK_SHIFT: u64 = 3;
79const LVL_CLK_DIV: u64 = 1 << LVL_CLK_SHIFT;
80const LVL_CLK_MASK: u64 = LVL_CLK_DIV - 1;
81
82const LVL_BITS: u64 = 6;
84const LVL_SIZE: u64 = 1 << LVL_BITS;
85const LVL_MASK: u64 = LVL_SIZE - 1;
86
87const LVL_DEPTH: u64 = 8;
89
90const WHEEL_SIZE: usize = (LVL_SIZE * LVL_DEPTH) as usize;
92
93const WHEEL_TIMEOUT_CUTOFF: u64 = lvl_start(LVL_DEPTH);
95const WHEEL_TIMEOUT_MAX: u64 = WHEEL_TIMEOUT_CUTOFF - lvl_gran(LVL_DEPTH - 1);
96
97const LOWRES_RESOLUTION: Duration = Duration::from_millis(150);
99
100const fn lvl_shift(lvl: u64) -> u64 {
102 lvl * LVL_CLK_SHIFT
103}
104
105const fn lvl_gran(lvl: u64) -> u64 {
107 1 << lvl_shift(lvl)
108}
109
110const fn lvl_start(lvl: u64) -> u64 {
113 (LVL_SIZE - 1) << ((lvl - 1) * LVL_CLK_SHIFT)
114}
115
116const fn to_units(millis: u64) -> u64 {
117 millis >> UNITS
118}
119
120const fn to_millis(units: u64) -> u64 {
121 units << UNITS
122}
123
124const fn as_millis(dur: Duration) -> u64 {
125 dur.as_secs() * 1_000 + (dur.subsec_millis() as u64)
126}
127
128#[inline]
133pub fn now() -> Instant {
134 ntex_rt::now()
135}
136
137#[inline]
141pub fn system_time() -> SystemTime {
142 TIMER.with(Timer::system_time)
143}
144
145#[derive(Debug)]
146pub struct TimerHandle(NonZeroUsize);
154
155impl TimerHandle {
156 pub fn new(millis: u64) -> Self {
158 TIMER.with(|t| t.add_timer(millis))
159 }
160
161 pub fn reset(&self, millis: u64) {
163 TIMER.with(|t| t.update_timer(self.0.get(), millis));
164 }
165
166 pub fn elapse(&self) {
168 TIMER.with(|t| t.remove_timer(self.0.get()));
169 }
170
171 pub fn is_elapsed(&self) -> bool {
173 TIMER.with(|t| t.with_wheel(|w| w.timers[self.0.get()].bucket.is_none()))
174 }
175
176 pub fn poll_elapsed(&self, cx: &mut task::Context<'_>) -> Poll<()> {
178 TIMER.with(|t| {
179 t.with_wheel(|w| {
180 let entry = &mut w.timers[self.0.get()];
181 if entry.bucket.is_none() {
182 Poll::Ready(())
183 } else {
184 if entry.task.as_ref().is_none_or(|w| !w.will_wake(cx.waker())) {
185 entry.task = Some(ntex_rt::LocalWaker::from_waker(cx.waker()));
186 }
187 Poll::Pending
188 }
189 })
190 })
191 }
192}
193
194impl Drop for TimerHandle {
195 fn drop(&mut self) {
196 let _ = TIMER.try_with(|t| {
199 t.with_wheel(|w| {
200 w.unlink(self.0.get());
201 w.timers.remove(self.0.get());
202 });
203 });
204 }
205}
206
207bitflags::bitflags! {
208 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
209 struct Flags: u8 {
210 const DRIVER_STARTED = 0b0000_0001;
212 const LOWRES_TIMER = 0b0000_1000;
214 const LOWRES_DRIVER = 0b0001_0000;
216 const RUNNING = 0b0010_0000;
218 }
219}
220
221thread_local! {
222 pub(super) static TIMER: Rc<Timer> = Rc::new(Timer::new());
223}
224
225pub(super) struct Timer {
227 elapsed: Cell<u64>,
229 elapsed_time: Cell<Option<Instant>>,
232 next_expiry: Cell<u64>,
234 flags: Cell<Flags>,
235 pub(super) generation: Cell<u64>,
237 driver: LocalWaker,
238 lowres_stime: Cell<Option<SystemTime>>,
239 lowres_driver: LocalWaker,
240 wheel: Cell<Option<Box<Wheel>>>,
242}
243
244pub(super) struct Wheel {
246 pub(super) timers: Slab<TimerEntry>,
249 buckets: Box<[Slab<usize>]>,
251 occupied: [u64; LVL_DEPTH as usize],
253 pub(super) callbacks: Option<Box<Callbacks>>,
255}
256
257struct WheelGuard<'a> {
258 slot: &'a Cell<Option<Box<Wheel>>>,
259 wheel: Option<Box<Wheel>>,
260}
261
262impl Drop for WheelGuard<'_> {
263 fn drop(&mut self) {
264 self.slot.set(self.wheel.take());
265 }
266}
267
268#[derive(Debug)]
269pub(super) struct TimerEntry {
270 pub(super) bucket: Option<u16>,
272 pub(super) bucket_entry: usize,
274 pub(super) callback: bool,
275 pub(super) task: Option<ntex_rt::LocalWaker>,
276}
277
278#[cfg(target_pointer_width = "64")]
279const _: () = assert!(mem::size_of::<TimerEntry>() == 32);
280
281struct ExpiredTimers<'a> {
282 timers: &'a mut Slab<TimerEntry>,
283 entries: slab::Drain<'a, usize>,
284}
285
286impl Drop for ExpiredTimers<'_> {
287 fn drop(&mut self) {
288 for no in self.entries.by_ref() {
290 self.timers[no].bucket = None;
291 }
292 }
293}
294
295impl Timer {
296 fn new() -> Self {
297 let mut timers = Slab::default();
298 timers.insert(TimerEntry {
299 bucket: None,
300 bucket_entry: 0,
301 callback: false,
302 task: None,
303 });
304
305 Timer {
306 elapsed: Cell::new(0),
307 elapsed_time: Cell::new(None),
308 next_expiry: Cell::new(u64::MAX),
309 flags: Cell::new(Flags::empty()),
310 generation: Cell::new(0),
311 driver: LocalWaker::new(),
312 lowres_stime: Cell::new(None),
313 lowres_driver: LocalWaker::new(),
314 wheel: Cell::new(Some(Box::new(Wheel {
315 timers,
316 buckets: (0..WHEEL_SIZE).map(|_| Slab::new()).collect(),
317 occupied: [0; LVL_DEPTH as usize],
318 callbacks: None,
319 }))),
320 }
321 }
322
323 pub(super) fn with_wheel<F, R>(&self, f: F) -> R
324 where
325 F: FnOnce(&mut Wheel) -> R,
326 {
327 let mut guard = WheelGuard {
328 slot: &self.wheel,
329 wheel: Some(
330 self.wheel
331 .take()
332 .expect("timer wheel operations are not reentrant"),
333 ),
334 };
335 f(guard.wheel.as_deref_mut().unwrap())
336 }
337
338 fn insert_flags(&self, flags: Flags) -> Flags {
339 let mut f = self.flags.get();
340 f.insert(flags);
341 self.flags.set(f);
342 f
343 }
344
345 fn system_time(self: &Rc<Self>) -> SystemTime {
348 if let Some(cur) = self.lowres_stime.get() {
349 cur
350 } else {
351 let now = SystemTime::now();
352 if self.flags.get().contains(Flags::RUNNING) {
353 self.lowres_stime.set(Some(now));
354 self.refresh_lowres();
355 }
356 now
357 }
358 }
359
360 fn refresh_lowres(self: &Rc<Self>) {
362 if self.flags.get().contains(Flags::LOWRES_DRIVER) {
363 self.lowres_driver.wake();
364 } else {
365 LowresTimerDriver::start(self);
366 }
367 }
368
369 fn elapsed_time(&self) -> Instant {
371 if let Some(elapsed_time) = self.elapsed_time.get() {
372 elapsed_time
373 } else {
374 let elapsed_time = Instant::now();
375 self.elapsed_time.set(Some(elapsed_time));
376 elapsed_time
377 }
378 }
379
380 fn add_timer(self: &Rc<Self>, millis: u64) -> TimerHandle {
381 let no = if millis == 0 {
382 self.with_wheel(|w| {
384 w.timers.insert(TimerEntry {
385 bucket: None,
386 bucket_entry: 0,
387 callback: false,
388 task: None,
389 })
390 })
391 } else {
392 let (idx, expiry) = self.calc_bucket(millis);
393 let no = self.with_wheel(|w| {
394 let no = w.timers.insert(TimerEntry {
395 bucket: None,
396 bucket_entry: 0,
397 callback: false,
398 task: None,
399 });
400 w.link(no, idx);
401 no
402 });
403 self.update_next_expiry(expiry);
404 no
405 };
406
407 TimerHandle(NonZeroUsize::new(no).unwrap())
409 }
410
411 fn update_timer(self: &Rc<Self>, hnd: usize, millis: u64) {
414 if millis == 0 {
415 self.remove_timer(hnd);
416 } else {
417 let (idx, expiry) = self.calc_bucket(millis);
418 self.with_wheel(|w| w.relink(hnd, idx));
419 self.update_next_expiry(expiry);
420 }
421 }
422
423 fn remove_timer(&self, hnd: usize) {
425 self.with_wheel(|w| {
426 if w.unlink(hnd)
427 && let Some(task) = w.timers[hnd].task.take()
428 {
429 task.wake();
430 }
431 });
432 }
433
434 pub(super) fn calc_bucket(self: &Rc<Self>, millis: u64) -> (usize, u64) {
436 self.insert_flags(Flags::RUNNING);
437
438 let since = Instant::now().saturating_duration_since(self.elapsed_time());
442 let delta = to_units(as_millis(since) + millis);
443 self.calc_wheel_index(self.elapsed.get().wrapping_add(delta), delta)
444 }
445
446 fn calc_wheel_index(&self, expires: u64, delta: u64) -> (usize, u64) {
449 for lvl in 0..LVL_DEPTH {
450 if delta < lvl_start(lvl + 1) {
451 return Self::calc_index(expires, lvl);
452 }
453 }
454 Self::calc_index(
456 self.elapsed.get().wrapping_add(WHEEL_TIMEOUT_MAX),
457 LVL_DEPTH - 1,
458 )
459 }
460
461 fn calc_index(expires: u64, lvl: u64) -> (usize, u64) {
463 let expires = (expires + lvl_gran(lvl)) >> lvl_shift(lvl);
467 (
468 (lvl * LVL_SIZE + (expires & LVL_MASK)) as usize,
469 expires << lvl_shift(lvl),
470 )
471 }
472
473 pub(super) fn update_next_expiry(self: &Rc<Self>, expiry: u64) {
475 if expiry < self.next_expiry.get() {
476 self.next_expiry.set(expiry);
477 if self.flags.get().contains(Flags::DRIVER_STARTED) {
478 self.driver.wake();
479 } else {
480 TimerDriver::start(self);
481 }
482 }
483 }
484
485 fn expiry_time(&self, expiry: u64) -> Instant {
487 self.elapsed_time()
488 + Duration::from_millis(to_millis(expiry.saturating_sub(self.elapsed.get())))
489 }
490
491 fn next_pending_bucket(&self, wheel: &Wheel) -> Option<u64> {
493 let mut clk = self.elapsed.get();
494 let mut next = u64::MAX;
495
496 for lvl in 0..LVL_DEPTH {
497 let lvl_clk = clk & LVL_CLK_MASK;
498 let occupied = wheel.occupied[lvl as usize];
499
500 if occupied != 0 {
501 let pos = u64::from(
503 occupied
504 .rotate_right((clk & LVL_MASK) as u32)
505 .trailing_zeros(),
506 );
507 next = cmp::min(next, (clk + pos) << lvl_shift(lvl));
508
509 if pos <= ((LVL_CLK_DIV - lvl_clk) & LVL_CLK_MASK) {
513 break;
514 }
515 }
516
517 clk >>= LVL_CLK_SHIFT;
521 clk += u64::from(lvl_clk != 0);
522 }
523
524 if next < u64::MAX { Some(next) } else { None }
525 }
526
527 fn remove_flags(&self, flags: Flags) {
530 let mut f = self.flags.get();
531 f.remove(flags | Flags::RUNNING);
532 self.flags.set(f);
533 }
534
535 fn stop_lowres(&self) {
537 self.remove_flags(Flags::LOWRES_DRIVER | Flags::LOWRES_TIMER);
538 self.lowres_stime.set(None);
539 }
540
541 fn reset(&self) {
544 self.generation.set(self.generation.get().wrapping_add(1));
545 self.stop_wheel();
546 self.stop_lowres();
547 self.driver.take_local();
548 self.lowres_driver.take_local();
549 }
550
551 fn stop_wheel(&self) {
554 self.remove_flags(Flags::DRIVER_STARTED);
555
556 self.with_wheel(|wheel| {
557 let Wheel {
558 timers,
559 buckets,
560 occupied,
561 callbacks,
562 } = wheel;
563 for bucket in buckets.iter_mut() {
564 for no in bucket.drain() {
565 timers[no].bucket = None;
566 }
567 }
568 *occupied = [0; LVL_DEPTH as usize];
569 if let Some(callbacks) = callbacks {
570 callbacks.ready.clear();
571 for ticket in callbacks.entries.values() {
572 if let Some(state) = ticket.state.upgrade() {
573 state.pending.set(false);
574 }
575 }
576 }
577
578 self.next_expiry.set(u64::MAX);
579 self.elapsed.set(0);
580 self.elapsed_time.set(None);
581 });
582 }
583}
584
585impl Wheel {
586 fn bucket_bit(idx: usize) -> (usize, u64) {
588 (idx / LVL_SIZE as usize, 1 << (idx % LVL_SIZE as usize))
589 }
590
591 pub(super) fn link(&mut self, hnd: usize, idx: usize) {
593 let entry = &mut self.timers[hnd];
594 entry.bucket = Some(idx as u16);
595 entry.bucket_entry = self.buckets[idx].insert(hnd);
596
597 let (lvl, bit) = Self::bucket_bit(idx);
598 self.occupied[lvl] |= bit;
599 }
600
601 pub(super) fn unlink(&mut self, hnd: usize) -> bool {
605 let entry = &mut self.timers[hnd];
606 if let Some(idx) = entry.bucket.take() {
607 let idx = idx as usize;
608 let bucket = &mut self.buckets[idx];
609 bucket.remove(entry.bucket_entry);
610 if bucket.is_empty() {
611 let (lvl, bit) = Self::bucket_bit(idx);
612 self.occupied[lvl] &= !bit;
613 }
614 true
615 } else {
616 false
617 }
618 }
619
620 pub(super) fn relink(&mut self, hnd: usize, idx: usize) {
622 if self.timers[hnd].bucket != Some(idx as u16) {
623 self.unlink(hnd);
624 self.link(hnd, idx);
625 }
626 }
627
628 fn execute_expired_timers(&mut self, mut clk: u64) {
630 for lvl in 0..LVL_DEPTH {
631 let idx = ((clk & LVL_MASK) + lvl * LVL_SIZE) as usize;
632 let bucket = &mut self.buckets[idx];
633 if !bucket.is_empty() {
634 let (lvl, bit) = Self::bucket_bit(idx);
635 self.occupied[lvl] &= !bit;
636 let mut expired = ExpiredTimers {
637 timers: &mut self.timers,
638 entries: bucket.drain(),
639 };
640 for no in expired.entries.by_ref() {
641 let entry = &mut expired.timers[no];
642 entry.bucket = None;
643 if entry.callback {
644 let callbacks = self.callbacks.as_mut().unwrap();
645 callbacks.ready.push(callbacks.entries[&no].clone());
646 } else if let Some(task) = entry.task.take() {
647 task.wake();
648 }
649 }
650 }
651
652 if (clk & LVL_CLK_MASK) != 0 {
655 break;
656 }
657 clk >>= LVL_CLK_SHIFT;
658 }
659 }
660}
661
662#[derive(Default)]
664struct TimerReset;
665
666impl TimerReset {
667 fn register() {
668 ntex_rt::with_item::<TimerReset, _, _>(|_| ());
669 }
670}
671
672impl Drop for TimerReset {
673 fn drop(&mut self) {
674 let _ = TIMER.try_with(|t| t.reset());
676 }
677}
678
679struct TimerDriver {
681 timer: Rc<Timer>,
682 generation: u64,
683 sleep: Delay,
684 armed: Option<Instant>,
686}
687
688impl TimerDriver {
689 fn start(timer: &Rc<Timer>) {
690 timer.insert_flags(Flags::DRIVER_STARTED);
691 TimerReset::register();
692
693 let deadline = timer.expiry_time(timer.next_expiry.get());
694 crate::spawn_detached(TimerDriver {
695 timer: timer.clone(),
696 generation: timer.generation.get(),
697 sleep: Delay::new(deadline.saturating_duration_since(Instant::now())),
698 armed: Some(deadline),
699 });
700 }
701}
702
703impl Drop for TimerDriver {
704 fn drop(&mut self) {
705 if self.timer.generation.get() == self.generation {
706 self.timer.stop_wheel();
707 }
708 }
709}
710
711impl Future for TimerDriver {
712 type Output = ();
713
714 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
715 let this = &mut *self;
716 let timer = &this.timer;
717 if timer.generation.get() != this.generation {
718 return Poll::Ready(());
719 }
720 timer.driver.register(cx.waker());
721
722 let mut now = Instant::now();
723
724 loop {
725 let expiry = timer.next_expiry.get();
726 if expiry == u64::MAX {
727 return Poll::Pending;
729 }
730
731 let deadline = timer.expiry_time(expiry);
732 if deadline > now {
733 if this.armed != Some(deadline) {
734 this.armed = Some(deadline);
735 this.sleep.reset(deadline.saturating_duration_since(now));
736 }
737 if Pin::new(&mut this.sleep).poll(cx).is_pending() {
738 return Poll::Pending;
739 }
740 if deadline > now {
741 this.armed = None;
743 continue;
744 }
745 }
746
747 timer.elapsed.set(expiry);
750 timer.elapsed_time.set(Some(deadline));
751
752 let (next, callbacks) = timer.with_wheel(|w| {
753 w.execute_expired_timers(expiry);
754 let callbacks = w.callbacks.as_mut().and_then(|callbacks| {
755 if callbacks.ready.is_empty() {
756 None
757 } else {
758 Some(mem::take(&mut callbacks.ready))
759 }
760 });
761 (timer.next_pending_bucket(w), callbacks)
762 });
763
764 if let Some(next) = next {
765 timer.next_expiry.set(next);
766 } else {
767 timer.next_expiry.set(u64::MAX);
768 timer.elapsed_time.set(None);
769 }
770
771 if let Some(mut callbacks) = callbacks {
772 for ticket in callbacks.drain(..) {
773 if timer.generation.get() != this.generation {
774 return Poll::Ready(());
775 }
776 if ticket.generation == this.generation
777 && let Some(state) = ticket.state.upgrade()
778 && state.arm.get() == ticket.arm
779 && state.pending.replace(false)
780 {
781 (state.callback)();
782 }
783 }
784 if timer.generation.get() != this.generation {
786 return Poll::Ready(());
787 }
788 timer.with_wheel(|wheel| wheel.callbacks.as_mut().unwrap().ready = callbacks);
789 now = Instant::now();
790 }
791 }
792 }
793}
794
795struct LowresTimerDriver {
797 timer: Rc<Timer>,
798 generation: u64,
799 sleep: Delay,
800}
801
802impl LowresTimerDriver {
803 fn start(timer: &Rc<Timer>) {
804 timer.insert_flags(Flags::LOWRES_DRIVER);
805 TimerReset::register();
806
807 crate::spawn_detached(LowresTimerDriver {
808 timer: timer.clone(),
809 generation: timer.generation.get(),
810 sleep: Delay::new(LOWRES_RESOLUTION),
811 });
812 }
813}
814
815impl Drop for LowresTimerDriver {
816 fn drop(&mut self) {
817 if self.timer.generation.get() == self.generation {
818 self.timer.stop_lowres();
819 }
820 }
821}
822
823impl Future for LowresTimerDriver {
824 type Output = ();
825
826 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
827 let this = &mut *self;
828 let timer = &this.timer;
829 if timer.generation.get() != this.generation {
830 return Poll::Ready(());
831 }
832 timer.lowres_driver.register(cx.waker());
833
834 let mut flags = timer.flags.get();
836 if !flags.contains(Flags::LOWRES_TIMER) {
837 flags.insert(Flags::LOWRES_TIMER);
838 timer.flags.set(flags);
839 this.sleep.reset(LOWRES_RESOLUTION);
840 }
841
842 if Pin::new(&mut this.sleep).poll(cx).is_ready() {
843 timer.lowres_stime.set(None);
844 flags.remove(Flags::LOWRES_TIMER);
845 timer.flags.set(flags);
846 }
847 Poll::Pending
848 }
849}
850
851#[cfg(test)]
852mod tests {
853 use std::cell::RefCell;
854 use std::panic::{AssertUnwindSafe, catch_unwind};
855 use std::sync::Arc;
856 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
857 use std::task::{Context, RawWaker, RawWakerVTable, Wake, Waker};
858
859 use super::*;
860 use crate::future::OnDropFn;
861 use crate::time::{CallbackTimer, Millis, interval, sleep};
862
863 #[derive(Default)]
864 struct InPlaceWaker {
865 wakes: AtomicUsize,
866 delay: Duration,
867 panic_on_wake: bool,
868 }
869
870 impl Wake for InPlaceWaker {
871 fn wake(self: Arc<Self>) {
872 TIMER.with(|timer| {
873 let wheel = timer.wheel.take();
874 let held = wheel.is_none();
875 timer.wheel.set(wheel);
876 assert!(held, "waker must run in place while the wheel is held");
877 });
878 let previous = self.wakes.fetch_add(1, Ordering::Relaxed);
879 assert!(!self.panic_on_wake, "notification");
880 if previous == 0 && !self.delay.is_zero() {
881 std::thread::sleep(self.delay);
882 }
883 }
884 }
885
886 fn timer_state() -> Rc<Timer> {
887 TIMER.with(|timer| {
888 timer.reset();
889 timer.insert_flags(Flags::DRIVER_STARTED);
891 timer.clone()
892 })
893 }
894
895 #[test]
901 fn debug_callback_timer() {
902 let timer = timer_state();
903 let calls = Rc::new(Cell::new(0));
904 let captured = calls.clone();
905 let callback = CallbackTimer::new(Millis(10_000), move || {
906 captured.set(captured.get() + 1);
907 });
908 let expected = format!("CallbackTimer {{ handle: {}, .. }}", callback.hnd);
909 timer.with_wheel(|_| assert_eq!(format!("{callback:?}"), expected));
910 assert!(!callback.is_elapsed());
911 callback.cancel();
912 assert_eq!(format!("{callback:?}"), expected);
913 assert!(callback.is_elapsed());
914 assert_eq!(calls.get(), 0);
915 }
916
917 fn timer_driver(timer: &Rc<Timer>) -> TimerDriver {
918 TimerDriver {
919 timer: timer.clone(),
920 generation: timer.generation.get(),
921 sleep: Delay::new(Duration::ZERO),
922 armed: None,
923 }
924 }
925
926 fn make_due(timer: &Timer) {
927 timer.elapsed_time.set(Some(
928 Instant::now().checked_sub(Duration::from_secs(1)).unwrap(),
929 ));
930 }
931
932 #[derive(Debug)]
933 struct NoopNotify;
934
935 impl ntex_rt::Notify for NoopNotify {
936 fn notify(&self) -> std::io::Result<()> {
937 Ok(())
938 }
939 }
940
941 #[test]
947 fn test_local_waker_registration() {
948 struct Registration {
949 inner: Waker,
950 clones: AtomicUsize,
951 panic_on_clone: AtomicBool,
952 }
953
954 static VTABLE: RawWakerVTable = RawWakerVTable::new(
956 |data| unsafe {
957 let state = &*data.cast::<Registration>();
958 assert!(!state.panic_on_clone.load(Ordering::Relaxed), "clone");
959 state.clones.fetch_add(1, Ordering::Relaxed);
960 Arc::increment_strong_count(data.cast::<Registration>());
961 RawWaker::new(data, &VTABLE)
962 },
963 |data| unsafe {
964 Arc::from_raw(data.cast::<Registration>())
965 .inner
966 .wake_by_ref();
967 },
968 |data| unsafe {
969 (*data.cast::<Registration>()).inner.wake_by_ref();
970 },
971 |data| unsafe {
972 drop(Arc::from_raw(data.cast::<Registration>()));
973 },
974 );
975
976 let wrap = |task: &Arc<InPlaceWaker>| {
977 let state = Arc::new(Registration {
978 inner: Waker::from(task.clone()),
979 clones: AtomicUsize::new(0),
980 panic_on_clone: AtomicBool::new(false),
981 });
982 let waker = unsafe {
983 Waker::from_raw(RawWaker::new(Arc::into_raw(state.clone()).cast(), &VTABLE))
984 };
985 (state, waker)
986 };
987
988 let timer = timer_state();
989 let handle = TimerHandle::new(10_000);
990 let old_task = Arc::new(InPlaceWaker::default());
991 let new_task = Arc::new(InPlaceWaker::default());
992 let (old, old_waker) = wrap(&old_task);
993 let (new, new_waker) = wrap(&new_task);
994 let mut old_cx = Context::from_waker(&old_waker);
995 let mut new_cx = Context::from_waker(&new_waker);
996
997 assert!(handle.poll_elapsed(&mut old_cx).is_pending());
998 handle.reset(20_000);
999 assert!(handle.poll_elapsed(&mut old_cx).is_pending());
1000 assert_eq!(old.clones.load(Ordering::Relaxed), 1);
1001 assert_eq!(Arc::strong_count(&old), 3);
1002
1003 new.panic_on_clone.store(true, Ordering::Relaxed);
1004 assert!(catch_unwind(AssertUnwindSafe(|| handle.poll_elapsed(&mut new_cx))).is_err());
1005 timer.with_wheel(|wheel| {
1006 assert!(
1007 wheel.timers[handle.0.get()]
1008 .task
1009 .as_ref()
1010 .unwrap()
1011 .will_wake(&old_waker)
1012 );
1013 });
1014 assert_eq!(Arc::strong_count(&old), 3);
1015 assert_eq!(Arc::strong_count(&new), 2);
1016
1017 new.panic_on_clone.store(false, Ordering::Relaxed);
1018 assert!(handle.poll_elapsed(&mut new_cx).is_pending());
1019 assert!(handle.poll_elapsed(&mut new_cx).is_pending());
1020 assert_eq!(new.clones.load(Ordering::Relaxed), 1);
1021 assert_eq!(Arc::strong_count(&old), 2);
1022 assert_eq!(Arc::strong_count(&new), 3);
1023
1024 timer.with_wheel(|wheel| {
1025 wheel.relink(handle.0.get(), 3);
1026 wheel.execute_expired_timers(3);
1027 });
1028 assert!(handle.poll_elapsed(&mut new_cx).is_ready());
1029 assert_eq!(new.clones.load(Ordering::Relaxed), 1);
1030 assert_eq!(new_task.wakes.load(Ordering::Relaxed), 1);
1031 assert_eq!(old_task.wakes.load(Ordering::Relaxed), 0);
1032 assert_eq!(Arc::strong_count(&new), 2);
1033
1034 handle.reset(10_000);
1035 assert!(handle.poll_elapsed(&mut old_cx).is_pending());
1036 handle.reset(0);
1037 assert!(handle.is_elapsed());
1038 assert_eq!(old_task.wakes.load(Ordering::Relaxed), 1);
1039 assert_eq!(Arc::strong_count(&old), 2);
1040
1041 handle.reset(10_000);
1042 assert!(handle.poll_elapsed(&mut old_cx).is_pending());
1043 drop(handle);
1044 assert_eq!(old_task.wakes.load(Ordering::Relaxed), 1);
1045 assert_eq!(old.clones.load(Ordering::Relaxed), 3);
1046 assert_eq!(Arc::strong_count(&old), 2);
1047 }
1048
1049 #[test]
1055 fn test_local_waker_native_replacement() {
1056 let timer = timer_state();
1057 let rt = ntex_rt::Runtime::new(Box::new(NoopNotify));
1058 let handle = Rc::new(TimerHandle::new(10_000));
1059 let first_waker = Rc::new(Cell::new(None));
1060 let (first_handle, saved) = (handle.clone(), first_waker.clone());
1061 let first = rt.spawn(std::future::poll_fn(move |cx| {
1062 saved.set(Some(cx.waker().clone()));
1063 first_handle.poll_elapsed(cx)
1064 }));
1065 rt.poll();
1066
1067 let second_handle = handle.clone();
1068 let second = rt.spawn(std::future::poll_fn(move |cx| {
1069 second_handle.poll_elapsed(cx)
1070 }));
1071 rt.poll();
1072 timer.with_wheel(|wheel| {
1073 wheel.relink(handle.0.get(), 3);
1074 wheel.execute_expired_timers(3);
1075 });
1076 rt.poll();
1077 assert!(!first.is_finished());
1078 assert!(second.is_finished());
1079
1080 handle.reset(10_000);
1081 first_waker.take().unwrap().wake();
1082 rt.poll();
1083 assert!(!first.is_finished());
1084 handle.reset(0);
1085 rt.poll();
1086 assert!(first.is_finished());
1087 assert_eq!(Rc::strong_count(&handle), 1);
1088 drop(rt);
1089 first_waker.take().unwrap().wake();
1090 }
1091
1092 #[test]
1098 fn test_local_waker_runtime_shutdown() {
1099 for reuse in [false, true] {
1100 let timer = timer_state();
1101 let rt = ntex_rt::Runtime::new(Box::new(NoopNotify));
1102 let handle = Rc::new(TimerHandle::new(10_000));
1103 let (task_timer, task_handle) = (timer.clone(), handle.clone());
1104 let task = rt.spawn(std::future::poll_fn(move |cx| {
1105 task_timer.driver.register(cx.waker());
1106 task_timer.lowres_driver.register(cx.waker());
1107 task_handle.poll_elapsed(cx)
1108 }));
1109 rt.poll();
1110 drop(rt);
1111 assert!(task.is_finished());
1112 assert_eq!(Rc::strong_count(&handle), 1);
1113 drop(task);
1114
1115 timer.reset();
1116 assert!(handle.is_elapsed());
1117 assert!(!timer.driver.is_set());
1118 assert!(!timer.lowres_driver.is_set());
1119 timer.with_wheel(|wheel| {
1120 assert!(wheel.timers[handle.0.get()].task.is_some());
1121 });
1122
1123 if reuse {
1124 timer.insert_flags(Flags::DRIVER_STARTED);
1125 handle.reset(10_000);
1126 let rt = ntex_rt::Runtime::new(Box::new(NoopNotify));
1127 let task_handle = handle.clone();
1128 let task = rt.spawn(std::future::poll_fn(move |cx| task_handle.poll_elapsed(cx)));
1129 rt.poll();
1130 assert!(!task.is_finished());
1131 handle.elapse();
1132 rt.poll();
1133 assert!(task.is_finished());
1134 assert_eq!(Rc::strong_count(&handle), 1);
1135 }
1136 drop(handle);
1137 timer.with_wheel(|wheel| assert_eq!(wheel.timers.len(), 1));
1138 }
1139 }
1140
1141 #[test]
1147 fn test_local_waker_in_next_system() {
1148 struct Wrapped {
1149 inner: Waker,
1150 wakes: Arc<AtomicUsize>,
1151 }
1152
1153 impl Wake for Wrapped {
1154 fn wake(self: Arc<Self>) {
1155 self.wakes.fetch_add(1, Ordering::Relaxed);
1156 self.inner.wake_by_ref();
1157 }
1158 }
1159
1160 std::thread::spawn(|| {
1161 let mut handle = None::<TimerHandle>;
1162 for wrapped in [false, true, false] {
1163 let notifications = Arc::new(AtomicUsize::new(0));
1164 let count = notifications.clone();
1165 handle = Some(
1166 ntex::rt::System::build()
1167 .build(ntex::rt::DefaultRuntime)
1168 .block_on(async move {
1169 let handle = if let Some(handle) = handle {
1170 assert!(handle.is_elapsed());
1171 handle.reset(10_000);
1172 handle
1173 } else {
1174 TimerHandle::new(10_000)
1175 };
1176 std::future::poll_fn(|cx| {
1177 let waker = if wrapped {
1178 Waker::from(Arc::new(Wrapped {
1179 inner: cx.waker().clone(),
1180 wakes: count.clone(),
1181 }))
1182 } else {
1183 cx.waker().clone()
1184 };
1185 let cx = &mut Context::from_waker(&waker);
1186 assert!(handle.poll_elapsed(cx).is_pending());
1187 handle.reset(0);
1188 assert!(handle.poll_elapsed(cx).is_ready());
1189 handle.reset(10_000);
1190 assert!(handle.poll_elapsed(cx).is_pending());
1191 Poll::Ready(())
1192 })
1193 .await;
1194 handle
1195 }),
1196 );
1197 assert!(handle.as_ref().unwrap().is_elapsed());
1198 assert_eq!(notifications.load(Ordering::Relaxed), usize::from(wrapped));
1199 }
1200 })
1201 .join()
1202 .unwrap();
1203 }
1204
1205 #[ntex::test]
1211 async fn test_callback_timer() {
1212 let calls = Rc::new(Cell::new(0));
1213 let count = calls.clone();
1214 let callback = crate::time::CallbackTimer::new(Millis::ZERO, move || {
1215 count.set(count.get() + 1);
1216 });
1217 assert!(!callback.is_elapsed());
1218 assert_eq!(calls.get(), 0);
1219 callback.reset(Millis(10_000));
1220 callback.cancel();
1221 assert!(callback.is_elapsed());
1222 sleep(Millis(50)).await;
1223 assert_eq!(calls.get(), 0);
1224
1225 for expected in 1..=2 {
1226 callback.reset(Millis::ZERO);
1227 assert!(!callback.is_elapsed());
1228 sleep(Millis(50)).await;
1229 assert!(callback.is_elapsed());
1230 assert_eq!(calls.get(), expected);
1231 }
1232 }
1233
1234 #[test]
1240 fn test_callback_stale_tickets() {
1241 let timer = timer_state();
1242 let calls = Rc::new(Cell::new(0));
1243 let count = calls.clone();
1244 let cancelled = CallbackTimer::new(Millis(1), move || count.set(count.get() + 1));
1245 let count = calls.clone();
1246 let reset = CallbackTimer::new(Millis(1), move || count.set(count.get() + 1));
1247 let capture = Rc::new(Cell::new(0));
1248 let weak = Rc::downgrade(&capture);
1249 let dropped = CallbackTimer::new(Millis(1), move || capture.set(1));
1250 let old_slot = dropped.hnd;
1251 timer.with_wheel(|wheel| {
1252 for handle in [&cancelled, &reset, &dropped] {
1253 wheel.relink(handle.hnd.get(), 3);
1254 }
1255 wheel.execute_expired_timers(3);
1256 });
1257 assert!(cancelled.is_elapsed());
1258 assert!(reset.is_elapsed());
1259 assert!(dropped.is_elapsed());
1260 assert_eq!(calls.get(), 0);
1261 cancelled.cancel();
1262 reset.reset(Millis(10_000));
1263 drop(dropped);
1264 assert!(
1265 weak.upgrade().is_none(),
1266 "queued tickets must not retain captures"
1267 );
1268 let count = calls.clone();
1269 let replacement = CallbackTimer::new(Millis(10_000), move || count.set(count.get() + 100));
1270 assert_eq!(replacement.hnd, old_slot);
1271
1272 make_due(&timer);
1273 let mut driver = timer_driver(&timer);
1274 assert!(
1275 Pin::new(&mut driver)
1276 .poll(&mut Context::from_waker(Waker::noop()))
1277 .is_pending()
1278 );
1279 assert_eq!(calls.get(), 0);
1280 assert!(!reset.is_elapsed());
1281 assert!(!replacement.is_elapsed());
1282 timer.elapsed_time.set(Some(
1283 Instant::now().checked_sub(Duration::from_secs(20)).unwrap(),
1284 ));
1285 for _ in 0..2 {
1286 assert!(
1287 Pin::new(&mut driver)
1288 .poll(&mut Context::from_waker(Waker::noop()))
1289 .is_pending()
1290 );
1291 assert_eq!(calls.get(), 101);
1292 }
1293 }
1294
1295 #[test]
1301 fn test_callback_self_rearm_and_cross_cancel() {
1302 let timer = timer_state();
1303 let calls = Rc::new(Cell::new(0));
1304 let handles = Rc::new(RefCell::new(Vec::<CallbackTimer>::new()));
1305 for index in 0..2 {
1306 let count = calls.clone();
1307 let weak = Rc::downgrade(&handles);
1308 let callback = CallbackTimer::new(Millis(1), move || {
1309 count.set(count.get() + 1);
1310 let handles = weak.upgrade().unwrap();
1311 let handles = handles.borrow();
1312 assert!(handles[index].is_elapsed());
1313 handles[1 - index].cancel();
1314 handles[index].reset(Millis(10_000));
1315 });
1316 handles.borrow_mut().push(callback);
1317 }
1318 timer.with_wheel(|wheel| {
1319 for handle in handles.borrow().iter() {
1320 wheel.relink(handle.hnd.get(), 1);
1321 }
1322 });
1323 make_due(&timer);
1324 let mut driver = timer_driver(&timer);
1325 assert!(
1326 Pin::new(&mut driver)
1327 .poll(&mut Context::from_waker(Waker::noop()))
1328 .is_pending()
1329 );
1330 assert_eq!(calls.get(), 1);
1331 assert_eq!(
1332 handles.borrow().iter().filter(|h| !h.is_elapsed()).count(),
1333 1
1334 );
1335 timer.elapsed_time.set(Some(
1336 Instant::now().checked_sub(Duration::from_secs(20)).unwrap(),
1337 ));
1338 for _ in 0..2 {
1339 assert!(
1340 Pin::new(&mut driver)
1341 .poll(&mut Context::from_waker(Waker::noop()))
1342 .is_pending()
1343 );
1344 assert_eq!(calls.get(), 2);
1345 }
1346 }
1347
1348 #[test]
1354 fn test_callback_capture_drop_schedules_timers() {
1355 for active in [false, true] {
1356 let timer = timer_state();
1357 let released = Rc::new(Cell::new(false));
1358 let finished = Rc::new(Cell::new(false));
1359 let reset_calls = Rc::new(Cell::new(0));
1360 let new_calls = Rc::new(Cell::new(0));
1361 let count = reset_calls.clone();
1362 let reset = Rc::new(CallbackTimer::new(Millis(20_000), move || {
1363 count.set(count.get() + 1);
1364 }));
1365 let cancelled = Rc::new(CallbackTimer::new(Millis(20_000), || {
1366 panic!("cancelled callback");
1367 }));
1368 let replacement = Rc::new(RefCell::new(None::<CallbackTimer>));
1369 let capture = {
1370 let reset = reset.clone();
1371 let cancelled = cancelled.clone();
1372 let replacement = replacement.clone();
1373 let new_calls = new_calls.clone();
1374 let released = released.clone();
1375 let finished = finished.clone();
1376 OnDropFn::new(move || {
1377 assert!(!active || finished.get());
1378 let ordinary = TimerHandle::new(10_000);
1379 ordinary.reset(0);
1380 drop(ordinary);
1381 cancelled.cancel();
1382 reset.reset(Millis(10_000));
1383 *replacement.borrow_mut() =
1384 Some(CallbackTimer::new(Millis(10_000), move || {
1385 new_calls.set(new_calls.get() + 1);
1386 }));
1387 released.set(true);
1388 })
1389 };
1390 let handle = Rc::new(RefCell::new(None::<CallbackTimer>));
1391 let weak = Rc::downgrade(&handle);
1392 let was_released = released.clone();
1393 *handle.borrow_mut() = Some(CallbackTimer::new(Millis(1), move || {
1394 let _capture = &capture;
1395 assert!(active, "dropped queued callback must not run");
1396 drop(weak.upgrade().unwrap().borrow_mut().take());
1397 assert!(!was_released.get());
1398 finished.set(true);
1399 }));
1400 let old_slot = handle.borrow().as_ref().unwrap().hnd;
1401 if !active {
1402 timer.with_wheel(|wheel| {
1403 wheel.relink(old_slot.get(), 1);
1404 wheel.execute_expired_timers(1);
1405 });
1406 drop(handle.borrow_mut().take());
1407 assert!(released.get());
1408 }
1409 make_due(&timer);
1410 let mut driver = timer_driver(&timer);
1411 assert!(
1412 Pin::new(&mut driver)
1413 .poll(&mut Context::from_waker(Waker::noop()))
1414 .is_pending()
1415 );
1416 assert!(released.get());
1417 assert!(handle.borrow().is_none());
1418 assert!(cancelled.is_elapsed());
1419 assert!(!reset.is_elapsed());
1420 assert_eq!(replacement.borrow().as_ref().unwrap().hnd, old_slot);
1421 assert!(!replacement.borrow().as_ref().unwrap().is_elapsed());
1422 assert_eq!((reset_calls.get(), new_calls.get()), (0, 0));
1423
1424 timer.elapsed_time.set(Some(
1425 Instant::now().checked_sub(Duration::from_secs(20)).unwrap(),
1426 ));
1427 for _ in 0..2 {
1428 assert!(
1429 Pin::new(&mut driver)
1430 .poll(&mut Context::from_waker(Waker::noop()))
1431 .is_pending()
1432 );
1433 assert_eq!((reset_calls.get(), new_calls.get()), (1, 1));
1434 }
1435 }
1436 }
1437
1438 #[test]
1444 fn test_callback_capture_drop_resets_runtime() {
1445 let timer = timer_state();
1446 let new_calls = Rc::new(Cell::new(0));
1447 let replacement = Rc::new(RefCell::new(None::<CallbackTimer>));
1448 let capture = {
1449 let timer = timer.clone();
1450 let new_calls = new_calls.clone();
1451 let replacement = replacement.clone();
1452 OnDropFn::new(move || {
1453 timer.reset();
1454 timer.insert_flags(Flags::DRIVER_STARTED);
1455 let callback = CallbackTimer::new(Millis(1), move || {
1456 new_calls.set(new_calls.get() + 1);
1457 });
1458 timer.with_wheel(|wheel| {
1459 wheel.relink(callback.hnd.get(), 1);
1460 wheel.execute_expired_timers(1);
1461 });
1462 *replacement.borrow_mut() = Some(callback);
1463 })
1464 };
1465 let handle = Rc::new(RefCell::new(None::<CallbackTimer>));
1466 let weak = Rc::downgrade(&handle);
1467 *handle.borrow_mut() = Some(CallbackTimer::new(Millis(1), move || {
1468 let _capture = &capture;
1469 drop(weak.upgrade().unwrap().borrow_mut().take());
1470 }));
1471 make_due(&timer);
1472 let mut old_driver = timer_driver(&timer);
1473 assert!(
1474 Pin::new(&mut old_driver)
1475 .poll(&mut Context::from_waker(Waker::noop()))
1476 .is_ready()
1477 );
1478 assert!(handle.borrow().is_none());
1479 assert!(replacement.borrow().as_ref().unwrap().is_elapsed());
1480 assert_eq!(new_calls.get(), 0);
1481 drop(old_driver);
1482
1483 make_due(&timer);
1484 let mut driver = timer_driver(&timer);
1485 for _ in 0..2 {
1486 assert!(
1487 Pin::new(&mut driver)
1488 .poll(&mut Context::from_waker(Waker::noop()))
1489 .is_pending()
1490 );
1491 assert_eq!(new_calls.get(), 1);
1492 }
1493 }
1494
1495 #[test]
1501 fn test_callback_refreshes_time() {
1502 let timer = timer_state();
1503 let calls = Rc::new(Cell::new(0));
1504 let handles = [1, 32].map(|millis| {
1505 let calls = calls.clone();
1506 CallbackTimer::new(Millis(millis), move || {
1507 let previous = calls.replace(calls.get() + 1);
1508 if previous == 0 {
1509 std::thread::sleep(Duration::from_millis(64));
1510 }
1511 })
1512 });
1513 timer.with_wheel(|wheel| {
1514 wheel.relink(handles[0].hnd.get(), 1);
1515 wheel.relink(handles[1].hnd.get(), 3);
1516 });
1517 timer.elapsed_time.set(Some(
1518 Instant::now()
1519 .checked_sub(Duration::from_millis(32))
1520 .unwrap(),
1521 ));
1522 let mut driver = timer_driver(&timer);
1523 assert!(
1524 Pin::new(&mut driver)
1525 .poll(&mut Context::from_waker(Waker::noop()))
1526 .is_pending()
1527 );
1528 assert_eq!(calls.get(), 2);
1529 assert!(handles.iter().all(CallbackTimer::is_elapsed));
1530 }
1531
1532 #[test]
1538 fn test_callback_panic_after_rearm_cleanup() {
1539 let timer = timer_state();
1540 let callback = Rc::new_cyclic(|weak: &std::rc::Weak<CallbackTimer>| {
1541 let weak = weak.clone();
1542 CallbackTimer::new(Millis(1), move || {
1543 let callback = weak.upgrade().unwrap();
1544 callback.reset(Millis(10_000));
1545 panic!("callback");
1546 })
1547 });
1548 let later = CallbackTimer::new(Millis(10_000), || panic!("not due"));
1549 let ordinary = TimerHandle::new(10_000);
1550 make_due(&timer);
1551 let mut driver = timer_driver(&timer);
1552 assert!(
1553 catch_unwind(AssertUnwindSafe(|| {
1554 let _ = Pin::new(&mut driver).poll(&mut Context::from_waker(Waker::noop()));
1555 }))
1556 .is_err()
1557 );
1558 assert!(!callback.is_elapsed());
1559 drop(driver);
1560 assert!(callback.is_elapsed());
1561 assert!(!callback.state.pending.get());
1562 assert!(later.is_elapsed());
1563 assert!(ordinary.is_elapsed());
1564 assert!(!later.state.pending.get());
1565 timer.with_wheel(|wheel| {
1566 assert!(wheel.buckets.iter().all(Slab::is_empty));
1567 assert_eq!(wheel.occupied, [0; LVL_DEPTH as usize]);
1568 assert!(wheel.callbacks.as_ref().unwrap().ready.is_empty());
1569 });
1570 }
1571
1572 #[test]
1578 fn test_callback_runtime_reset_during_delivery() {
1579 let timer = timer_state();
1580 let calls = Rc::new(Cell::new(0));
1581 let new_calls = Rc::new(Cell::new(0));
1582 let replacement = Rc::new(RefCell::new(None::<CallbackTimer>));
1583 let handles = [0, 1].map(|_| {
1584 let timer = timer.clone();
1585 let calls = calls.clone();
1586 let new_calls = new_calls.clone();
1587 let replacement = replacement.clone();
1588 CallbackTimer::new(Millis(1), move || {
1589 calls.set(calls.get() + 1);
1590 timer.reset();
1591 timer.insert_flags(Flags::DRIVER_STARTED);
1592 let new_calls = new_calls.clone();
1593 *replacement.borrow_mut() = Some(CallbackTimer::new(Millis(1), move || {
1594 new_calls.set(new_calls.get() + 1);
1595 }));
1596 })
1597 });
1598 timer.with_wheel(|wheel| {
1599 for handle in &handles {
1600 wheel.relink(handle.hnd.get(), 1);
1601 }
1602 });
1603 make_due(&timer);
1604 let mut old_driver = timer_driver(&timer);
1605 assert!(
1606 Pin::new(&mut old_driver)
1607 .poll(&mut Context::from_waker(Waker::noop()))
1608 .is_ready()
1609 );
1610 assert_eq!(calls.get(), 1);
1611 assert!(handles.iter().all(CallbackTimer::is_elapsed));
1612 drop(old_driver);
1613 assert!(!replacement.borrow().as_ref().unwrap().is_elapsed());
1614 make_due(&timer);
1615 let mut driver = timer_driver(&timer);
1616 assert!(
1617 Pin::new(&mut driver)
1618 .poll(&mut Context::from_waker(Waker::noop()))
1619 .is_pending()
1620 );
1621 assert_eq!(new_calls.get(), 1);
1622 }
1623
1624 #[test]
1630 fn test_callback_mixed_bucket_waker_panic() {
1631 for panic_position in 0..3 {
1632 let timer = timer_state();
1633 let calls = Rc::new(Cell::new(0));
1634 let callbacks = [0, 1].map(|_| {
1635 let calls = calls.clone();
1636 CallbackTimer::new(Millis(10_000), move || calls.set(calls.get() + 1))
1637 });
1638 let ordinary = TimerHandle::new(10_000);
1639 let task = Arc::new(InPlaceWaker {
1640 panic_on_wake: true,
1641 ..InPlaceWaker::default()
1642 });
1643 let waker = Waker::from(task.clone());
1644 assert!(
1645 ordinary
1646 .poll_elapsed(&mut Context::from_waker(&waker))
1647 .is_pending()
1648 );
1649 timer.with_wheel(|wheel| {
1650 let mut entries = [
1652 callbacks[0].hnd.get(),
1653 ordinary.0.get(),
1654 callbacks[1].hnd.get(),
1655 ];
1656 entries.swap(1, panic_position);
1657 for no in entries {
1658 wheel.unlink(no);
1659 }
1660 wheel.buckets[3] = Slab::new();
1661 for no in entries {
1662 wheel.link(no, 3);
1663 }
1664 });
1665 timer.next_expiry.set(3);
1666 make_due(&timer);
1667 let mut driver = timer_driver(&timer);
1668 assert!(
1669 catch_unwind(AssertUnwindSafe(|| {
1670 let _ = Pin::new(&mut driver).poll(&mut Context::from_waker(Waker::noop()));
1671 }))
1672 .is_err()
1673 );
1674 assert_eq!(task.wakes.load(Ordering::Relaxed), 1);
1675 assert_eq!(calls.get(), 0);
1676 assert!(ordinary.is_elapsed());
1677 assert!(callbacks.iter().all(CallbackTimer::is_elapsed));
1678 timer.with_wheel(|wheel| {
1679 assert!(wheel.buckets.iter().all(Slab::is_empty));
1680 assert_eq!(wheel.occupied, [0; LVL_DEPTH as usize]);
1681 assert_eq!(
1682 wheel.callbacks.as_ref().unwrap().ready.len(),
1683 panic_position
1684 );
1685 });
1686 drop(driver);
1687 assert!(
1688 callbacks
1689 .iter()
1690 .all(|callback| !callback.state.pending.get())
1691 );
1692 timer.with_wheel(|wheel| {
1693 assert!(wheel.callbacks.as_ref().unwrap().ready.is_empty());
1694 });
1695
1696 timer.insert_flags(Flags::DRIVER_STARTED);
1697 callbacks[0].reset(Millis::ZERO);
1698 make_due(&timer);
1699 let mut driver = timer_driver(&timer);
1700 for _ in 0..2 {
1701 assert!(
1702 Pin::new(&mut driver)
1703 .poll(&mut Context::from_waker(Waker::noop()))
1704 .is_pending()
1705 );
1706 assert_eq!(calls.get(), 1);
1707 }
1708 }
1709 }
1710
1711 #[test]
1717 fn test_callback_reuse_in_next_system() {
1718 std::thread::spawn(|| {
1719 let calls = Rc::new(Cell::new(0));
1720 let mut callback = None::<CallbackTimer>;
1721 for expected in 1..=2 {
1722 let calls = calls.clone();
1723 callback = Some(
1724 ntex::rt::System::build()
1725 .build(ntex::rt::DefaultRuntime)
1726 .block_on(async move {
1727 let callback = if let Some(callback) = callback {
1728 assert!(callback.is_elapsed());
1729 sleep(Millis(50)).await;
1730 assert_eq!(calls.get(), expected - 1);
1731 callback.reset(Millis::ZERO);
1732 callback
1733 } else {
1734 let calls = calls.clone();
1735 CallbackTimer::new(Millis::ZERO, move || {
1736 calls.set(calls.get() + 1);
1737 })
1738 };
1739 sleep(Millis(50)).await;
1740 assert_eq!(calls.get(), expected);
1741 callback.reset(Millis(10_000));
1742 callback
1743 }),
1744 );
1745 assert!(callback.as_ref().unwrap().is_elapsed());
1746 }
1747 })
1748 .join()
1749 .unwrap();
1750 }
1751
1752 #[test]
1758 fn test_wheel_access_restored_on_unwind() {
1759 let timer = Timer::new();
1760 assert!(
1761 catch_unwind(AssertUnwindSafe(|| {
1762 timer.with_wheel(|wheel| {
1763 wheel.timers.insert(entry());
1764 panic!("wheel operation");
1765 });
1766 }))
1767 .is_err()
1768 );
1769 timer.with_wheel(|wheel| assert_eq!(wheel.timers.len(), 2));
1770 }
1771
1772 #[test]
1778 fn test_wake_in_place() {
1779 let timer = timer_state();
1780 let task = Arc::new(InPlaceWaker::default());
1781 let waker = Waker::from(task.clone());
1782 let mut cx = Context::from_waker(&waker);
1783 for reset in [false, true] {
1784 let handle = TimerHandle::new(10_000);
1785 assert!(handle.poll_elapsed(&mut cx).is_pending());
1786 if reset {
1787 handle.reset(0);
1788 } else {
1789 handle.elapse();
1790 }
1791 assert!(handle.is_elapsed());
1792 }
1793 let handles = [TimerHandle::new(1), TimerHandle::new(1)];
1794 for handle in &handles {
1795 assert!(handle.poll_elapsed(&mut cx).is_pending());
1796 }
1797 timer.elapsed_time.set(Some(
1798 Instant::now().checked_sub(Duration::from_secs(20)).unwrap(),
1799 ));
1800 let mut driver = timer_driver(&timer);
1801 assert!(
1802 Pin::new(&mut driver)
1803 .poll(&mut Context::from_waker(Waker::noop()))
1804 .is_pending()
1805 );
1806 assert!(handles.iter().all(TimerHandle::is_elapsed));
1807 assert_eq!(task.wakes.load(Ordering::Relaxed), 4);
1808 assert_eq!(Arc::strong_count(&task), 2);
1809 }
1810
1811 #[test]
1817 fn test_dispatch_uses_one_time_sample_for_wakers() {
1818 let timer = timer_state();
1819 let handles = [TimerHandle::new(1), TimerHandle::new(32)];
1820 timer.with_wheel(|wheel| wheel.relink(handles[1].0.get(), 3));
1821 let task = Arc::new(InPlaceWaker {
1822 delay: Duration::from_millis(64),
1823 ..InPlaceWaker::default()
1824 });
1825 let waker = Waker::from(task.clone());
1826 for handle in &handles {
1827 assert!(
1828 handle
1829 .poll_elapsed(&mut Context::from_waker(&waker))
1830 .is_pending()
1831 );
1832 }
1833 timer.elapsed_time.set(Some(
1834 Instant::now()
1835 .checked_sub(Duration::from_millis(32))
1836 .unwrap(),
1837 ));
1838 let mut driver = timer_driver(&timer);
1839 assert!(
1840 Pin::new(&mut driver)
1841 .poll(&mut Context::from_waker(Waker::noop()))
1842 .is_pending()
1843 );
1844 assert!(handles[0].is_elapsed());
1845 assert!(!handles[1].is_elapsed());
1846 assert_eq!(task.wakes.load(Ordering::Relaxed), 1);
1847 assert!(
1848 Pin::new(&mut driver)
1849 .poll(&mut Context::from_waker(Waker::noop()))
1850 .is_pending()
1851 );
1852 assert!(handles[1].is_elapsed());
1853 assert_eq!(task.wakes.load(Ordering::Relaxed), 2);
1854 }
1855
1856 #[test]
1862 fn test_dispatch_panic_cleans_expired_bucket() {
1863 let timer = timer_state();
1864 let handles = [TimerHandle::new(1), TimerHandle::new(1)];
1865 timer.with_wheel(|wheel| {
1866 let bucket = wheel.timers[handles[0].0.get()].bucket.unwrap();
1867 wheel.relink(handles[1].0.get(), usize::from(bucket));
1868 });
1869 let task = Arc::new(InPlaceWaker {
1870 panic_on_wake: true,
1871 ..InPlaceWaker::default()
1872 });
1873 let waker = Waker::from(task.clone());
1874 for handle in &handles {
1875 assert!(
1876 handle
1877 .poll_elapsed(&mut Context::from_waker(&waker))
1878 .is_pending()
1879 );
1880 }
1881 timer.elapsed_time.set(Some(
1882 Instant::now()
1883 .checked_sub(Duration::from_millis(64))
1884 .unwrap(),
1885 ));
1886 let mut driver = timer_driver(&timer);
1887 assert!(
1888 catch_unwind(AssertUnwindSafe(|| {
1889 let _ = Pin::new(&mut driver).poll(&mut Context::from_waker(Waker::noop()));
1890 }))
1891 .is_err()
1892 );
1893 assert_eq!(task.wakes.load(Ordering::Relaxed), 1);
1894 assert!(handles.iter().all(TimerHandle::is_elapsed));
1895 timer.with_wheel(|wheel| {
1896 assert!(wheel.buckets.iter().all(Slab::is_empty));
1897 assert_eq!(wheel.occupied, [0; LVL_DEPTH as usize]);
1898 });
1899 for handle in &handles {
1900 handle.reset(10_000);
1901 assert!(!handle.is_elapsed());
1902 }
1903 drop(driver);
1904 assert!(handles.iter().all(TimerHandle::is_elapsed));
1905 assert!(!timer.flags.get().contains(Flags::DRIVER_STARTED));
1906 }
1907
1908 #[test]
1914 fn test_drop_handle_after_wheel_destroyed() {
1915 use std::cell::RefCell;
1916
1917 thread_local! {
1918 static HOLDER: RefCell<Option<TimerHandle>> = const { RefCell::new(None) };
1919 }
1920
1921 let res = std::thread::spawn(|| {
1922 HOLDER.with(|h| h.borrow_mut().take());
1925 ntex::rt::System::build()
1926 .build(ntex::rt::DefaultRuntime)
1927 .block_on(async {
1928 let hnd = TimerHandle::new(1000);
1929 std::future::poll_fn(|cx| {
1930 assert!(hnd.poll_elapsed(cx).is_pending());
1931 Poll::Ready(())
1932 })
1933 .await;
1934 HOLDER.with(|h| *h.borrow_mut() = Some(hnd));
1935 });
1936 })
1937 .join();
1938 assert!(res.is_ok());
1939 }
1940
1941 #[test]
1947 fn test_drop_callback_after_wheel_destroyed() {
1948 thread_local! {
1949 static HOLDER: RefCell<Option<CallbackTimer>> = const { RefCell::new(None) };
1950 }
1951
1952 let drops = Arc::new(AtomicUsize::new(0));
1953 let destroyed = Arc::new(AtomicBool::new(false));
1954 let count = drops.clone();
1955 let was_destroyed = destroyed.clone();
1956 std::thread::spawn(move || {
1957 HOLDER.with(|holder| holder.borrow_mut().take());
1959 ntex::rt::System::build()
1960 .build(ntex::rt::DefaultRuntime)
1961 .block_on(async move {
1962 let ordinary = TimerHandle::new(10_000);
1963 let capture = OnDropFn::new(move || {
1964 was_destroyed.store(TIMER.try_with(|_| ()).is_err(), Ordering::Relaxed);
1965 drop(ordinary);
1966 count.fetch_add(1, Ordering::Relaxed);
1967 });
1968 let callback = CallbackTimer::new(Millis(10_000), move || {
1969 let _capture = &capture;
1970 panic!("callback after shutdown");
1971 });
1972 HOLDER.with(|holder| *holder.borrow_mut() = Some(callback));
1973 });
1974 })
1975 .join()
1976 .unwrap();
1977 assert!(destroyed.load(Ordering::Relaxed));
1978 assert_eq!(drops.load(Ordering::Relaxed), 1);
1979 }
1980
1981 #[test]
1987 fn test_timer_in_next_system() {
1988 let res = std::thread::spawn(|| {
1989 for _ in 0..3 {
1990 let start = Instant::now();
1991 ntex::rt::System::build()
1992 .build(ntex::rt::DefaultRuntime)
1993 .block_on(async {
1994 sleep(Millis(10)).await;
1995 let _ = now();
1996 let _hnd = sleep(Millis(10_000));
1998 crate::spawn(async { sleep(Millis(10_000)).await });
1999 });
2000 assert!(start.elapsed() < Duration::from_secs(5));
2001 }
2002 });
2003 let (tx, rx) = std::sync::mpsc::channel();
2004 std::thread::spawn(move || tx.send(res.join().is_ok()));
2005 assert_eq!(rx.recv_timeout(Duration::from_secs(10)), Ok(true));
2006 }
2007
2008 #[test]
2014 fn test_stale_driver_drop() {
2015 let timer = Rc::new(Timer::new());
2016 timer.insert_flags(Flags::RUNNING | Flags::DRIVER_STARTED | Flags::LOWRES_DRIVER);
2017 timer.reset();
2018 assert_eq!(timer.flags.get(), Flags::empty());
2019
2020 timer.insert_flags(Flags::RUNNING | Flags::DRIVER_STARTED | Flags::LOWRES_DRIVER);
2021 drop(TimerDriver {
2022 timer: timer.clone(),
2023 generation: 0,
2024 sleep: Delay::new(Duration::ZERO),
2025 armed: None,
2026 });
2027 drop(LowresTimerDriver {
2028 timer: timer.clone(),
2029 generation: 0,
2030 sleep: Delay::new(Duration::ZERO),
2031 });
2032 assert_eq!(
2033 timer.flags.get(),
2034 Flags::RUNNING | Flags::DRIVER_STARTED | Flags::LOWRES_DRIVER
2035 );
2036 }
2037
2038 fn entry() -> TimerEntry {
2039 TimerEntry {
2040 bucket: None,
2041 bucket_entry: 0,
2042 callback: false,
2043 task: None,
2044 }
2045 }
2046
2047 #[test]
2053 fn test_bucket_expiry_bounds() {
2054 let timer = Timer::new();
2055 for elapsed in [0, 1, 7, 8, 63, 64, 511, 12_345, 1 << 30] {
2056 timer.elapsed.set(elapsed);
2057 let mut delta = 0;
2058 while delta < WHEEL_TIMEOUT_CUTOFF {
2059 let (idx, expiry) = timer.calc_wheel_index(elapsed + delta, delta);
2060 let lvl = (idx / LVL_SIZE as usize) as u64;
2061 assert!(expiry > elapsed + delta, "{elapsed} {delta} {expiry}");
2062 assert!(
2063 expiry <= elapsed + delta + lvl_gran(lvl),
2064 "{elapsed} {delta} {expiry}"
2065 );
2066 assert_eq!(expiry % lvl_gran(lvl), 0);
2067 assert_eq!(
2068 ((expiry >> lvl_shift(lvl)) & LVL_MASK) as usize,
2069 idx % LVL_SIZE as usize
2070 );
2071 delta = delta * 2 + 1;
2072 }
2073
2074 let (_, expiry) =
2076 timer.calc_wheel_index(elapsed + u64::from(u32::MAX), u64::from(u32::MAX));
2077 assert!(expiry <= elapsed + WHEEL_TIMEOUT_CUTOFF);
2078 }
2079 }
2080
2081 #[test]
2087 fn test_next_pending_bucket() {
2088 let timer = Timer::new();
2089 timer.elapsed.set(1000);
2090
2091 timer.with_wheel(|w| {
2092 assert_eq!(timer.next_pending_bucket(w), None);
2093
2094 let mut expected = Vec::new();
2095 for delta in [5000, 30, 700, 100_000] {
2096 let (idx, expiry) = timer.calc_wheel_index(1000 + delta, delta);
2097 let no = w.timers.insert(entry());
2098 w.link(no, idx);
2099 expected.push((expiry, no));
2100 }
2101 expected.sort_unstable();
2102
2103 for (expiry, no) in expected {
2104 assert_eq!(timer.next_pending_bucket(w), Some(expiry));
2105 timer.elapsed.set(expiry);
2106 w.execute_expired_timers(expiry);
2107 assert!(w.timers[no].bucket.is_none());
2108 }
2109 assert_eq!(timer.next_pending_bucket(w), None);
2110 assert_eq!(w.occupied, [0; LVL_DEPTH as usize]);
2111 });
2112 }
2113
2114 #[test]
2120 fn test_unlink_relink() {
2121 let timer = Timer::new();
2122 timer.with_wheel(|w| {
2123 let a = w.timers.insert(entry());
2124 let b = w.timers.insert(entry());
2125 w.link(a, 3);
2126 w.link(b, 3);
2127 assert_eq!(w.occupied[0], 1 << 3);
2128
2129 assert!(w.unlink(a));
2130 assert!(!w.unlink(a));
2131 assert_eq!(w.occupied[0], 1 << 3);
2132
2133 w.relink(b, LVL_SIZE as usize + 5);
2134 assert_eq!(w.occupied[0], 0);
2135 assert_eq!(w.occupied[1], 1 << 5);
2136 assert_eq!(w.timers[b].bucket, Some(LVL_SIZE as u16 + 5));
2137
2138 assert!(w.unlink(b));
2139 assert_eq!(w.occupied, [0; LVL_DEPTH as usize]);
2140 });
2141 }
2142
2143 #[ntex::test]
2149 async fn test_reset_zero_wakes_task() {
2150 let hnd = Rc::new(TimerHandle::new(10_000));
2151 let hnd2 = hnd.clone();
2152 crate::spawn(async move { hnd2.reset(0) });
2153
2154 let start = Instant::now();
2156 crate::future::select(
2157 std::future::poll_fn(|cx| hnd.poll_elapsed(cx)),
2158 sleep(Millis(500)),
2159 )
2160 .await;
2161 let elapsed = start.elapsed();
2162 assert!(elapsed < Duration::from_millis(100), "elapsed: {elapsed:?}");
2163 }
2164
2165 #[test]
2171 fn test_driver_drop_keeps_other_driver() {
2172 let timer = Rc::new(Timer::new());
2173 let no = timer.with_wheel(|w| {
2174 let no = w.timers.insert(entry());
2175 w.link(no, 3);
2176 no
2177 });
2178 timer.next_expiry.set(3);
2179 timer.lowres_stime.set(Some(SystemTime::now()));
2180 timer.insert_flags(
2181 Flags::RUNNING | Flags::DRIVER_STARTED | Flags::LOWRES_DRIVER | Flags::LOWRES_TIMER,
2182 );
2183
2184 drop(LowresTimerDriver {
2185 timer: timer.clone(),
2186 generation: 0,
2187 sleep: Delay::new(Duration::ZERO),
2188 });
2189 assert_eq!(timer.flags.get(), Flags::DRIVER_STARTED);
2190 assert!(timer.lowres_stime.get().is_none());
2191 assert_eq!(timer.next_expiry.get(), 3);
2193 timer.with_wheel(|w| assert_eq!(w.timers[no].bucket, Some(3)));
2194
2195 timer.insert_flags(Flags::RUNNING | Flags::LOWRES_DRIVER);
2196 drop(TimerDriver {
2197 timer: timer.clone(),
2198 generation: 0,
2199 sleep: Delay::new(Duration::ZERO),
2200 armed: None,
2201 });
2202 assert_eq!(timer.flags.get(), Flags::LOWRES_DRIVER);
2203 assert_eq!(timer.next_expiry.get(), u64::MAX);
2204 timer.with_wheel(|w| {
2205 assert!(w.timers[no].bucket.is_none());
2206 assert_eq!(w.occupied, [0; LVL_DEPTH as usize]);
2207 });
2208 }
2209
2210 #[ntex::test]
2216 async fn test_short_timer_after_blocking() {
2217 let _hnd = sleep(Millis(10_000));
2218 let _ = now();
2219
2220 std::thread::sleep(Duration::from_millis(100));
2222
2223 let start = Instant::now();
2224 sleep(Millis(50)).await;
2225 let elapsed = start.elapsed();
2226 assert!(elapsed >= Duration::from_millis(50), "elapsed: {elapsed:?}");
2227 }
2228
2229 #[ntex::test]
2235 async fn test_driver_cached_time_expires() {
2236 sleep(Millis(400)).await;
2238
2239 let (tx, rx) = async_channel::bounded(1);
2241 std::thread::spawn(move || {
2242 std::thread::sleep(Duration::from_millis(600));
2243 let _ = tx.send_blocking(());
2244 });
2245 rx.recv().await.unwrap();
2246
2247 let stale = Instant::now().saturating_duration_since(now());
2248 assert!(stale < Duration::from_millis(300), "stale: {stale:?}");
2249 }
2250
2251 #[ntex::test]
2257 async fn test_late_wakeup_does_not_drift() {
2258 let start = Instant::now();
2259 let fut1 = sleep(Millis(50));
2260 let fut2 = sleep(Millis(600));
2261
2262 std::thread::sleep(Duration::from_millis(500));
2267 fut1.await;
2268 fut2.await;
2269
2270 let elapsed = start.elapsed();
2271 assert!(
2272 elapsed >= Duration::from_millis(600) && elapsed < Duration::from_millis(900),
2273 "elapsed: {elapsed:?}"
2274 );
2275 }
2276
2277 #[ntex::test]
2283 #[allow(unused_variables, clippy::used_underscore_binding)]
2284 async fn test_timer() {
2285 crate::spawn(async {
2286 let s = interval(Millis(25));
2287 loop {
2288 s.tick().await;
2289 }
2290 });
2291 let time = Instant::now();
2292 let fut1 = sleep(Millis(1000));
2293 let fut2 = sleep(Millis(200));
2294
2295 fut2.await;
2296 #[cfg(not(target_os = "macos"))]
2297 {
2298 let _elapsed = time.elapsed();
2299 assert!(
2300 _elapsed > Duration::from_millis(200) && _elapsed < Duration::from_millis(300),
2301 "elapsed: {_elapsed:?}"
2302 );
2303 }
2304
2305 fut1.await;
2306
2307 #[cfg(not(target_os = "macos"))]
2308 {
2309 let _elapsed = time.elapsed();
2310 assert!(
2311 _elapsed > Duration::from_secs(1) && _elapsed < Duration::from_millis(1200), "elapsed: {_elapsed:?}",
2313 );
2314 }
2315
2316 let time = Instant::now();
2317 sleep(Millis(25)).await;
2318 #[cfg(not(target_os = "macos"))]
2319 {
2320 let _elapsed = time.elapsed();
2321 assert!(
2322 _elapsed > Duration::from_millis(20) && _elapsed < Duration::from_millis(50),
2323 "elapsed: {_elapsed:?}",
2324 );
2325 }
2326 }
2327}