1use super::convert;
3use lazycell::LazyCell;
4use log::trace;
5use mio::{Interest, Registry, Token, Waker, event::Source};
6use slab::Slab;
7use std::{
8 cmp, fmt, io, iter,
9 sync::{
10 Arc, Mutex,
11 atomic::{AtomicUsize, Ordering},
12 },
13 thread,
14 time::{Duration, Instant},
15 u64, usize,
16};
17
18type Tick = u64;
19
20const TICK_MAX: Tick = u64::MAX;
21
22type WakeupState = Arc<AtomicUsize>;
24
25const TERMINATE_THREAD: usize = 0;
26const EMPTY: Token = Token(usize::MAX);
27
28pub struct Timer<T> {
41 tick_ms: u64,
43 entries: Slab<Entry<T>>,
45 wheel: Vec<WheelEntry>,
48 start: Instant,
50 tick: Tick,
52 next: Token,
54 mask: u64,
56 inner: LazyCell<Inner>,
58}
59
60pub struct Builder {
62 tick: Duration,
64 num_slots: usize,
66 capacity: usize,
68}
69
70impl Builder {
71 pub fn tick_duration(mut self, duration: Duration) -> Builder {
73 self.tick = duration;
74 self
75 }
76
77 pub fn num_slots(mut self, num_slots: usize) -> Builder {
79 self.num_slots = num_slots;
80 self
81 }
82
83 pub fn capacity(mut self, capacity: usize) -> Builder {
85 self.capacity = capacity;
86 self
87 }
88
89 pub fn build<T>(self) -> Timer<T> {
91 Timer::new(
92 convert::millis(self.tick),
93 self.num_slots,
94 self.capacity,
95 Instant::now(),
96 )
97 }
98}
99
100impl Default for Builder {
101 fn default() -> Builder {
102 Builder {
103 tick: Duration::from_millis(100),
104 num_slots: 1 << 8,
105 capacity: 1 << 16,
106 }
107 }
108}
109
110#[derive(Clone, Debug)]
114pub struct Timeout {
115 token: Token,
117 tick: u64,
119}
120
121struct Inner {
122 waker: Arc<Mutex<Option<Waker>>>,
123 wakeup_state: WakeupState,
124 wakeup_thread: thread::JoinHandle<()>,
125}
126
127impl Drop for Inner {
128 fn drop(&mut self) {
129 self.wakeup_state.store(TERMINATE_THREAD, Ordering::Release);
131 self.wakeup_thread.thread().unpark();
133 }
134}
135
136impl fmt::Debug for Inner {
137 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
138 fmt.debug_struct("Inner")
139 .field("wakeup_state", &self.wakeup_state.load(Ordering::Relaxed))
140 .finish()
141 }
142}
143
144#[derive(Copy, Clone, Debug)]
145struct WheelEntry {
146 next_tick: Tick,
147 head: Token,
148}
149
150struct Entry<T> {
153 state: T,
154 links: EntryLinks,
155}
156
157impl<T> Entry<T> {
158 fn new(state: T, tick: u64, next: Token) -> Entry<T> {
159 Entry {
160 state,
161 links: EntryLinks {
162 tick,
163 prev: EMPTY,
164 next,
165 },
166 }
167 }
168}
169
170#[derive(Copy, Clone)]
171struct EntryLinks {
172 tick: Tick,
173 prev: Token,
174 next: Token,
175}
176
177impl<T> Timer<T> {
178 fn new(tick_ms: u64, num_slots: usize, capacity: usize, start: Instant) -> Timer<T> {
179 let num_slots = num_slots.next_power_of_two();
180 let capacity = capacity.next_power_of_two();
181 let mask = (num_slots as u64) - 1;
182 let wheel = iter::repeat(WheelEntry {
183 next_tick: TICK_MAX,
184 head: EMPTY,
185 })
186 .take(num_slots)
187 .collect();
188
189 Timer {
190 tick_ms,
191 entries: Slab::with_capacity(capacity),
192 wheel,
193 start,
194 tick: 0,
195 next: EMPTY,
196 mask,
197 inner: LazyCell::new(),
198 }
199 }
200
201 pub fn set_timeout(&mut self, delay_from_now: Duration, state: T) -> Timeout {
205 let delay_from_start = self.start.elapsed() + delay_from_now;
206 self.set_timeout_at(delay_from_start, state)
207 }
208
209 fn set_timeout_at(&mut self, delay_from_start: Duration, state: T) -> Timeout {
210 let mut tick = duration_to_tick(delay_from_start, self.tick_ms);
211 trace!(
212 "setting timeout; delay={:?}; tick={:?}; current-tick={:?}",
213 delay_from_start, tick, self.tick
214 );
215
216 if tick <= self.tick {
218 tick = self.tick + 1;
219 }
220
221 self.insert(tick, state)
222 }
223
224 fn insert(&mut self, tick: Tick, state: T) -> Timeout {
225 let slot = self.slot_for(tick);
227 let curr = self.wheel[slot];
228
229 let entry = Entry::new(state, tick, curr.head);
231 let token = Token(self.entries.insert(entry));
232
233 if curr.head != EMPTY {
234 self.entries[curr.head.into()].links.prev = token;
237 }
238
239 self.wheel[slot] = WheelEntry {
241 next_tick: cmp::min(tick, curr.next_tick),
242 head: token,
243 };
244
245 self.schedule_readiness(tick);
246
247 trace!("inserted timout; slot={}; token={:?}", slot, token);
248
249 Timeout { token, tick }
251 }
252
253 pub fn cancel_timeout(&mut self, timeout: &Timeout) -> Option<T> {
258 let links = match self.entries.get(timeout.token.into()) {
259 Some(e) => e.links,
260 None => return None,
261 };
262
263 if links.tick != timeout.tick {
265 return None;
266 }
267
268 self.unlink(&links, timeout.token);
269 Some(self.entries.remove(timeout.token.into()).state)
270 }
271
272 pub fn poll(&mut self) -> Option<T> {
277 let target_tick = current_tick(self.start, self.tick_ms);
278 self.poll_to(target_tick)
279 }
280
281 fn poll_to(&mut self, mut target_tick: Tick) -> Option<T> {
282 trace!(
283 "tick_to; target_tick={}; current_tick={}",
284 target_tick, self.tick
285 );
286
287 if target_tick < self.tick {
288 target_tick = self.tick;
289 }
290
291 while self.tick <= target_tick {
292 let curr = self.next;
293
294 trace!("ticking; curr={:?}", curr);
295
296 if curr == EMPTY {
297 self.tick += 1;
298
299 let slot = self.slot_for(self.tick);
300 self.next = self.wheel[slot].head;
301
302 if self.next == EMPTY {
308 self.wheel[slot].next_tick = TICK_MAX;
309 }
310 } else {
311 let slot = self.slot_for(self.tick);
312
313 if curr == self.wheel[slot].head {
314 self.wheel[slot].next_tick = TICK_MAX;
315 }
316
317 let links = self.entries[curr.into()].links;
318
319 if links.tick <= self.tick {
320 trace!("triggering; token={:?}", curr);
321
322 self.unlink(&links, curr);
324
325 return Some(self.entries.remove(curr.into()).state);
327 } else {
328 let next_tick = self.wheel[slot].next_tick;
329 self.wheel[slot].next_tick = cmp::min(next_tick, links.tick);
330 self.next = links.next;
331 }
332 }
333 }
334
335 if let Some(_inner) = self.inner.borrow() {
337 trace!("unsetting readiness");
338 if let Some(tick) = self.next_tick() {
341 self.schedule_readiness(tick);
342 }
343 }
344
345 None
346 }
347
348 fn unlink(&mut self, links: &EntryLinks, token: Token) {
349 trace!(
350 "unlinking timeout; slot={}; token={:?}",
351 self.slot_for(links.tick),
352 token
353 );
354
355 if links.prev == EMPTY {
356 let slot = self.slot_for(links.tick);
357 self.wheel[slot].head = links.next;
358 } else {
359 self.entries[links.prev.into()].links.next = links.next;
360 }
361
362 if links.next != EMPTY {
363 self.entries[links.next.into()].links.prev = links.prev;
364
365 if token == self.next {
366 self.next = links.next;
367 }
368 } else if token == self.next {
369 self.next = EMPTY;
370 }
371 }
372
373 fn schedule_readiness(&self, tick: Tick) {
374 if let Some(inner) = self.inner.borrow() {
375 let mut curr = inner.wakeup_state.load(Ordering::Acquire);
377
378 loop {
379 if curr as Tick <= tick {
380 return;
382 }
383
384 trace!("advancing the wakeup time; target={}; curr={}", tick, curr);
386 let actual = inner
387 .wakeup_state
388 .compare_exchange(curr, tick as usize, Ordering::Release, Ordering::Relaxed)
389 .unwrap_or_else(|x| x);
390
391 if actual == curr {
392 trace!("unparking wakeup thread");
395 inner.wakeup_thread.thread().unpark();
396 return;
397 }
398
399 curr = actual;
400 }
401 }
402 }
403
404 fn next_tick(&self) -> Option<Tick> {
406 if self.next != EMPTY {
407 let slot = self.slot_for(self.entries[self.next.into()].links.tick);
408
409 if self.wheel[slot].next_tick == self.tick {
410 return Some(self.tick);
412 }
413 }
414
415 self.wheel.iter().map(|e| e.next_tick).min()
416 }
417
418 fn slot_for(&self, tick: Tick) -> usize {
419 (self.mask & tick) as usize
420 }
421}
422
423impl<T> Default for Timer<T> {
424 fn default() -> Timer<T> {
425 Builder::default().build()
426 }
427}
428
429impl<T> Source for Timer<T> {
430 fn register(&mut self, registry: &Registry, token: Token, _: Interest) -> io::Result<()> {
431 if self.inner.borrow().is_some() {
432 return Err(io::Error::new(
433 io::ErrorKind::Other,
434 "timer already registered",
435 ));
436 }
437
438 let waker = Arc::new(Mutex::new(Some(Waker::new(registry, token)?)));
439 let wakeup_state = Arc::new(AtomicUsize::new(usize::MAX));
440 let thread_handle = spawn_wakeup_thread(
441 Arc::clone(&wakeup_state),
442 waker.clone(),
443 self.start,
444 self.tick_ms,
445 );
446
447 self.inner
448 .fill(Inner {
449 waker,
450 wakeup_state,
451 wakeup_thread: thread_handle,
452 })
453 .expect("timer already registered");
454
455 if let Some(next_tick) = self.next_tick() {
456 self.schedule_readiness(next_tick);
457 }
458
459 Ok(())
460 }
461
462 fn reregister(&mut self, registry: &Registry, token: Token, _: Interest) -> io::Result<()> {
463 match self.inner.borrow() {
464 Some(inner) => {
465 let mut waker = inner.waker.lock().unwrap();
466 *waker = Some(Waker::new(registry, token)?);
467
468 return Ok(());
469 }
470 None => Err(io::Error::new(
471 io::ErrorKind::Other,
472 "receiver not registered",
473 )),
474 }
475 }
476
477 fn deregister(&mut self, _: &Registry) -> io::Result<()> {
478 match self.inner.borrow() {
479 Some(inner) => {
480 let mut waker = inner.waker.lock().unwrap();
481 *waker = None;
482
483 return Ok(());
484 }
485 None => Err(io::Error::new(
486 io::ErrorKind::Other,
487 "receiver not registered",
488 )),
489 }
490 }
491}
492
493fn spawn_wakeup_thread(
494 state: WakeupState,
495 waker: Arc<Mutex<Option<Waker>>>,
496 start: Instant,
497 tick_ms: u64,
498) -> thread::JoinHandle<()> {
499 thread::spawn(move || {
500 let mut sleep_until_tick = state.load(Ordering::Acquire) as Tick;
501
502 loop {
503 if sleep_until_tick == TERMINATE_THREAD as Tick {
504 return;
505 }
506
507 let now_tick = current_tick(start, tick_ms);
508
509 trace!(
510 "wakeup thread: sleep_until_tick={:?}; now_tick={:?}",
511 sleep_until_tick, now_tick
512 );
513
514 if now_tick < sleep_until_tick {
515 match tick_ms.checked_mul(sleep_until_tick - now_tick) {
520 Some(sleep_duration) => {
521 trace!(
522 "sleeping; tick_ms={}; now_tick={}; sleep_until_tick={}; duration={:?}",
523 tick_ms, now_tick, sleep_until_tick, sleep_duration
524 );
525 thread::park_timeout(Duration::from_millis(sleep_duration));
526 }
527 None => {
528 trace!(
529 "sleeping; tick_ms={}; now_tick={}; blocking sleep",
530 tick_ms, now_tick
531 );
532 thread::park();
533 }
534 }
535 sleep_until_tick = state.load(Ordering::Acquire) as Tick;
536 } else {
537 let actual = state
538 .compare_exchange(
539 sleep_until_tick as usize,
540 usize::MAX,
541 Ordering::AcqRel,
542 Ordering::Acquire,
543 )
544 .unwrap_or_else(|x| x) as Tick;
545
546 if actual == sleep_until_tick {
547 trace!("setting readiness from wakeup thread");
548 if let Some(waker) = &mut *waker.lock().unwrap() {
549 let _ = waker.wake();
550 }
551 sleep_until_tick = usize::MAX as Tick;
552 } else {
553 sleep_until_tick = actual as Tick;
554 }
555 }
556 }
557 })
558}
559
560fn duration_to_tick(elapsed: Duration, tick_ms: u64) -> Tick {
561 let elapsed_ms = convert::millis(elapsed);
563 elapsed_ms.saturating_add(tick_ms / 2) / tick_ms
564}
565
566fn current_tick(start: Instant, tick_ms: u64) -> Tick {
567 duration_to_tick(start.elapsed(), tick_ms)
568}
569
570#[cfg(test)]
571mod test {
572 use super::*;
573 use std::time::{Duration, Instant};
574
575 #[test]
576 pub fn test_timeout_next_tick() {
577 let mut t = timer();
578 let mut tick;
579
580 t.set_timeout_at(Duration::from_millis(100), "a");
581
582 tick = ms_to_tick(&t, 50);
583 assert_eq!(None, t.poll_to(tick));
584
585 tick = ms_to_tick(&t, 100);
586 assert_eq!(Some("a"), t.poll_to(tick));
587 assert_eq!(None, t.poll_to(tick));
588
589 tick = ms_to_tick(&t, 150);
590 assert_eq!(None, t.poll_to(tick));
591
592 tick = ms_to_tick(&t, 200);
593 assert_eq!(None, t.poll_to(tick));
594
595 assert_eq!(count(&t), 0);
596 }
597
598 #[test]
599 pub fn test_clearing_timeout() {
600 let mut t = timer();
601 let mut tick;
602
603 let to = t.set_timeout_at(Duration::from_millis(100), "a");
604 assert_eq!("a", t.cancel_timeout(&to).unwrap());
605
606 tick = ms_to_tick(&t, 100);
607 assert_eq!(None, t.poll_to(tick));
608
609 tick = ms_to_tick(&t, 200);
610 assert_eq!(None, t.poll_to(tick));
611
612 assert_eq!(count(&t), 0);
613 }
614
615 #[test]
616 pub fn test_multiple_timeouts_same_tick() {
617 let mut t = timer();
618 let mut tick;
619
620 t.set_timeout_at(Duration::from_millis(100), "a");
621 t.set_timeout_at(Duration::from_millis(100), "b");
622
623 let mut rcv = vec![];
624
625 tick = ms_to_tick(&t, 100);
626 rcv.push(t.poll_to(tick).unwrap());
627 rcv.push(t.poll_to(tick).unwrap());
628
629 assert_eq!(None, t.poll_to(tick));
630
631 rcv.sort();
632 assert!(rcv == ["a", "b"], "actual={:?}", rcv);
633
634 tick = ms_to_tick(&t, 200);
635 assert_eq!(None, t.poll_to(tick));
636
637 assert_eq!(count(&t), 0);
638 }
639
640 #[test]
641 pub fn test_multiple_timeouts_diff_tick() {
642 let mut t = timer();
643 let mut tick;
644
645 t.set_timeout_at(Duration::from_millis(110), "a");
646 t.set_timeout_at(Duration::from_millis(220), "b");
647 t.set_timeout_at(Duration::from_millis(230), "c");
648 t.set_timeout_at(Duration::from_millis(440), "d");
649 t.set_timeout_at(Duration::from_millis(560), "e");
650
651 tick = ms_to_tick(&t, 100);
652 assert_eq!(Some("a"), t.poll_to(tick));
653 assert_eq!(None, t.poll_to(tick));
654
655 tick = ms_to_tick(&t, 200);
656 assert_eq!(Some("c"), t.poll_to(tick));
657 assert_eq!(Some("b"), t.poll_to(tick));
658 assert_eq!(None, t.poll_to(tick));
659
660 tick = ms_to_tick(&t, 300);
661 assert_eq!(None, t.poll_to(tick));
662
663 tick = ms_to_tick(&t, 400);
664 assert_eq!(Some("d"), t.poll_to(tick));
665 assert_eq!(None, t.poll_to(tick));
666
667 tick = ms_to_tick(&t, 500);
668 assert_eq!(None, t.poll_to(tick));
669
670 tick = ms_to_tick(&t, 600);
671 assert_eq!(Some("e"), t.poll_to(tick));
672 assert_eq!(None, t.poll_to(tick));
673 }
674
675 #[test]
676 pub fn test_catching_up() {
677 let mut t = timer();
678
679 t.set_timeout_at(Duration::from_millis(110), "a");
680 t.set_timeout_at(Duration::from_millis(220), "b");
681 t.set_timeout_at(Duration::from_millis(230), "c");
682 t.set_timeout_at(Duration::from_millis(440), "d");
683
684 let tick = ms_to_tick(&t, 600);
685 assert_eq!(Some("a"), t.poll_to(tick));
686 assert_eq!(Some("c"), t.poll_to(tick));
687 assert_eq!(Some("b"), t.poll_to(tick));
688 assert_eq!(Some("d"), t.poll_to(tick));
689 assert_eq!(None, t.poll_to(tick));
690 }
691
692 #[test]
693 pub fn test_timeout_hash_collision() {
694 let mut t = timer();
695 let mut tick;
696
697 t.set_timeout_at(Duration::from_millis(100), "a");
698 t.set_timeout_at(Duration::from_millis(100 + TICK * SLOTS as u64), "b");
699
700 tick = ms_to_tick(&t, 100);
701 assert_eq!(Some("a"), t.poll_to(tick));
702 assert_eq!(1, count(&t));
703
704 tick = ms_to_tick(&t, 200);
705 assert_eq!(None, t.poll_to(tick));
706 assert_eq!(1, count(&t));
707
708 tick = ms_to_tick(&t, 100 + TICK * SLOTS as u64);
709 assert_eq!(Some("b"), t.poll_to(tick));
710 assert_eq!(0, count(&t));
711 }
712
713 #[test]
714 pub fn test_clearing_timeout_between_triggers() {
715 let mut t = timer();
716 let mut tick;
717
718 let a = t.set_timeout_at(Duration::from_millis(100), "a");
719 let _ = t.set_timeout_at(Duration::from_millis(100), "b");
720 let _ = t.set_timeout_at(Duration::from_millis(200), "c");
721
722 tick = ms_to_tick(&t, 100);
723 assert_eq!(Some("b"), t.poll_to(tick));
724 assert_eq!(2, count(&t));
725
726 t.cancel_timeout(&a);
727 assert_eq!(1, count(&t));
728
729 assert_eq!(None, t.poll_to(tick));
730
731 tick = ms_to_tick(&t, 200);
732 assert_eq!(Some("c"), t.poll_to(tick));
733 assert_eq!(0, count(&t));
734 }
735
736 const TICK: u64 = 100;
737 const SLOTS: usize = 16;
738 const CAPACITY: usize = 32;
739
740 fn count<T>(timer: &Timer<T>) -> usize {
741 timer.entries.len()
742 }
743
744 fn timer() -> Timer<&'static str> {
745 Timer::new(TICK, SLOTS, CAPACITY, Instant::now())
746 }
747
748 fn ms_to_tick<T>(timer: &Timer<T>, ms: u64) -> u64 {
749 ms / timer.tick_ms
750 }
751}