I want a simple Timeout future for testing and other capabilities. The following will work but it feels a little brute force to me and I was wondering if there was a better way to implement this that might take advantage of the OS or something. A caveat is that it must use only core Rust. I cannot ingest the Tokio ecosystem nor do I want to import a crate of hundreds of things for just this.
struct TimeoutFuture {
/// State contains a bool indicating if the future completed and the waker it is tracking.
state: Arc<Mutex<(bool, Option<Waker>)>>,
}
impl TimeoutFuture {
fn new(duration: Duration) -> Self {
let result = TimeoutFuture {
state: Arc::new(Mutex::new((false, None))),
};
let state_clone = result.state.clone();
thread::spawn(move || {
thread::sleep(duration);
let mut state = state_clone.lock().unwrap();
state.0 = true;
if let Some(waker) = state.1.take() {
waker.wake();
}
});
result
}
}
impl Future for TimeoutFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut state = self.state.lock().unwrap();
if state.0 {
Poll::Ready(())
} else {
state.1 = Some(cx.waker().clone());
Poll::Pending
}
}
}
The future works but it just feels wrong.