1
1
use super :: { Reactor , REACTOR } ;
2
2
3
- use core:: future:: Future ;
4
- use core:: pin:: pin;
5
- use core:: task:: Waker ;
6
- use core:: task:: { Context , Poll } ;
3
+ use std:: future:: Future ;
4
+ use std:: pin:: pin;
5
+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
7
6
use std:: sync:: Arc ;
8
- use std:: task:: Wake ;
7
+ use std:: task:: { Context , Poll , Wake , Waker } ;
9
8
10
9
/// Start the event loop
11
10
pub fn block_on < Fut > ( fut : Fut ) -> Fut :: Output
@@ -24,30 +23,50 @@ where
24
23
let mut fut = pin ! ( fut) ;
25
24
26
25
// Create a new context to be passed to the future.
27
- let waker = noop_waker ( ) ;
26
+ let root = Arc :: new ( RootWaker :: new ( ) ) ;
27
+ let waker = Waker :: from ( root. clone ( ) ) ;
28
28
let mut cx = Context :: from_waker ( & waker) ;
29
29
30
30
// Either the future completes and we return, or some IO is happening
31
31
// and we wait.
32
32
let res = loop {
33
33
match fut. as_mut ( ) . poll ( & mut cx) {
34
34
Poll :: Ready ( res) => break res,
35
- Poll :: Pending => reactor. block_until ( ) ,
35
+ Poll :: Pending => {
36
+ // If some non-pollable based future has marked the root task
37
+ // as awake, reset and poll again. otherwise, block until a
38
+ // pollable wakes a future.
39
+ if root. is_awake ( ) {
40
+ root. reset ( )
41
+ } else {
42
+ reactor. block_on_pollables ( )
43
+ }
44
+ }
36
45
}
37
46
} ;
38
47
// Clear the singleton
39
48
REACTOR . replace ( None ) ;
40
49
res
41
50
}
42
51
43
- /// Construct a new no-op waker
44
- // NOTE: we can remove this once <https://github.com/rust-lang/rust/issues/98286> lands
45
- fn noop_waker ( ) -> Waker {
46
- struct NoopWaker ;
47
-
48
- impl Wake for NoopWaker {
49
- fn wake ( self : Arc < Self > ) { }
52
+ struct RootWaker {
53
+ wake : AtomicBool ,
54
+ }
55
+ impl RootWaker {
56
+ fn new ( ) -> Self {
57
+ Self {
58
+ wake : AtomicBool :: new ( false ) ,
59
+ }
60
+ }
61
+ fn is_awake ( & self ) -> bool {
62
+ self . wake . load ( Ordering :: Relaxed )
63
+ }
64
+ fn reset ( & self ) {
65
+ self . wake . store ( false , Ordering :: Relaxed ) ;
66
+ }
67
+ }
68
+ impl Wake for RootWaker {
69
+ fn wake ( self : Arc < Self > ) {
70
+ self . wake . store ( true , Ordering :: Relaxed ) ;
50
71
}
51
-
52
- Waker :: from ( Arc :: new ( NoopWaker ) )
53
72
}
0 commit comments