use std::{future::Future, pin::Pin, task};
use futures::future::{pending, AbortHandle, Abortable, Pending};
pub trait StopToken {
fn stop(self);
}
pub struct Noop;
impl StopToken for Noop {
fn stop(self) {}
}
#[derive(Clone)]
pub struct AsyncStopToken(AbortHandle);
#[pin_project::pin_project]
#[derive(Clone)]
pub struct AsyncStopFlag(#[pin] Abortable<Pending<()>>);
impl AsyncStopToken {
pub fn new_pair() -> (Self, AsyncStopFlag) {
let (handle, reg) = AbortHandle::new_pair();
let token = Self(handle);
let flag = AsyncStopFlag(Abortable::new(pending(), reg));
(token, flag)
}
}
impl StopToken for AsyncStopToken {
fn stop(self) {
self.0.abort()
}
}
impl AsyncStopFlag {
pub fn is_stopped(&self) -> bool {
self.0.is_aborted()
}
}
impl Future for AsyncStopFlag {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
self.project().0.poll(cx).map(|res| {
debug_assert!(
res.is_err(),
"Pending Future can't ever be resolved, so Abortable is only resolved when \
canceled"
);
})
}
}