Skip to content

Commit 001cbf0

Browse files
taiki-ecramertj
authored andcommitted
Re-add try_future::select_ok (#1557)
1 parent bdfebff commit 001cbf0

File tree

5 files changed

+45
-54
lines changed

5 files changed

+45
-54
lines changed

futures-util/src/future/mod.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ mod remote_handle;
105105
#[cfg(feature = "std")]
106106
pub use self::remote_handle::{Remote, RemoteHandle};
107107

108-
// #[cfg(feature = "std")]
109-
// mod select_ok;
110-
// #[cfg(feature = "std")]
111-
// pub use self::select_ok::{SelectOk, select_ok};
112-
113108
#[cfg(feature = "std")]
114109
mod shared;
115110
#[cfg(feature = "std")]

futures-util/src/try_future/mod.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,6 @@ use futures_sink::Sink;
88

99
#[cfg(feature = "compat")] use crate::compat::Compat;
1010

11-
/* TODO
12-
mod select;
13-
pub use self::select::Select;
14-
15-
#[cfg(feature = "std")]
16-
mod select_all;
17-
#[cfg(feature = "std")]
18-
mod select_ok;
19-
#[cfg(feature = "std")]
20-
pub use self::select_all::{SelectAll, SelectAllNext, select_all};
21-
#[cfg(feature = "std")]
22-
pub use self::select_ok::{SelectOk, select_ok};
23-
*/
24-
2511
mod try_join;
2612
pub use self::try_join::{
2713
try_join, try_join3, try_join4, try_join5,
@@ -33,6 +19,15 @@ mod try_join_all;
3319
#[cfg(feature = "alloc")]
3420
pub use self::try_join_all::{try_join_all, TryJoinAll};
3521

22+
// TODO
23+
// mod try_select;
24+
// pub use self::try_select::{try_select, TrySelect};
25+
26+
#[cfg(feature = "alloc")]
27+
mod select_ok;
28+
#[cfg(feature = "alloc")]
29+
pub use self::select_ok::{select_ok, SelectOk};
30+
3631
// Combinators
3732
mod and_then;
3833
pub use self::and_then::AndThen;
Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
//! Definition of the `SelectOk` combinator, finding the first successful future
2-
//! in a list.
3-
4-
use std::mem;
5-
use std::prelude::v1::*;
6-
7-
use futures_core::{Future, IntoFuture, Poll, Async};
8-
use futures_core::task;
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, TryFuture};
6+
use futures_core::task::{Context, Poll};
97

108
/// Future for the [`select_ok`] function.
119
#[derive(Debug)]
1210
#[must_use = "futures do nothing unless polled"]
13-
pub struct SelectOk<A> where A: Future {
14-
inner: Vec<A>,
11+
pub struct SelectOk<Fut> {
12+
inner: Vec<Fut>,
1513
}
1614

15+
impl<Fut: Unpin> Unpin for SelectOk<Fut> {}
16+
1717
/// Creates a new future which will select the first successful future over a list of futures.
1818
///
1919
/// The returned future will wait for any future within `iter` to be ready and Ok. Unlike
@@ -24,55 +24,56 @@ pub struct SelectOk<A> where A: Future {
2424
/// # Panics
2525
///
2626
/// This function will panic if the iterator specified contains no items.
27-
pub fn select_ok<I>(iter: I) -> SelectOk<<I::Item as IntoFuture>::Future>
27+
pub fn select_ok<I>(iter: I) -> SelectOk<I::Item>
2828
where I: IntoIterator,
29-
I::Item: IntoFuture,
29+
I::Item: TryFuture + Unpin,
3030
{
3131
let ret = SelectOk {
32-
inner: iter.into_iter()
33-
.map(|a| a.into_future())
34-
.collect(),
32+
inner: iter.into_iter().collect()
3533
};
36-
assert!(ret.inner.len() > 0);
34+
assert!(!ret.inner.is_empty());
3735
ret
3836
}
3937

40-
impl<A> Future for SelectOk<A> where A: Future {
41-
type Item = (A::Item, Vec<A>);
42-
type Error = A::Error;
38+
impl<Fut: TryFuture + Unpin> Future for SelectOk<Fut> {
39+
type Output = Result<(Fut::Ok, Vec<Fut>), Fut::Error>;
4340

44-
fn poll(&mut self, cx: &mut Context<'_>) -> Poll<Self::Item, Self::Error> {
41+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
4542
// loop until we've either exhausted all errors, a success was hit, or nothing is ready
4643
loop {
47-
let item = self.inner.iter_mut().enumerate().filter_map(|(i, f)| {
48-
match f.poll(cx) {
49-
Ok(Poll::Pending) => None,
50-
Ok(Poll::Ready(e)) => Some((i, Ok(e))),
51-
Err(e) => Some((i, Err(e))),
44+
let item = self.inner.iter_mut().enumerate().find_map(|(i, f)| {
45+
match Pin::new(f).try_poll(cx) {
46+
Poll::Pending => None,
47+
Poll::Ready(e) => Some((i, e)),
5248
}
53-
}).next();
54-
49+
});
5550
match item {
5651
Some((idx, res)) => {
5752
// always remove Ok or Err, if it's not the last Err continue looping
5853
drop(self.inner.remove(idx));
5954
match res {
6055
Ok(e) => {
6156
let rest = mem::replace(&mut self.inner, Vec::new());
62-
return Ok(Poll::Ready((e, rest)))
63-
},
57+
return Poll::Ready(Ok((e, rest)))
58+
}
6459
Err(e) => {
6560
if self.inner.is_empty() {
66-
return Err(e)
61+
return Poll::Ready(Err(e))
6762
}
68-
},
63+
}
6964
}
7065
}
7166
None => {
7267
// based on the filter above, nothing is ready, return
73-
return Ok(Poll::Pending)
74-
},
68+
return Poll::Pending
69+
}
7570
}
7671
}
7772
}
7873
}
74+
75+
impl<Fut: TryFuture + Unpin> FromIterator<Fut> for SelectOk<Fut> {
76+
fn from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self {
77+
select_ok(iter)
78+
}
79+
}

futures/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,6 @@ pub mod future {
235235
Remote, RemoteHandle,
236236
// For FutureExt:
237237
CatchUnwind, Shared,
238-
239-
// ToDo: SelectOk, select_ok
240238
};
241239

242240
pub use futures_util::try_future::{
@@ -254,6 +252,7 @@ pub mod future {
254252
#[cfg(feature = "alloc")]
255253
pub use futures_util::try_future::{
256254
try_join_all, TryJoinAll,
255+
select_ok, SelectOk,
257256
};
258257
}
259258

futures/tests_disabled/select_ok.rs renamed to futures/tests/select_ok.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use futures::executor::block_on;
2+
use futures::future::{err, ok, select_ok};
23

34
#[test]
45
fn ignore_err() {

0 commit comments

Comments
 (0)