use std::future::Future;
use std::pin::Pin;
use std::task::Poll;
pub type Task<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
pub async fn yield_now() {
let mut yielded = false;
std::future::poll_fn(|cx| {
if yielded {
Poll::Ready(())
} else {
yielded = true;
cx.waker().wake_by_ref();
Poll::Pending
}
})
.await;
}
pub async fn join_all<T>(tasks: Vec<Task<'_, T>>) -> Vec<T> {
let mut slots: Vec<Option<T>> = tasks.iter().map(|_| None).collect();
let mut tasks: Vec<Option<Task<'_, T>>> = tasks.into_iter().map(Some).collect();
std::future::poll_fn(|cx| {
let mut pending = false;
for (i, t) in tasks.iter_mut().enumerate() {
let ready = match t.as_mut() {
Some(fut) => match fut.as_mut().poll(cx) {
Poll::Ready(v) => Some(v),
Poll::Pending => {
pending = true;
None
}
},
None => None,
};
if let Some(v) = ready {
slots[i] = Some(v);
*t = None;
}
}
if pending {
Poll::Pending
} else {
Poll::Ready(())
}
})
.await;
slots.into_iter().flatten().collect()
}