@@ -6,8 +6,8 @@ use std::task::{Context, Poll};
6
6
use std:: thread;
7
7
use std:: time:: { Duration , Instant } ;
8
8
9
+ use async_lock:: OnceCell ;
9
10
use futures_lite:: pin;
10
- use once_cell:: sync:: Lazy ;
11
11
use waker_fn:: waker_fn;
12
12
13
13
use crate :: reactor:: Reactor ;
@@ -16,25 +16,29 @@ use crate::reactor::Reactor;
16
16
static BLOCK_ON_COUNT : AtomicUsize = AtomicUsize :: new ( 0 ) ;
17
17
18
18
/// Unparker for the "async-io" thread.
19
- static UNPARKER : Lazy < parking:: Unparker > = Lazy :: new ( || {
20
- let ( parker, unparker) = parking:: pair ( ) ;
21
-
22
- // Spawn a helper thread driving the reactor.
23
- //
24
- // Note that this thread is not exactly necessary, it's only here to help push things
25
- // forward if there are no `Parker`s around or if `Parker`s are just idling and never
26
- // parking.
27
- thread:: Builder :: new ( )
28
- . name ( "async-io" . to_string ( ) )
29
- . spawn ( move || main_loop ( parker) )
30
- . expect ( "cannot spawn async-io thread" ) ;
31
-
32
- unparker
33
- } ) ;
19
+ fn unparker ( ) -> & ' static parking:: Unparker {
20
+ static UNPARKER : OnceCell < parking:: Unparker > = OnceCell :: new ( ) ;
21
+
22
+ UNPARKER . get_or_init_blocking ( || {
23
+ let ( parker, unparker) = parking:: pair ( ) ;
24
+
25
+ // Spawn a helper thread driving the reactor.
26
+ //
27
+ // Note that this thread is not exactly necessary, it's only here to help push things
28
+ // forward if there are no `Parker`s around or if `Parker`s are just idling and never
29
+ // parking.
30
+ thread:: Builder :: new ( )
31
+ . name ( "async-io" . to_string ( ) )
32
+ . spawn ( move || main_loop ( parker) )
33
+ . expect ( "cannot spawn async-io thread" ) ;
34
+
35
+ unparker
36
+ } )
37
+ }
34
38
35
39
/// Initializes the "async-io" thread.
36
40
pub ( crate ) fn init ( ) {
37
- Lazy :: force ( & UNPARKER ) ;
41
+ let _ = unparker ( ) ;
38
42
}
39
43
40
44
/// The main loop for the "async-io" thread.
@@ -109,7 +113,7 @@ pub fn block_on<T>(future: impl Future<Output = T>) -> T {
109
113
// Make sure to decrement `BLOCK_ON_COUNT` at the end and wake the "async-io" thread.
110
114
let _guard = CallOnDrop ( || {
111
115
BLOCK_ON_COUNT . fetch_sub ( 1 , Ordering :: SeqCst ) ;
112
- UNPARKER . unpark ( ) ;
116
+ unparker ( ) . unpark ( ) ;
113
117
} ) ;
114
118
115
119
// Parker and unparker for notifying the current thread.
@@ -205,7 +209,7 @@ pub fn block_on<T>(future: impl Future<Output = T>) -> T {
205
209
206
210
// Unpark the "async-io" thread in case no other thread is ready to start
207
211
// processing I/O events. This way we prevent a potential latency spike.
208
- UNPARKER . unpark ( ) ;
212
+ unparker ( ) . unpark ( ) ;
209
213
210
214
// Wait for a notification.
211
215
p. park ( ) ;
0 commit comments