use kyansel::{cancellable, CancellableResult};
use std::future::Future;
use tokio::{
prelude::*,
sync::{
mpsc::{unbounded_channel, UnboundedReceiver},
oneshot::{channel, error::RecvError, Sender},
},
timer::delay,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, _) = channel();
let mut tx = Some(tx);
let (cancel_tx, cancel_rx) = unbounded_channel();
let (finish_tx, finish_rx) = unbounded_channel();
for i in 0..20 {
let mut finish_tx = finish_tx.clone();
let mut cancel_tx = cancel_tx.clone();
let (tmp_tx, fut) = create_cancellable_future(i, tx.take().unwrap());
tx = Some(tmp_tx);
tokio::spawn(async move {
let result = fut.await;
let _ = match result {
CancellableResult::Cancelled(canceler) => {
cancel_tx.send((i, canceler.unwrap())).await
}
CancellableResult::Finished(me) => finish_tx.send(me).await,
};
});
delay(tokio::clock::now() + std::time::Duration::from_millis(20)).await;
}
std::mem::drop(cancel_tx);
std::mem::drop(finish_tx);
async move {
let mut v = collect_channel::<usize>(finish_rx).await;
v.sort();
println!("Finished: {:?}", v);
}
.await;
async move {
let mut v = collect_channel::<(usize, usize)>(cancel_rx).await;
v.sort();
println!("Cancelled: {:?}", v);
}
.await;
Ok(())
}
async fn collect_channel<T>(mut rx: UnboundedReceiver<T>) -> Vec<T> {
let mut v = Vec::new();
while let Some(n) = rx.recv().await {
v.push(n);
}
v
}
fn create_cancellable_future(
input: usize,
tx: Sender<usize>,
) -> (Sender<usize>, impl Future<Output = CancellableResult<usize, Result<usize, RecvError>>>) {
let cancel_previous = async move { tx.send(input) };
let (tx, rx) = channel();
let fut = async move {
delay(tokio::clock::now() + std::time::Duration::from_millis(20)).await;
input
};
let cancel = cancellable(fut, rx);
(tx, async move {
let _ = cancel_previous.await;
cancel.await
})
}