1
1
use std:: fmt;
2
2
use std:: sync:: { Arc , Mutex } ;
3
+ use std:: time:: Duration ;
3
4
4
5
use mio:: { self , Evented } ;
5
- use once_cell:: sync:: Lazy ;
6
6
use slab:: Slab ;
7
7
8
8
use crate :: io;
9
+ use crate :: rt:: RUNTIME ;
9
10
use crate :: task:: { Context , Poll , Waker } ;
10
- use crate :: utils:: abort_on_panic;
11
11
12
12
/// Data associated with a registered I/O handle.
13
13
#[ derive( Debug ) ]
@@ -18,15 +18,18 @@ struct Entry {
18
18
/// Tasks that are blocked on reading from this I/O handle.
19
19
readers : Mutex < Vec < Waker > > ,
20
20
21
- /// Thasks that are blocked on writing to this I/O handle.
21
+ /// Tasks that are blocked on writing to this I/O handle.
22
22
writers : Mutex < Vec < Waker > > ,
23
23
}
24
24
25
25
/// The state of a networking driver.
26
- struct Reactor {
26
+ pub struct Reactor {
27
27
/// A mio instance that polls for new events.
28
28
poller : mio:: Poll ,
29
29
30
+ /// A list into which mio stores events.
31
+ events : Mutex < mio:: Events > ,
32
+
30
33
/// A collection of registered I/O handles.
31
34
entries : Mutex < Slab < Arc < Entry > > > ,
32
35
@@ -39,12 +42,13 @@ struct Reactor {
39
42
40
43
impl Reactor {
41
44
/// Creates a new reactor for polling I/O events.
42
- fn new ( ) -> io:: Result < Reactor > {
45
+ pub fn new ( ) -> io:: Result < Reactor > {
43
46
let poller = mio:: Poll :: new ( ) ?;
44
47
let notify_reg = mio:: Registration :: new2 ( ) ;
45
48
46
49
let mut reactor = Reactor {
47
50
poller,
51
+ events : Mutex :: new ( mio:: Events :: with_capacity ( 1000 ) ) ,
48
52
entries : Mutex :: new ( Slab :: new ( ) ) ,
49
53
notify_reg,
50
54
notify_token : mio:: Token ( 0 ) ,
@@ -92,72 +96,60 @@ impl Reactor {
92
96
Ok ( ( ) )
93
97
}
94
98
95
- // fn notify(&self) {
96
- // self.notify_reg
97
- // .1
98
- // .set_readiness(mio::Ready::readable())
99
- // .unwrap();
100
- // }
101
- }
99
+ /// Notifies the reactor so that polling stops blocking.
100
+ pub fn notify ( & self ) -> io:: Result < ( ) > {
101
+ self . notify_reg . 1 . set_readiness ( mio:: Ready :: readable ( ) )
102
+ }
103
+
104
+ /// Waits on the poller for new events and wakes up tasks blocked on I/O handles.
105
+ ///
106
+ /// Returns `Ok(true)` if at least one new task was woken.
107
+ pub fn poll ( & self , timeout : Option < Duration > ) -> io:: Result < bool > {
108
+ let mut events = self . events . lock ( ) . unwrap ( ) ;
102
109
103
- /// The state of the global networking driver.
104
- static REACTOR : Lazy < Reactor > = Lazy :: new ( || {
105
- // Spawn a thread that waits on the poller for new events and wakes up tasks blocked on I/O
106
- // handles.
107
- std:: thread:: Builder :: new ( )
108
- . name ( "async-std/net" . to_string ( ) )
109
- . spawn ( move || {
110
- // If the driver thread panics, there's not much we can do. It is not a
111
- // recoverable error and there is no place to propagate it into so we just abort.
112
- abort_on_panic ( || {
113
- main_loop ( ) . expect ( "async networking thread has panicked" ) ;
114
- } )
115
- } )
116
- . expect ( "cannot start a thread driving blocking tasks" ) ;
117
-
118
- Reactor :: new ( ) . expect ( "cannot initialize reactor" )
119
- } ) ;
120
-
121
- /// Waits on the poller for new events and wakes up tasks blocked on I/O handles.
122
- fn main_loop ( ) -> io:: Result < ( ) > {
123
- let reactor = & REACTOR ;
124
- let mut events = mio:: Events :: with_capacity ( 1000 ) ;
125
-
126
- loop {
127
110
// Block on the poller until at least one new event comes in.
128
- reactor . poller . poll ( & mut events, None ) ?;
111
+ self . poller . poll ( & mut events, timeout ) ?;
129
112
130
113
// Lock the entire entry table while we're processing new events.
131
- let entries = reactor. entries . lock ( ) . unwrap ( ) ;
114
+ let entries = self . entries . lock ( ) . unwrap ( ) ;
115
+
116
+ // The number of woken tasks.
117
+ let mut progress = false ;
132
118
133
119
for event in events. iter ( ) {
134
120
let token = event. token ( ) ;
135
121
136
- if token == reactor . notify_token {
122
+ if token == self . notify_token {
137
123
// If this is the notification token, we just need the notification state.
138
- reactor . notify_reg . 1 . set_readiness ( mio:: Ready :: empty ( ) ) ?;
124
+ self . notify_reg . 1 . set_readiness ( mio:: Ready :: empty ( ) ) ?;
139
125
} else {
140
126
// Otherwise, look for the entry associated with this token.
141
127
if let Some ( entry) = entries. get ( token. 0 ) {
142
128
// Set the readiness flags from this I/O event.
143
129
let readiness = event. readiness ( ) ;
144
130
145
131
// Wake up reader tasks blocked on this I/O handle.
146
- if !( readiness & reader_interests ( ) ) . is_empty ( ) {
132
+ let reader_interests = mio:: Ready :: all ( ) - mio:: Ready :: writable ( ) ;
133
+ if !( readiness & reader_interests) . is_empty ( ) {
147
134
for w in entry. readers . lock ( ) . unwrap ( ) . drain ( ..) {
148
135
w. wake ( ) ;
136
+ progress = true ;
149
137
}
150
138
}
151
139
152
140
// Wake up writer tasks blocked on this I/O handle.
153
- if !( readiness & writer_interests ( ) ) . is_empty ( ) {
141
+ let writer_interests = mio:: Ready :: all ( ) - mio:: Ready :: readable ( ) ;
142
+ if !( readiness & writer_interests) . is_empty ( ) {
154
143
for w in entry. writers . lock ( ) . unwrap ( ) . drain ( ..) {
155
144
w. wake ( ) ;
145
+ progress = true ;
156
146
}
157
147
}
158
148
}
159
149
}
160
150
}
151
+
152
+ Ok ( progress)
161
153
}
162
154
}
163
155
@@ -180,7 +172,8 @@ impl<T: Evented> Watcher<T> {
180
172
/// lifetime of the returned I/O handle.
181
173
pub fn new ( source : T ) -> Watcher < T > {
182
174
Watcher {
183
- entry : REACTOR
175
+ entry : RUNTIME
176
+ . reactor ( )
184
177
. register ( & source)
185
178
. expect ( "cannot register an I/O event source" ) ,
186
179
source : Some ( source) ,
@@ -264,7 +257,8 @@ impl<T: Evented> Watcher<T> {
264
257
#[ allow( dead_code) ]
265
258
pub fn into_inner ( mut self ) -> T {
266
259
let source = self . source . take ( ) . unwrap ( ) ;
267
- REACTOR
260
+ RUNTIME
261
+ . reactor ( )
268
262
. deregister ( & source, & self . entry )
269
263
. expect ( "cannot deregister I/O event source" ) ;
270
264
source
@@ -274,7 +268,8 @@ impl<T: Evented> Watcher<T> {
274
268
impl < T : Evented > Drop for Watcher < T > {
275
269
fn drop ( & mut self ) {
276
270
if let Some ( ref source) = self . source {
277
- REACTOR
271
+ RUNTIME
272
+ . reactor ( )
278
273
. deregister ( source, & self . entry )
279
274
. expect ( "cannot deregister I/O event source" ) ;
280
275
}
@@ -289,27 +284,3 @@ impl<T: Evented + fmt::Debug> fmt::Debug for Watcher<T> {
289
284
. finish ( )
290
285
}
291
286
}
292
-
293
- /// Returns a mask containing flags that interest tasks reading from I/O handles.
294
- #[ inline]
295
- fn reader_interests ( ) -> mio:: Ready {
296
- mio:: Ready :: all ( ) - mio:: Ready :: writable ( )
297
- }
298
-
299
- /// Returns a mask containing flags that interest tasks writing into I/O handles.
300
- #[ inline]
301
- fn writer_interests ( ) -> mio:: Ready {
302
- mio:: Ready :: writable ( ) | hup ( )
303
- }
304
-
305
- /// Returns a flag containing the hangup status.
306
- #[ inline]
307
- fn hup ( ) -> mio:: Ready {
308
- #[ cfg( unix) ]
309
- let ready = mio:: unix:: UnixReady :: hup ( ) . into ( ) ;
310
-
311
- #[ cfg( not( unix) ) ]
312
- let ready = mio:: Ready :: empty ( ) ;
313
-
314
- ready
315
- }
0 commit comments