@@ -2,12 +2,15 @@ use crate::future::{Either, TryFutureExt};
2
2
use core:: pin:: Pin ;
3
3
use futures_core:: future:: { Future , TryFuture } ;
4
4
use futures_core:: task:: { Context , Poll } ;
5
+ use rand:: rngs:: SmallRng ;
6
+ use rand:: Rng ;
5
7
6
8
/// Future for the [`try_select()`] function.
7
9
#[ must_use = "futures do nothing unless you `.await` or poll them" ]
8
10
#[ derive( Debug ) ]
9
11
pub struct TrySelect < A , B > {
10
12
inner : Option < ( A , B ) > ,
13
+ rng : SmallRng ,
11
14
}
12
15
13
16
impl < A : Unpin , B : Unpin > Unpin for TrySelect < A , B > { }
@@ -24,6 +27,9 @@ type EitherErr<A, B> = Either<(<A as TryFuture>::Error, B), (<B as TryFuture>::E
24
27
/// Note that this function consumes the receiving futures and returns a
25
28
/// wrapped version of them.
26
29
///
30
+ /// If both futures are ready when this is polled, the winner will be pseudo-randomly
31
+ /// selected.
32
+ ///
27
33
/// Also note that if both this and the second future have the same
28
34
/// success/error type you can use the `Either::factor_first` method to
29
35
/// conveniently extract out the value at the end.
57
63
{
58
64
super :: assert_future :: < Result < EitherOk < A , B > , EitherErr < A , B > > , _ > ( TrySelect {
59
65
inner : Some ( ( future1, future2) ) ,
66
+ rng : crate :: gen_rng ( ) ,
60
67
} )
61
68
}
62
69
@@ -69,17 +76,26 @@ where
69
76
70
77
fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
71
78
let ( mut a, mut b) = self . inner . take ( ) . expect ( "cannot poll Select twice" ) ;
72
- match a. try_poll_unpin ( cx) {
73
- Poll :: Ready ( Err ( x) ) => Poll :: Ready ( Err ( Either :: Left ( ( x, b) ) ) ) ,
74
- Poll :: Ready ( Ok ( x) ) => Poll :: Ready ( Ok ( Either :: Left ( ( x, b) ) ) ) ,
75
- Poll :: Pending => match b. try_poll_unpin ( cx) {
76
- Poll :: Ready ( Err ( x) ) => Poll :: Ready ( Err ( Either :: Right ( ( x, a) ) ) ) ,
77
- Poll :: Ready ( Ok ( x) ) => Poll :: Ready ( Ok ( Either :: Right ( ( x, a) ) ) ) ,
78
- Poll :: Pending => {
79
- self . inner = Some ( ( a, b) ) ;
80
- Poll :: Pending
79
+ macro_rules! poll_wrap {
80
+ ( $poll_first: expr, $poll_second: expr, $wrap_first: expr, $wrap_second: expr) => {
81
+ match $poll_first. try_poll_unpin( cx) {
82
+ Poll :: Ready ( Err ( x) ) => Poll :: Ready ( Err ( $wrap_first( ( x, $poll_second) ) ) ) ,
83
+ Poll :: Ready ( Ok ( x) ) => Poll :: Ready ( Ok ( $wrap_first( ( x, $poll_second) ) ) ) ,
84
+ Poll :: Pending => match $poll_second. try_poll_unpin( cx) {
85
+ Poll :: Ready ( Err ( x) ) => Poll :: Ready ( Err ( $wrap_second( ( x, $poll_first) ) ) ) ,
86
+ Poll :: Ready ( Ok ( x) ) => Poll :: Ready ( Ok ( $wrap_second( ( x, $poll_first) ) ) ) ,
87
+ Poll :: Pending => {
88
+ self . inner = Some ( ( a, b) ) ;
89
+ Poll :: Pending
90
+ }
91
+ } ,
81
92
}
82
- } ,
93
+ } ;
94
+ }
95
+ if self . rng . gen :: < bool > ( ) {
96
+ poll_wrap ! ( a, b, Either :: Left , Either :: Right )
97
+ } else {
98
+ poll_wrap ! ( b, a, Either :: Right , Either :: Left )
83
99
}
84
100
}
85
101
}
0 commit comments