Skip to content

Commit 89100f7

Browse files
taiki-ecramertj
authored andcommitted
Re-add future::select_all
1 parent 58623a9 commit 89100f7

File tree

6 files changed

+100
-104
lines changed

6 files changed

+100
-104
lines changed

futures-util/src/future/disabled/select_all.rs

Lines changed: 0 additions & 69 deletions
This file was deleted.

futures-util/src/future/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ mod join_all;
4141
#[cfg(feature = "alloc")]
4242
pub use self::join_all::{join_all, JoinAll};
4343

44+
mod select;
45+
pub use self::select::{select, Select};
46+
47+
#[cfg(feature = "alloc")]
48+
mod select_all;
49+
#[cfg(feature = "alloc")]
50+
pub use self::select_all::{select_all, SelectAll};
51+
4452
// Combinators
4553
mod flatten;
4654
pub use self::flatten::Flatten;
@@ -57,9 +65,6 @@ pub use self::into_stream::IntoStream;
5765
mod map;
5866
pub use self::map::Map;
5967

60-
mod select;
61-
pub use self::select::{select, Select};
62-
6368
mod then;
6469
pub use self::then::Then;
6570

@@ -98,11 +103,6 @@ mod remote_handle;
98103
#[cfg(feature = "std")]
99104
pub use self::remote_handle::{Remote, RemoteHandle};
100105

101-
// #[cfg(feature = "std")]
102-
// mod select_all;
103-
// #[cfg(feature = "std")]
104-
// pub use self::select_all::{SelectAll, SelectAllNext, select_all};
105-
106106
// #[cfg(feature = "std")]
107107
// mod select_ok;
108108
// #[cfg(feature = "std")]

futures-util/src/future/select_all.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use core::iter::FromIterator;
2+
use core::mem;
3+
use core::pin::Pin;
4+
use alloc::vec::Vec;
5+
use futures_core::future::Future;
6+
use futures_core::task::{Context, Poll};
7+
8+
/// Future for the [`select_all`] function.
9+
#[derive(Debug)]
10+
#[must_use = "futures do nothing unless polled"]
11+
pub struct SelectAll<Fut> {
12+
inner: Vec<Fut>,
13+
}
14+
15+
impl<Fut: Unpin> Unpin for SelectAll<Fut> {}
16+
17+
/// Creates a new future which will select over a list of futures.
18+
///
19+
/// The returned future will wait for any future within `iter` to be ready. Upon
20+
/// completion the item resolved will be returned, along with the index of the
21+
/// future that was ready and the list of all the remaining futures.
22+
///
23+
/// # Panics
24+
///
25+
/// This function will panic if the iterator specified contains no items.
26+
pub fn select_all<I>(iter: I) -> SelectAll<I::Item>
27+
where I: IntoIterator,
28+
I::Item: Future + Unpin,
29+
{
30+
let ret = SelectAll {
31+
inner: iter.into_iter().collect()
32+
};
33+
assert!(!ret.inner.is_empty());
34+
ret
35+
}
36+
37+
impl<Fut: Future + Unpin> Future for SelectAll<Fut> {
38+
type Output = (Fut::Output, usize, Vec<Fut>);
39+
40+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
41+
let item = self.inner.iter_mut().enumerate().find_map(|(i, f)| {
42+
match Pin::new(f).poll(cx) {
43+
Poll::Pending => None,
44+
Poll::Ready(e) => Some((i, e)),
45+
}
46+
});
47+
match item {
48+
Some((idx, res)) => {
49+
self.inner.remove(idx);
50+
let rest = mem::replace(&mut self.inner, Vec::new());
51+
Poll::Ready((res, idx, rest))
52+
}
53+
None => Poll::Pending,
54+
}
55+
}
56+
}
57+
58+
impl<Fut: Future + Unpin> FromIterator<Fut> for SelectAll<Fut> {
59+
fn from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self {
60+
select_all(iter)
61+
}
62+
}

futures/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,10 @@ pub mod future {
207207
};
208208

209209
#[cfg(feature = "alloc")]
210-
pub use futures_util::future::{join_all, JoinAll};
210+
pub use futures_util::future::{
211+
join_all, JoinAll,
212+
select_all, SelectAll,
213+
};
211214

212215
#[cfg_attr(
213216
feature = "cfg-target-has-atomic",
@@ -224,7 +227,7 @@ pub mod future {
224227
// For FutureExt:
225228
CatchUnwind, Shared,
226229

227-
// ToDo: SelectAll, SelectOk, select_all, select_ok
230+
// ToDo: SelectOk, select_ok
228231
};
229232

230233
pub use futures_util::try_future::{

futures/tests/select_all.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use futures::executor::block_on;
2+
use futures::future::{ready, select_all};
3+
4+
#[test]
5+
fn smoke() {
6+
let v = vec![
7+
ready(1),
8+
ready(2),
9+
ready(3),
10+
];
11+
12+
let (i, idx, v) = block_on(select_all(v));
13+
assert_eq!(i, 1);
14+
assert_eq!(idx, 0);
15+
16+
let (i, idx, v) = block_on(select_all(v));
17+
assert_eq!(i, 2);
18+
assert_eq!(idx, 0);
19+
20+
let (i, idx, v) = block_on(select_all(v));
21+
assert_eq!(i, 3);
22+
assert_eq!(idx, 0);
23+
24+
assert!(v.is_empty());
25+
}

futures/tests_disabled/select_all.rs

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)