use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Waker};
struct SignalState {
completed: bool,
attacher: Option<Box<dyn FnOnce(Waker, Waker) + Send + 'static>>,
}
pub(crate) struct Signal {
state: Arc<Mutex<SignalState>>,
}
impl Signal {
pub fn new<F>(attacher: F) -> Self
where
F: FnOnce(Waker, Waker) + Send + 'static,
{
Signal {
state: Arc::new(Mutex::new(SignalState {
completed: false,
attacher: Some(Box::new(attacher)),
})),
}
}
}
impl Future for Signal {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.state.lock().unwrap().completed {
Poll::Ready(())
} else {
if let Some(attacher) = self.state.lock().unwrap().attacher.take() {
let state = Arc::clone(&self.state);
attacher(
async_task::waker_fn(move || {
state.lock().unwrap().completed = true;
}),
cx.waker().clone(),
);
}
Poll::Pending
}
}
}