use futures::future::{FusedFuture, Shared};
use futures::{Future, FutureExt};
use std::task::{Context, Poll};
use crate::DropWatch;
#[derive(Clone)]
#[must_use = "futures do nothing unless you await or poll them"]
pub struct Dropped(Shared<futures::channel::oneshot::Receiver<()>>);
impl Dropped {
pub fn new<DW: DropWatch<U> + ?Sized, U: ?Sized>(watchable: &DW) -> Self {
let (sender, receiver) = futures::channel::oneshot::channel();
DropWatch::watch(watchable, move |_| {
let _ = sender.send(());
});
Self(receiver.shared())
}
}
impl Future for Dropped {
type Output = ();
fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.0.poll_unpin(cx).map(|_| ())
}
}
impl FusedFuture for Dropped {
fn is_terminated(&self) -> bool {
self.0.is_terminated()
}
}
#[cfg(test)]
mod tests {
use async_utils::PollExt;
use futures_test::task::new_count_waker;
use super::*;
use crate::Vigil;
#[test]
fn obits() {
let v = Vigil::new(());
let mut obit = Vigil::dropped(&v);
let mut obit2 = Vigil::dropped(&v);
let mut obit_never_polled = Vigil::dropped(&v);
let (waker, count) = new_count_waker();
let mut cx = Context::from_waker(&waker);
obit.poll_unpin(&mut cx).expect_pending("shouldn't be done");
obit2.poll_unpin(&mut cx).expect_pending("shouldn't be done");
drop(v);
assert_eq!(2, count.get());
obit.poll_unpin(&mut cx).expect("should be done");
obit2.poll_unpin(&mut cx).expect("should also be done");
obit_never_polled.poll_unpin(&mut cx).expect("be done");
}
}