lazyBoy/crates/control/src/wait.rs

43 lines
1.2 KiB
Rust
Raw Normal View History

2026-09-10 14:42:17 +00:00
use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WaitOutcome {
Satisfied,
Timeout,
DisabledUnknown,
}
/// Wait for a predicate with a deadline. Unknown disabled reasons do not spin
/// forever — they surface as DisabledUnknown so the caller can re-observe.
pub fn wait_until<F>(deadline: Duration, mut ready: F) -> WaitOutcome
where
F: FnMut() -> Result<bool, &'static str>,
{
let start = Instant::now();
loop {
match ready() {
Ok(true) => return WaitOutcome::Satisfied,
Ok(false) if start.elapsed() >= deadline => return WaitOutcome::Timeout,
Ok(false) => std::thread::sleep(Duration::from_millis(5)),
Err(_) => return WaitOutcome::DisabledUnknown,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deadline_stops_an_unready_condition() {
let outcome = wait_until(Duration::from_millis(20), || Ok(false));
assert_eq!(outcome, WaitOutcome::Timeout);
}
#[test]
fn unknown_disabled_does_not_spin() {
let outcome = wait_until(Duration::from_secs(5), || Err("unknown"));
assert_eq!(outcome, WaitOutcome::DisabledUnknown);
}
}