futures: add join_array.
This commit is contained in:
parent
598689ef43
commit
4c0f1b6354
1 changed files with 68 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
//! Wait for multiple futures to complete.
|
//! Wait for multiple futures to complete.
|
||||||
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
use core::{fmt, mem};
|
use core::{fmt, mem};
|
||||||
|
@ -252,3 +253,70 @@ where
|
||||||
{
|
{
|
||||||
Join5::new(future1, future2, future3, future4, future5)
|
Join5::new(future1, future2, future3, future4, future5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
/// Future for the [`join_array`] function.
|
||||||
|
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||||
|
pub struct JoinArray<Fut: Future, const N: usize> {
|
||||||
|
futures: [MaybeDone<Fut>; N],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Fut: Future, const N: usize> fmt::Debug for JoinArray<Fut, N>
|
||||||
|
where
|
||||||
|
Fut: Future + fmt::Debug,
|
||||||
|
Fut::Output: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("JoinArray").field("futures", &self.futures).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Fut: Future, const N: usize> Future for JoinArray<Fut, N> {
|
||||||
|
type Output = [Fut::Output; N];
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let this = unsafe { self.get_unchecked_mut() };
|
||||||
|
let mut all_done = true;
|
||||||
|
for f in this.futures.iter_mut() {
|
||||||
|
all_done &= unsafe { Pin::new_unchecked(f) }.poll(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if all_done {
|
||||||
|
let mut array: [MaybeUninit<Fut::Output>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
|
for i in 0..N {
|
||||||
|
array[i].write(this.futures[i].take_output());
|
||||||
|
}
|
||||||
|
Poll::Ready(unsafe { (&array as *const _ as *const [Fut::Output; N]).read() })
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Joins the result of an array of futures, waiting for them all to complete.
|
||||||
|
///
|
||||||
|
/// This function will return a new future which awaits all futures to
|
||||||
|
/// complete. The returned future will finish with a tuple of all results.
|
||||||
|
///
|
||||||
|
/// Note that this function consumes the passed futures and returns a
|
||||||
|
/// wrapped version of it.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # embassy_futures::block_on(async {
|
||||||
|
///
|
||||||
|
/// async fn foo(n: u32) -> u32 { n }
|
||||||
|
/// let a = foo(1);
|
||||||
|
/// let b = foo(2);
|
||||||
|
/// let c = foo(3);
|
||||||
|
/// let res = embassy_futures::join::join_array([a, b, c]).await;
|
||||||
|
///
|
||||||
|
/// assert_eq!(res, [1, 2, 3]);
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
pub fn join_array<Fut: Future, const N: usize>(futures: [Fut; N]) -> JoinArray<Fut, N> {
|
||||||
|
JoinArray {
|
||||||
|
futures: futures.map(MaybeDone::Future),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue