use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
time::Duration,
};
pub(crate) struct Delay(DelayInner);
enum DelayInner {
#[cfg(feature = "tokio-timer")]
Tokio(Pin<Box<tokio::time::Sleep>>),
AsyncIo(Pin<Box<async_io::Timer>>),
}
impl Delay {
pub fn new(duration: Duration) -> Self {
#[cfg(feature = "tokio-timer")]
if tokio::runtime::Handle::try_current().is_ok() {
return Self(DelayInner::Tokio(Box::pin(tokio::time::sleep(duration))));
}
#[allow(unreachable_code)]
Self(DelayInner::AsyncIo(Box::pin(async_io::Timer::after(
duration,
))))
}
pub fn reset(&mut self, duration: Duration) {
match &mut self.0 {
#[cfg(feature = "tokio-timer")]
DelayInner::Tokio(sleep) => {
sleep.as_mut().reset(tokio::time::Instant::now() + duration);
}
DelayInner::AsyncIo(timer) => {
timer.as_mut().set_after(duration);
}
}
}
}
impl Future for Delay {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match &mut self.0 {
#[cfg(feature = "tokio-timer")]
DelayInner::Tokio(sleep) => sleep.as_mut().poll(cx),
DelayInner::AsyncIo(timer) => timer.as_mut().poll(cx).map(|_| ()),
}
}
}
impl Unpin for Delay {}