23
23
24
24
use std:: collections:: HashMap ;
25
25
use std:: fmt:: { Debug , Display , Formatter } ;
26
- use std:: io:: Write ;
27
26
use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
28
- use std:: os:: unix:: net:: UnixStream ;
29
- use std:: sync:: Arc ;
30
27
use std:: thread:: JoinHandle ;
31
28
use std:: time:: Duration ;
32
29
use std:: { io, thread} ;
33
30
34
31
use crossbeam_channel as chan;
35
32
36
- use crate :: poller:: { IoFail , IoType , Poll } ;
33
+ use crate :: poller:: { IoFail , IoType , Poll , Waker , WakerRecv , WakerSend } ;
37
34
use crate :: resource:: WriteError ;
38
35
use crate :: { Resource , Timer , Timestamp , WriteAtomic } ;
39
36
@@ -191,12 +188,12 @@ pub trait Handler: Send + Iterator<Item = Action<Self::Listener, Self::Transport
191
188
///
192
189
/// Apps running the [`Reactor`] can interface it and a [`Handler`] via use of the [`Controller`]
193
190
/// API.
194
- pub struct Reactor < C > {
191
+ pub struct Reactor < C , P : Poll > {
195
192
thread : JoinHandle < ( ) > ,
196
- controller : Controller < C > ,
193
+ controller : Controller < C , < P :: Waker as Waker > :: Send > ,
197
194
}
198
195
199
- impl < C > Reactor < C > {
196
+ impl < C , P : Poll > Reactor < C , P > {
200
197
/// Creates new reactor using provided [`Poll`] engine and a service exposing [`Handler`] API to
201
198
/// the reactor.
202
199
///
@@ -206,7 +203,7 @@ impl<C> Reactor<C> {
206
203
/// # Error
207
204
///
208
205
/// Errors with a system/OS error if it was impossible to spawn a thread.
209
- pub fn new < P : Poll , H : Handler < Command = C > > ( service : H , poller : P ) -> Result < Self , io:: Error >
206
+ pub fn new < H : Handler < Command = C > > ( service : H , poller : P ) -> Result < Self , io:: Error >
210
207
where
211
208
H : ' static ,
212
209
P : ' static ,
@@ -225,7 +222,7 @@ impl<C> Reactor<C> {
225
222
/// # Error
226
223
///
227
224
/// Errors with a system/OS error if it was impossible to spawn a thread.
228
- pub fn named < P : Poll , H : Handler < Command = C > > (
225
+ pub fn named < H : Handler < Command = C > > (
229
226
service : H ,
230
227
poller : P ,
231
228
thread_name : String ,
@@ -248,7 +245,7 @@ impl<C> Reactor<C> {
248
245
/// # Error
249
246
///
250
247
/// Errors with a system/OS error if it was impossible to spawn a thread.
251
- pub fn with < P : Poll , H : Handler < Command = C > > (
248
+ pub fn with < H : Handler < Command = C > > (
252
249
service : H ,
253
250
mut poller : P ,
254
251
builder : thread:: Builder ,
@@ -260,13 +257,11 @@ impl<C> Reactor<C> {
260
257
{
261
258
let ( ctl_send, ctl_recv) = chan:: unbounded ( ) ;
262
259
263
- let ( waker_writer, waker_reader) = UnixStream :: pair ( ) ?;
264
- waker_reader. set_nonblocking ( true ) ?;
265
- waker_writer. set_nonblocking ( true ) ?;
260
+ let ( waker_writer, waker_reader) = P :: Waker :: pair ( ) ?;
266
261
267
262
let controller = Controller {
268
263
ctl_send,
269
- waker : Arc :: new ( waker_writer) ,
264
+ waker : waker_writer,
270
265
} ;
271
266
272
267
#[ cfg( feature = "log" ) ]
@@ -306,7 +301,7 @@ impl<C> Reactor<C> {
306
301
/// running inside of its thread.
307
302
///
308
303
/// See [`Handler::Command`] for the details.
309
- pub fn controller ( & self ) -> Controller < C > { self . controller . clone ( ) }
304
+ pub fn controller ( & self ) -> Controller < C , < P :: Waker as Waker > :: Send > { self . controller . clone ( ) }
310
305
311
306
/// Joins the reactor thread.
312
307
pub fn join ( self ) -> thread:: Result < ( ) > { self . thread . join ( ) }
@@ -323,12 +318,12 @@ enum Ctl<C> {
323
318
/// API to the reactor itself for receiving reactor-generated events. This API is used by the
324
319
/// reactor to inform the service about incoming commands, sent via this [`Controller`] API (see
325
320
/// [`Handler::Command`] for the details).
326
- pub struct Controller < C > {
321
+ pub struct Controller < C , W : WakerSend > {
327
322
ctl_send : chan:: Sender < Ctl < C > > ,
328
- waker : Arc < UnixStream > ,
323
+ waker : W ,
329
324
}
330
325
331
- impl < C > Clone for Controller < C > {
326
+ impl < C , W : WakerSend > Clone for Controller < C , W > {
332
327
fn clone ( & self ) -> Self {
333
328
Controller {
334
329
ctl_send : self . ctl_send . clone ( ) ,
@@ -337,7 +332,7 @@ impl<C> Clone for Controller<C> {
337
332
}
338
333
}
339
334
340
- impl < C > Controller < C > {
335
+ impl < C , W : WakerSend > Controller < C , W > {
341
336
/// Send a command to the service inside a [`Reactor`] or a reactor [`Runtime`].
342
337
#[ allow( unused_mut) ] // because of the `log` feature gate
343
338
pub fn cmd ( & self , mut command : C ) -> Result < ( ) , io:: Error >
@@ -377,56 +372,9 @@ impl<C> Controller<C> {
377
372
}
378
373
379
374
fn wake ( & self ) -> io:: Result < ( ) > {
380
- use io:: ErrorKind :: * ;
381
-
382
375
#[ cfg( feature = "log" ) ]
383
376
log:: trace!( target: "reactor-controller" , "Wakening the reactor" ) ;
384
-
385
- loop {
386
- let mut waker = self . waker . as_ref ( ) ;
387
- match ( & mut waker) . write_all ( & [ 0x1 ] ) {
388
- Ok ( _) => return Ok ( ( ) ) ,
389
- Err ( e) if e. kind ( ) == WouldBlock => {
390
- #[ cfg( feature = "log" ) ]
391
- log:: error!( target: "reactor-controller" , "Waker write queue got overfilled, resetting and repeating..." ) ;
392
- reset_fd ( & self . waker . as_raw_fd ( ) ) ?;
393
- }
394
- Err ( e) if e. kind ( ) == Interrupted => {
395
- #[ cfg( feature = "log" ) ]
396
- log:: error!( target: "reactor-controller" , "Waker failure, repeating..." ) ;
397
- }
398
- Err ( e) => {
399
- #[ cfg( feature = "log" ) ]
400
- log:: error!( target: "reactor-controller" , "Waker error: {e}" ) ;
401
-
402
- return Err ( e) ;
403
- }
404
- }
405
- }
406
- }
407
- }
408
-
409
- fn reset_fd ( fd : & impl AsRawFd ) -> io:: Result < ( ) > {
410
- let mut buf = [ 0u8 ; 4096 ] ;
411
-
412
- loop {
413
- // We use a low-level "read" here because the alternative is to create a `UnixStream`
414
- // from the `RawFd`, which has "drop" semantics which we want to avoid.
415
- match unsafe {
416
- libc:: read ( fd. as_raw_fd ( ) , buf. as_mut_ptr ( ) as * mut libc:: c_void , buf. len ( ) )
417
- } {
418
- -1 => match io:: Error :: last_os_error ( ) {
419
- e if e. kind ( ) == io:: ErrorKind :: WouldBlock => return Ok ( ( ) ) ,
420
- e => {
421
- #[ cfg( feature = "log" ) ]
422
- log:: error!( target: "reactor-controller" , "Unable to reset waker queue: {e}" ) ;
423
-
424
- return Err ( e) ;
425
- }
426
- } ,
427
- 0 => return Ok ( ( ) ) ,
428
- _ => continue ,
429
- }
377
+ self . waker . wake ( )
430
378
}
431
379
}
432
380
@@ -440,13 +388,13 @@ fn reset_fd(fd: &impl AsRawFd) -> io::Result<()> {
440
388
pub struct Runtime < H : Handler , P : Poll > {
441
389
service : H ,
442
390
poller : P ,
443
- controller : Controller < H :: Command > ,
391
+ controller : Controller < H :: Command , < P :: Waker as Waker > :: Send > ,
444
392
ctl_recv : chan:: Receiver < Ctl < H :: Command > > ,
445
393
listener_map : HashMap < RawFd , <H :: Listener as Resource >:: Id > ,
446
394
transport_map : HashMap < RawFd , <H :: Transport as Resource >:: Id > ,
447
395
listeners : HashMap < <H :: Listener as Resource >:: Id , H :: Listener > ,
448
396
transports : HashMap < <H :: Transport as Resource >:: Id , H :: Transport > ,
449
- waker : UnixStream ,
397
+ waker : < P :: Waker as Waker > :: Recv ,
450
398
timeouts : Timer ,
451
399
}
452
400
@@ -456,13 +404,11 @@ impl<H: Handler, P: Poll> Runtime<H, P> {
456
404
pub fn with ( service : H , poller : P ) -> io:: Result < Self > {
457
405
let ( ctl_send, ctl_recv) = chan:: unbounded ( ) ;
458
406
459
- let ( waker_writer, waker_reader) = UnixStream :: pair ( ) ?;
460
- waker_reader. set_nonblocking ( true ) ?;
461
- waker_writer. set_nonblocking ( true ) ?;
407
+ let ( waker_writer, waker_reader) = P :: Waker :: pair ( ) ?;
462
408
463
409
let controller = Controller {
464
410
ctl_send,
465
- waker : Arc :: new ( waker_writer) ,
411
+ waker : waker_writer,
466
412
} ;
467
413
468
414
Ok ( Runtime {
@@ -483,7 +429,9 @@ impl<H: Handler, P: Poll> Runtime<H, P> {
483
429
/// running inside of its thread.
484
430
///
485
431
/// See [`Handler::Command`] for the details.
486
- pub fn controller ( & self ) -> Controller < H :: Command > { self . controller . clone ( ) }
432
+ pub fn controller ( & self ) -> Controller < H :: Command , <P :: Waker as Waker >:: Send > {
433
+ self . controller . clone ( )
434
+ }
487
435
488
436
fn run ( mut self ) {
489
437
loop {
@@ -565,7 +513,7 @@ impl<H: Handler, P: Poll> Runtime<H, P> {
565
513
#[ cfg( feature = "log" ) ]
566
514
log:: trace!( target: "reactor" , "Awoken by the controller" ) ;
567
515
568
- reset_fd ( & self . waker ) . expect ( "waker failure" ) ;
516
+ self . waker . reset ( ) ;
569
517
awoken = true ;
570
518
} else if let Some ( id) = self . listener_map . get ( & fd) {
571
519
match res {
@@ -803,7 +751,7 @@ mod test {
803
751
impl AsRawFd for DumbRes {
804
752
fn as_raw_fd ( & self ) -> RawFd { self . 0 . as_raw_fd ( ) }
805
753
}
806
- impl Write for DumbRes {
754
+ impl io :: Write for DumbRes {
807
755
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > { Ok ( buf. len ( ) ) }
808
756
fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
809
757
}
0 commit comments