use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
time::{Duration, SystemTime},
};
use futures::future::FusedFuture;
use pin_project_lite::pin_project;
pin_project! {
#[derive(Debug, Copy, Clone)]
pub struct Sleep {
#[pin]
now: SystemTime,
#[pin]
duration: Duration,
#[pin]
polled: bool,
#[pin]
completed: bool,
}
}
impl Sleep {
#[must_use]
pub fn new(duration: Duration) -> Self {
Self {
now: gimbal_time::now(),
duration,
polled: false,
completed: false,
}
}
}
impl Future for Sleep {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let mut this = self.project();
log::trace!(
"Polling Sleep: now={:?} duration={:?} polled={} completed={}",
this.now,
this.duration,
this.polled,
this.completed,
);
let polled = *this.polled;
if polled {
let duration = gimbal_time::now().duration_since(*this.now).unwrap();
log::trace!(
"Sleep polled: {}ms/{}ms",
duration.as_millis(),
this.duration.as_millis(),
);
if duration >= *this.duration {
*this.completed.as_mut() = true;
return Poll::Ready(());
}
}
if !polled {
*this.polled.as_mut() = true;
}
cx.waker().wake_by_ref();
Poll::Pending
}
}
impl FusedFuture for Sleep {
fn is_terminated(&self) -> bool {
self.completed
}
}