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