async_time_mock_core/
interval.rs

1use crate::{Instant, TimeHandlerGuard, TimerRegistry};
2use std::fmt::{Debug, Formatter};
3use std::future::{poll_fn, Future};
4use std::pin::Pin;
5use std::sync::Arc;
6use std::task::{ready, Context, Poll};
7use std::time::Duration;
8
9pub struct Interval {
10	timer_registry: Arc<TimerRegistry>,
11	sleep: Pin<Box<dyn Future<Output = TimeHandlerGuard> + Send>>,
12	next_deadline: Instant,
13	period: Duration,
14}
15
16impl Interval {
17	pub(crate) fn new(timer_registry: Arc<TimerRegistry>, start: Instant, period: Duration) -> Self {
18		let sleep = Box::pin(timer_registry.sleep_until(start));
19		Self {
20			timer_registry,
21			sleep,
22			next_deadline: start,
23			period,
24		}
25	}
26
27	pub async fn tick(&mut self) -> (TimeHandlerGuard, Instant) {
28		poll_fn(|context| self.poll_tick(context)).await
29	}
30
31	pub fn poll_tick(&mut self, context: &mut Context<'_>) -> Poll<(TimeHandlerGuard, Instant)> {
32		let guard = ready!(self.sleep.as_mut().poll(context));
33
34		let tick_time = self.next_deadline;
35
36		self.next_deadline = tick_time + self.period;
37
38		self.sleep = Box::pin(self.timer_registry.sleep_until(self.next_deadline));
39
40		Poll::Ready((guard, tick_time))
41	}
42
43	pub fn reset(&mut self) {
44		let now = self.timer_registry.now();
45		self.next_deadline = now + self.period;
46		self.sleep = Box::pin(self.timer_registry.sleep_until(self.next_deadline));
47	}
48
49	pub fn period(&self) -> Duration {
50		self.period
51	}
52}
53
54impl Debug for Interval {
55	fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
56		let Self {
57			timer_registry,
58			sleep: _,
59			next_deadline,
60			period,
61		} = self;
62		formatter
63			.debug_struct("Interval")
64			.field("timer_registry", timer_registry)
65			.field("sleep", &"impl Future<Output = TimeHandlerGuard>")
66			.field("next_deadline", next_deadline)
67			.field("period", period)
68			.finish()
69	}
70}