use std::time::{Duration, Instant};
pub const POLL_INTERVAL: Duration = Duration::from_millis(25);
pub fn wait_until<T, E>(
deadline: Instant,
mut probe: impl FnMut(Instant) -> Result<Option<T>, E>,
) -> Result<Option<T>, E> {
loop {
if Instant::now() >= deadline {
return Ok(None);
}
let proof = probe(deadline)?;
if Instant::now() >= deadline {
return Ok(None);
}
if proof.is_some() {
return Ok(proof);
}
std::thread::sleep(POLL_INTERVAL.min(deadline.saturating_duration_since(Instant::now())));
}
}
#[cfg(feature = "async")]
pub trait AsyncProbe {
type Proof;
type Error;
fn probe(
&mut self,
) -> impl std::future::Future<Output = Result<Option<Self::Proof>, Self::Error>> + Send;
}
#[cfg(feature = "async")]
pub async fn wait_until_async<P: AsyncProbe>(
deadline: tokio::time::Instant,
probe: &mut P,
) -> Result<Option<P::Proof>, P::Error> {
loop {
if tokio::time::Instant::now() >= deadline {
return Ok(None);
}
let Ok(proof) = tokio::time::timeout_at(deadline, probe.probe()).await else {
return Ok(None);
};
let proof = proof?;
if tokio::time::Instant::now() >= deadline {
return Ok(None);
}
if proof.is_some() {
return Ok(proof);
}
tokio::time::sleep_until((tokio::time::Instant::now() + POLL_INTERVAL).min(deadline)).await;
}
}