When I await Futures struct, I want it to poll each of its member self.futures in a select. That is, it should poll each future in Vec<F> until one is ready. In which case, Futures should report that it is ready and return the result produced by the ready future.
I'm not trying to solve a basic problem already covered in a crate or std. I don't need select!{}. This is just a simplified minimum example.
The first thing you’ll need to sort out is how to pin the contained futures: Once a future is polled for the first time its address can’t be allowed to change, but Vec can reallocate and move its contents whenever it is modified.
There are a few ways to do that:
Store Pin<Box<F>> inside the vector instead
Instead of a vector, store an array [F; N] (adding N as a const generic parameter to the struct)
Manually ensure that you don’t do anything that might make the vector reallocate, and use unsafe to pin the references yielded from Vec::iter_mut
Find a crate that provides a Vec-like collection which pins its contents (probably something-arena)
Once you've figured that out, implementing Future is straightforward:
impl<F: Future> Futures<F> {
fn iter_pinned(self: Pin<&mut Self>)->impl Iterator<Item=Pin<&mut F>> {
todo!()
}
}
impl<F: Future> Future for Futures<F> {
type Output = F::Output;
fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
for f in self.iter_pinned() {
if let poll @ std::task::Poll::Ready(_) = f.poll(cx) { return poll; }
}
std::task::Poll::Pending
}
}