@@ -9,6 +9,7 @@ use futures_core::task::{Context, Poll};
9
9
#[ derive( Debug ) ]
10
10
pub struct Select < A , B > {
11
11
inner : Option < ( A , B ) > ,
12
+ _biased : bool ,
12
13
}
13
14
14
15
impl < A : Unpin , B : Unpin > Unpin for Select < A , B > { }
@@ -23,7 +24,8 @@ impl<A: Unpin, B: Unpin> Unpin for Select<A, B> {}
23
24
/// wrapped version of them.
24
25
///
25
26
/// If both futures are ready when this is polled, the winner will be pseudo-randomly
26
- /// selected.
27
+ /// selected, unless the std feature is not enabled. If std is enabled, the first
28
+ /// argument will always win.
27
29
///
28
30
/// Also note that if both this and the second future have the same
29
31
/// output type you can use the `Either::factor_first` method to
91
93
{
92
94
assert_future :: < Either < ( A :: Output , B ) , ( B :: Output , A ) > , _ > ( Select {
93
95
inner : Some ( ( future1, future2) ) ,
96
+ _biased : false ,
97
+ } )
98
+ }
99
+
100
+ /// Waits for either one of two differently-typed futures to complete, giving preferential treatment to the first one.
101
+ ///
102
+ /// This function will return a new future which awaits for either one of both
103
+ /// futures to complete. The returned future will finish with both the value
104
+ /// resolved and a future representing the completion of the other work.
105
+ ///
106
+ /// Note that this function consumes the receiving futures and returns a
107
+ /// wrapped version of them.
108
+ ///
109
+ /// If both futures are ready when this is polled, the winner will always be the first argument.
110
+ ///
111
+ /// Also note that if both this and the second future have the same
112
+ /// output type you can use the `Either::factor_first` method to
113
+ /// conveniently extract out the value at the end.
114
+ ///
115
+ /// # Examples
116
+ ///
117
+ /// A simple example
118
+ ///
119
+ /// ```
120
+ /// # futures::executor::block_on(async {
121
+ /// use futures::{
122
+ /// pin_mut,
123
+ /// future::Either,
124
+ /// future::self,
125
+ /// };
126
+ ///
127
+ /// // These two futures have different types even though their outputs have the same type.
128
+ /// let future1 = async {
129
+ /// future::pending::<()>().await; // will never finish
130
+ /// 1
131
+ /// };
132
+ /// let future2 = async {
133
+ /// future::ready(2).await
134
+ /// };
135
+ ///
136
+ /// // 'select_biased' requires Future + Unpin bounds
137
+ /// pin_mut!(future1);
138
+ /// pin_mut!(future2);
139
+ ///
140
+ /// let value = match future::select_biased(future1, future2).await {
141
+ /// Either::Left((value1, _)) => value1, // `value1` is resolved from `future1`
142
+ /// // `_` represents `future2`
143
+ /// Either::Right((value2, _)) => value2, // `value2` is resolved from `future2`
144
+ /// // `_` represents `future1`
145
+ /// };
146
+ ///
147
+ /// assert!(value == 2);
148
+ /// # });
149
+ /// ```
150
+ ///
151
+ /// A more complex example
152
+ ///
153
+ /// ```
154
+ /// use futures::future::{self, Either, Future, FutureExt};
155
+ ///
156
+ /// // A poor-man's join implemented on top of select
157
+ ///
158
+ /// fn join<A, B>(a: A, b: B) -> impl Future<Output=(A::Output, B::Output)>
159
+ /// where A: Future + Unpin,
160
+ /// B: Future + Unpin,
161
+ /// {
162
+ /// future::select_biased(a, b).then(|either| {
163
+ /// match either {
164
+ /// Either::Left((x, b)) => b.map(move |y| (x, y)).left_future(),
165
+ /// Either::Right((y, a)) => a.map(move |x| (x, y)).right_future(),
166
+ /// }
167
+ /// })
168
+ /// }
169
+ /// ```
170
+ pub fn select_biased < A , B > ( future1 : A , future2 : B ) -> Select < A , B >
171
+ where
172
+ A : Future + Unpin ,
173
+ B : Future + Unpin ,
174
+ {
175
+ assert_future :: < Either < ( A :: Output , B ) , ( B :: Output , A ) > , _ > ( Select {
176
+ inner : Some ( ( future1, future2) ) ,
177
+ _biased : true ,
94
178
} )
95
179
}
96
180
@@ -111,6 +195,7 @@ where
111
195
Some ( value) => value,
112
196
}
113
197
}
198
+ let _biased = self . _biased ;
114
199
115
200
let ( a, b) = self . inner . as_mut ( ) . expect ( "cannot poll Select twice" ) ;
116
201
@@ -123,7 +208,7 @@ where
123
208
}
124
209
125
210
#[ cfg( feature = "std" ) ]
126
- if crate :: gen_index ( 2 ) == 0 {
211
+ if _biased || crate :: gen_index ( 2 ) == 0 {
127
212
poll_wrap ! ( a, unwrap_option( self . inner. take( ) ) . 1 , Either :: Left ) ;
128
213
poll_wrap ! ( b, unwrap_option( self . inner. take( ) ) . 0 , Either :: Right ) ;
129
214
} else {
0 commit comments