use std::convert::Infallible;
use std::time::Duration;
use tokio::time::Instant;
use crate::runtime::RunOptions;
const INTERRUPT_CHECK_INTERVAL: Duration = Duration::from_millis(100);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum Wake {
Elapsed,
Stopping,
Cancelled,
}
pub(super) async fn race<F: Future>(
future: F,
deadline: Instant,
options: &RunOptions,
) -> Result<F::Output, Wake> {
tokio::pin!(future);
loop {
if options.check_limits().is_err() {
return Err(Wake::Cancelled);
}
if options.stop_requested() {
return Err(Wake::Stopping);
}
let now = Instant::now();
if now >= deadline {
return Err(Wake::Elapsed);
}
let check = tokio::time::sleep((deadline - now).min(INTERRUPT_CHECK_INTERVAL));
tokio::select! {
output = &mut future => return Ok(output),
() = check => {}
}
}
}
pub(super) async fn wait(deadline: Instant, options: &RunOptions) -> Wake {
match race(std::future::pending::<Infallible>(), deadline, options).await {
Ok(never) => match never {},
Err(wake) => wake,
}
}