#[cfg(not(target_arch = "wasm32"))]
use std::time;
#[cfg(target_arch = "wasm32")]
use web_time as time;
use core::task;
use core::future::Future;
use core::pin::Pin;
use crate::timer::Timer;
use crate::timer::Platform as PlatformTimer;
#[must_use = "Interval does nothing unless polled"]
pub struct Interval<T=PlatformTimer> {
timer: T,
pub interval: time::Duration,
finish_at: time::Instant,
}
impl Interval {
#[inline(always)]
pub fn platform_new(interval: time::Duration) -> Self {
Interval::<PlatformTimer>::new(interval)
}
}
impl<T: Timer> Interval<T> {
pub fn new(interval: time::Duration) -> Self {
Self {
timer: T::new(interval),
finish_at: time::Instant::now() + interval,
interval,
}
}
#[inline(always)]
pub fn cancel(&mut self) {
self.timer.cancel()
}
pub fn restart(&mut self) {
let now = time::Instant::now();
let interval = match now.checked_duration_since(self.finish_at) {
Some(delayed) => self.interval - time::Duration::from_nanos((delayed.as_nanos() % self.interval.as_nanos()) as _),
None => self.interval
};
self.timer.restart(interval);
}
#[inline(always)]
pub fn wait<'a>(&'a mut self) -> impl Future<Output=()> + 'a {
self
}
}
impl<T: Timer> Future for &'_ mut Interval<T> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context) -> task::Poll<Self::Output> {
match Future::poll(Pin::new(&mut self.timer), ctx) {
task::Poll::Ready(()) => {
self.restart();
task::Poll::Ready(())
},
task::Poll::Pending => task::Poll::Pending,
}
}
}