use std::{
future::Future,
pin::Pin,
task::{self, Poll},
};
use pin_project_lite::pin_project;
use crate::time::{
driver::{Handle, TimerEntry},
error::Error,
Duration, Instant,
};
#[cfg_attr(docsrs, doc(alias = "delay_until"))]
pub fn sleep_until(deadline: Instant) -> Sleep {
Sleep::new_timeout(deadline)
}
#[cfg_attr(docsrs, doc(alias = "delay_for"))]
#[cfg_attr(docsrs, doc(alias = "wait"))]
pub fn sleep(duration: Duration) -> Sleep {
match Instant::now().checked_add(duration) {
Some(deadline) => sleep_until(deadline),
None => sleep_until(Instant::far_future()),
}
}
pin_project! {
#[cfg_attr(docsrs, doc(alias = "Delay"))]
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Sleep {
deadline: Instant,
#[pin]
entry: TimerEntry,
}
}
impl Sleep {
pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
let handle = Handle::current();
let entry = TimerEntry::new(&handle, deadline);
Sleep { deadline, entry }
}
pub(crate) fn far_future() -> Sleep {
Self::new_timeout(Instant::far_future())
}
pub fn deadline(&self) -> Instant {
self.deadline
}
pub fn is_elapsed(&self) -> bool {
self.entry.is_elapsed()
}
pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
let me = self.project();
me.entry.reset(deadline);
*me.deadline = deadline;
}
fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
let me = self.project();
me.entry.poll_elapsed(cx)
}
}
impl Future for Sleep {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
match ready!(self.as_mut().poll_elapsed(cx)) {
Ok(()) => Poll::Ready(()),
Err(e) => panic!("timer error: {e}"),
}
}
}