Skip to main content

futures_time/stream/
interval.rs

1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
5use futures_core::stream::Stream;
6
7use crate::time::{Duration, Instant};
8
9#[cfg(feature = "web")]
10use crate::task::web_timer::Timer;
11#[cfg(not(feature = "web"))]
12use async_io::Timer;
13
14/// Creates a new stream that yields at a set interval.
15///
16/// The stream first yields after `dur`, and continues to yield every
17/// `dur` after that. The stream accounts for time elapsed between calls, and
18/// will adjust accordingly to prevent time skews.
19///
20/// Each interval may be slightly longer than the specified duration, but never
21/// less.
22///
23/// Note that intervals are not intended for high resolution timers, but rather
24/// they will likely fire some granularity after the exact instant that they're
25/// otherwise indicated to fire at.
26pub fn interval(dur: Duration) -> Interval {
27    Interval {
28        timer: Timer::after(dur.into()),
29        interval: dur,
30    }
31}
32
33/// A stream representing notifications at fixed interval
34///
35/// This stream is created by the [`interval`] function. See its
36/// documentation for more.
37///
38/// [`interval`]: fn.interval.html
39#[must_use = "streams do nothing unless polled or .awaited"]
40#[derive(Debug)]
41pub struct Interval {
42    timer: Timer,
43    interval: Duration,
44}
45
46impl Stream for Interval {
47    type Item = Instant;
48
49    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
50        let instant = match Pin::new(&mut self.timer).poll(cx) {
51            Poll::Ready(instant) => instant,
52            Poll::Pending => return Poll::Pending,
53        };
54        let interval = self.interval;
55        drop(std::mem::replace(
56            &mut self.timer,
57            Timer::after(interval.into()),
58        ));
59        Poll::Ready(Some(instant.into()))
60    }
61}