@@ -22,7 +22,7 @@ use stream::StreamWatcher;
22
22
use super :: { Loop , Request , UvError , Buf , status_to_io_result,
23
23
uv_error_to_io_error, UvHandle , slice_to_uv_buf,
24
24
wait_until_woken_after, wakeup} ;
25
- use timeout:: { AccessTimeout , AcceptTimeout , ConnectCtx } ;
25
+ use timeout:: { AccessTimeout , ConnectCtx , AcceptTimeout } ;
26
26
use uvio:: UvIoFactory ;
27
27
use uvll;
28
28
@@ -158,20 +158,20 @@ pub struct TcpWatcher {
158
158
// stream object, so we use these access guards in order to arbitrate among
159
159
// multiple concurrent reads and writes. Note that libuv *can* read and
160
160
// write simultaneously, it just can't read and read simultaneously.
161
- read_access : AccessTimeout ,
162
- write_access : AccessTimeout ,
161
+ read_access : AccessTimeout < ( ) > ,
162
+ write_access : AccessTimeout < ( ) > ,
163
163
}
164
164
165
165
pub struct TcpListener {
166
166
home : HomeHandle ,
167
- handle : * mut uvll:: uv_pipe_t ,
168
- outgoing : Sender < Result < Box < rtio:: RtioTcpStream + Send > , IoError > > ,
169
- incoming : Receiver < Result < Box < rtio:: RtioTcpStream + Send > , IoError > > ,
167
+ handle : * mut uvll:: uv_tcp_t ,
170
168
}
171
169
172
170
pub struct TcpAcceptor {
173
- listener : Box < TcpListener > ,
174
- timeout : AcceptTimeout ,
171
+ home : HomeHandle ,
172
+ handle : * mut uvll:: uv_tcp_t ,
173
+ access : AcceptTimeout < Box < rtio:: RtioTcpStream + Send > > ,
174
+ refcount : Refcount ,
175
175
}
176
176
177
177
// TCP watchers (clients/streams)
@@ -192,8 +192,8 @@ impl TcpWatcher {
192
192
handle : handle,
193
193
stream : StreamWatcher :: new ( handle, true ) ,
194
194
refcount : Refcount :: new ( ) ,
195
- read_access : AccessTimeout :: new ( ) ,
196
- write_access : AccessTimeout :: new ( ) ,
195
+ read_access : AccessTimeout :: new ( ( ) ) ,
196
+ write_access : AccessTimeout :: new ( ( ) ) ,
197
197
}
198
198
}
199
199
@@ -291,7 +291,7 @@ impl rtio::RtioTcpStream for TcpWatcher {
291
291
let task = {
292
292
let m = self . fire_homing_missile ( ) ;
293
293
self . read_access . access . close ( & m) ;
294
- self . stream . cancel_read ( uvll:: EOF as libc:: ssize_t )
294
+ self . stream . cancel_read ( uvll:: EOF as libc:: ssize_t )
295
295
} ;
296
296
let _ = task. map ( |t| t. reawaken ( ) ) ;
297
297
Ok ( ( ) )
@@ -354,12 +354,9 @@ impl TcpListener {
354
354
assert_eq ! ( unsafe {
355
355
uvll:: uv_tcp_init( io. uv_loop( ) , handle)
356
356
} , 0 ) ;
357
- let ( tx, rx) = channel ( ) ;
358
357
let l = box TcpListener {
359
358
home : io. make_handle ( ) ,
360
359
handle : handle,
361
- outgoing : tx,
362
- incoming : rx,
363
360
} ;
364
361
let mut storage = unsafe { mem:: zeroed ( ) } ;
365
362
let _len = addr_to_sockaddr ( address, & mut storage) ;
@@ -392,15 +389,19 @@ impl rtio::RtioSocket for TcpListener {
392
389
impl rtio:: RtioTcpListener for TcpListener {
393
390
fn listen ( self : Box < TcpListener > )
394
391
-> Result < Box < rtio:: RtioTcpAcceptor + Send > , IoError > {
392
+ let _m = self . fire_homing_missile ( ) ;
393
+
395
394
// create the acceptor object from ourselves
396
- let mut acceptor = box TcpAcceptor {
397
- listener : self ,
398
- timeout : AcceptTimeout :: new ( ) ,
399
- } ;
395
+ let acceptor = ( box TcpAcceptor {
396
+ handle : self . handle ,
397
+ home : self . home . clone ( ) ,
398
+ access : AcceptTimeout :: new ( ) ,
399
+ refcount : Refcount :: new ( ) ,
400
+ } ) . install ( ) ;
401
+ self . handle = 0 as * mut _ ;
400
402
401
- let _m = acceptor. fire_homing_missile ( ) ;
402
403
// FIXME: the 128 backlog should be configurable
403
- match unsafe { uvll:: uv_listen ( acceptor. listener . handle , 128 , listen_cb) } {
404
+ match unsafe { uvll:: uv_listen ( acceptor. handle , 128 , listen_cb) } {
404
405
0 => Ok ( acceptor as Box < rtio:: RtioTcpAcceptor + Send > ) ,
405
406
n => Err ( uv_error_to_io_error ( UvError ( n) ) ) ,
406
407
}
@@ -409,7 +410,7 @@ impl rtio::RtioTcpListener for TcpListener {
409
410
410
411
extern fn listen_cb ( server : * mut uvll:: uv_stream_t , status : c_int ) {
411
412
assert ! ( status != uvll:: ECANCELED ) ;
412
- let tcp: & mut TcpListener = unsafe { UvHandle :: from_uv_handle ( & server) } ;
413
+ let tcp: & mut TcpAcceptor = unsafe { UvHandle :: from_uv_handle ( & server) } ;
413
414
let msg = match status {
414
415
0 => {
415
416
let loop_ = Loop :: wrap ( unsafe {
@@ -421,11 +422,15 @@ extern fn listen_cb(server: *mut uvll::uv_stream_t, status: c_int) {
421
422
}
422
423
n => Err ( uv_error_to_io_error ( UvError ( n) ) )
423
424
} ;
424
- tcp. outgoing . send ( msg) ;
425
+
426
+ // If we're running then we have exclusive access, so the unsafe_get() is ok
427
+ unsafe { tcp. access . push ( msg) ; }
425
428
}
426
429
427
430
impl Drop for TcpListener {
428
431
fn drop ( & mut self ) {
432
+ if self . handle . is_null ( ) { return }
433
+
429
434
let _m = self . fire_homing_missile ( ) ;
430
435
self . close ( ) ;
431
436
}
@@ -434,40 +439,68 @@ impl Drop for TcpListener {
434
439
// TCP acceptors (bound servers)
435
440
436
441
impl HomingIO for TcpAcceptor {
437
- fn home < ' r > ( & ' r mut self ) -> & ' r mut HomeHandle { self . listener . home ( ) }
442
+ fn home < ' r > ( & ' r mut self ) -> & ' r mut HomeHandle { & mut self . home }
438
443
}
439
444
440
445
impl rtio:: RtioSocket for TcpAcceptor {
441
446
fn socket_name ( & mut self ) -> Result < rtio:: SocketAddr , IoError > {
442
447
let _m = self . fire_homing_missile ( ) ;
443
- socket_name ( Tcp , self . listener . handle )
448
+ socket_name ( Tcp , self . handle )
444
449
}
445
450
}
446
451
452
+ impl UvHandle < uvll:: uv_tcp_t > for TcpAcceptor {
453
+ fn uv_handle ( & self ) -> * mut uvll:: uv_tcp_t { self . handle }
454
+ }
455
+
447
456
impl rtio:: RtioTcpAcceptor for TcpAcceptor {
448
457
fn accept ( & mut self ) -> Result < Box < rtio:: RtioTcpStream + Send > , IoError > {
449
- self . timeout . accept ( & self . listener . incoming )
458
+ let m = self . fire_homing_missile ( ) ;
459
+ let loop_ = self . uv_loop ( ) ;
460
+ self . access . accept ( m, & loop_)
450
461
}
451
462
452
463
fn accept_simultaneously ( & mut self ) -> Result < ( ) , IoError > {
453
464
let _m = self . fire_homing_missile ( ) ;
454
465
status_to_io_result ( unsafe {
455
- uvll:: uv_tcp_simultaneous_accepts ( self . listener . handle , 1 )
466
+ uvll:: uv_tcp_simultaneous_accepts ( self . handle , 1 )
456
467
} )
457
468
}
458
469
459
470
fn dont_accept_simultaneously ( & mut self ) -> Result < ( ) , IoError > {
460
471
let _m = self . fire_homing_missile ( ) ;
461
472
status_to_io_result ( unsafe {
462
- uvll:: uv_tcp_simultaneous_accepts ( self . listener . handle , 0 )
473
+ uvll:: uv_tcp_simultaneous_accepts ( self . handle , 0 )
463
474
} )
464
475
}
465
476
466
477
fn set_timeout ( & mut self , ms : Option < u64 > ) {
467
478
let _m = self . fire_homing_missile ( ) ;
468
- match ms {
469
- None => self . timeout . clear ( ) ,
470
- Some ( ms) => self . timeout . set_timeout ( ms, & mut * self . listener ) ,
479
+ let loop_ = self . uv_loop ( ) ;
480
+ self . access . set_timeout ( ms, & loop_, & self . home ) ;
481
+ }
482
+
483
+ fn clone ( & self ) -> Box < rtio:: RtioTcpAcceptor + Send > {
484
+ box TcpAcceptor {
485
+ refcount : self . refcount . clone ( ) ,
486
+ home : self . home . clone ( ) ,
487
+ handle : self . handle ,
488
+ access : self . access . clone ( ) ,
489
+ } as Box < rtio:: RtioTcpAcceptor + Send >
490
+ }
491
+
492
+ fn close_accept ( & mut self ) -> Result < ( ) , IoError > {
493
+ let m = self . fire_homing_missile ( ) ;
494
+ self . access . close ( m) ;
495
+ Ok ( ( ) )
496
+ }
497
+ }
498
+
499
+ impl Drop for TcpAcceptor {
500
+ fn drop ( & mut self ) {
501
+ let _m = self . fire_homing_missile ( ) ;
502
+ if self . refcount . decrement ( ) {
503
+ self . close ( ) ;
471
504
}
472
505
}
473
506
}
@@ -482,8 +515,8 @@ pub struct UdpWatcher {
482
515
483
516
// See above for what these fields are
484
517
refcount : Refcount ,
485
- read_access : AccessTimeout ,
486
- write_access : AccessTimeout ,
518
+ read_access : AccessTimeout < ( ) > ,
519
+ write_access : AccessTimeout < ( ) > ,
487
520
488
521
blocked_sender : Option < BlockedTask > ,
489
522
}
@@ -507,8 +540,8 @@ impl UdpWatcher {
507
540
handle : unsafe { uvll:: malloc_handle ( uvll:: UV_UDP ) } ,
508
541
home : io. make_handle ( ) ,
509
542
refcount : Refcount :: new ( ) ,
510
- read_access : AccessTimeout :: new ( ) ,
511
- write_access : AccessTimeout :: new ( ) ,
543
+ read_access : AccessTimeout :: new ( ( ) ) ,
544
+ write_access : AccessTimeout :: new ( ( ) ) ,
512
545
blocked_sender : None ,
513
546
} ;
514
547
assert_eq ! ( unsafe {
0 commit comments