use async_channel::{Receiver, Sender};
use futures_concurrency::future::Race;
use futures_util::StreamExt;
use futures_util::stream::FuturesUnordered;
use crate::Task;
pub struct TaskReaper<T> {
send_task: Sender<Task<T>>,
_reaper: Task<()>,
}
impl<T: Send + 'static> Default for TaskReaper<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Send + 'static> TaskReaper<T> {
pub fn new() -> Self {
let (send_task, recv_task) = async_channel::unbounded();
let _reaper = crate::spawn(reaper_loop(recv_task));
Self { send_task, _reaper }
}
pub fn attach(&self, task: Task<T>) {
let _ = self.send_task.try_send(task);
}
}
async fn reaper_loop<T: Send + 'static>(recv_task: Receiver<Task<T>>) {
let mut inner: FuturesUnordered<Task<T>> = FuturesUnordered::new();
loop {
let next = (async { recv_task.recv().await }, async {
inner.next().await;
std::future::pending::<Result<Task<T>, async_channel::RecvError>>().await
})
.race()
.await;
match next {
Ok(task) => inner.push(task),
Err(_) => return,
}
}
}