use std::{
fmt,
future::Future,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
use super::node::{Node, Slot};
pub struct Cancelled<'a> {
node: &'a Arc<Node>,
slot: Option<u64>,
done: bool,
}
impl<'a> Cancelled<'a> {
pub(super) fn new(node: &'a Arc<Node>) -> Self {
Self {
node,
slot: None,
done: false,
}
}
}
impl Future for Cancelled<'_> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
let me = self.get_mut();
poll_cancelled(
&mut Fields {
node: me.node,
slot: &mut me.slot,
done: &mut me.done,
},
cx,
)
}
}
impl Drop for Cancelled<'_> {
fn drop(&mut self) {
if let Some(id) = self.slot.take() {
self.node.unregister(id);
}
}
}
impl fmt::Debug for Cancelled<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Cancelled").finish_non_exhaustive()
}
}
struct Fields<'a> {
node: &'a Arc<Node>,
slot: &'a mut Option<u64>,
done: &'a mut bool,
}
fn poll_cancelled(f: &mut Fields<'_>, cx: &mut Context<'_>) -> Poll<()> {
if *f.done {
return Poll::Ready(());
}
if f.node.is_cancelled() {
if let Some(id) = f.slot.take() {
f.node.unregister(id);
}
*f.done = true;
return Poll::Ready(());
}
if let Some(id) = *f.slot {
f.node.refresh_task(id, cx.waker());
return Poll::Pending;
}
if let Some(id) = f.node.register(Slot::Task(cx.waker().clone())) {
*f.slot = Some(id);
Poll::Pending
} else {
*f.done = true;
Poll::Ready(())
}
}