@@ -22,7 +22,7 @@ use stream::StreamWatcher;
2222use super :: { Loop , Request , UvError , Buf , status_to_io_result,
2323 uv_error_to_io_error, UvHandle , slice_to_uv_buf,
2424 wait_until_woken_after, wakeup} ;
25- use timeout:: { AccessTimeout , AcceptTimeout , ConnectCtx } ;
25+ use timeout:: { AccessTimeout , ConnectCtx , AcceptTimeout } ;
2626use uvio:: UvIoFactory ;
2727use uvll;
2828
@@ -158,20 +158,20 @@ pub struct TcpWatcher {
158158 // stream object, so we use these access guards in order to arbitrate among
159159 // multiple concurrent reads and writes. Note that libuv *can* read and
160160 // 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 < ( ) > ,
163163}
164164
165165pub struct TcpListener {
166166 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 ,
170168}
171169
172170pub 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 ,
175175}
176176
177177// TCP watchers (clients/streams)
@@ -192,8 +192,8 @@ impl TcpWatcher {
192192 handle : handle,
193193 stream : StreamWatcher :: new ( handle, true ) ,
194194 refcount : Refcount :: new ( ) ,
195- read_access : AccessTimeout :: new ( ) ,
196- write_access : AccessTimeout :: new ( ) ,
195+ read_access : AccessTimeout :: new ( ( ) ) ,
196+ write_access : AccessTimeout :: new ( ( ) ) ,
197197 }
198198 }
199199
@@ -291,7 +291,7 @@ impl rtio::RtioTcpStream for TcpWatcher {
291291 let task = {
292292 let m = self . fire_homing_missile ( ) ;
293293 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 )
295295 } ;
296296 let _ = task. map ( |t| t. reawaken ( ) ) ;
297297 Ok ( ( ) )
@@ -354,12 +354,9 @@ impl TcpListener {
354354 assert_eq ! ( unsafe {
355355 uvll:: uv_tcp_init( io. uv_loop( ) , handle)
356356 } , 0 ) ;
357- let ( tx, rx) = channel ( ) ;
358357 let l = box TcpListener {
359358 home : io. make_handle ( ) ,
360359 handle : handle,
361- outgoing : tx,
362- incoming : rx,
363360 } ;
364361 let mut storage = unsafe { mem:: zeroed ( ) } ;
365362 let _len = addr_to_sockaddr ( address, & mut storage) ;
@@ -392,15 +389,19 @@ impl rtio::RtioSocket for TcpListener {
392389impl rtio:: RtioTcpListener for TcpListener {
393390 fn listen ( self : Box < TcpListener > )
394391 -> Result < Box < rtio:: RtioTcpAcceptor + Send > , IoError > {
392+ let _m = self . fire_homing_missile ( ) ;
393+
395394 // 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 _ ;
400402
401- let _m = acceptor. fire_homing_missile ( ) ;
402403 // 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) } {
404405 0 => Ok ( acceptor as Box < rtio:: RtioTcpAcceptor + Send > ) ,
405406 n => Err ( uv_error_to_io_error ( UvError ( n) ) ) ,
406407 }
@@ -409,7 +410,7 @@ impl rtio::RtioTcpListener for TcpListener {
409410
410411extern fn listen_cb ( server : * mut uvll:: uv_stream_t , status : c_int ) {
411412 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) } ;
413414 let msg = match status {
414415 0 => {
415416 let loop_ = Loop :: wrap ( unsafe {
@@ -421,11 +422,15 @@ extern fn listen_cb(server: *mut uvll::uv_stream_t, status: c_int) {
421422 }
422423 n => Err ( uv_error_to_io_error ( UvError ( n) ) )
423424 } ;
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) ; }
425428}
426429
427430impl Drop for TcpListener {
428431 fn drop ( & mut self ) {
432+ if self . handle . is_null ( ) { return }
433+
429434 let _m = self . fire_homing_missile ( ) ;
430435 self . close ( ) ;
431436 }
@@ -434,40 +439,68 @@ impl Drop for TcpListener {
434439// TCP acceptors (bound servers)
435440
436441impl 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 }
438443}
439444
440445impl rtio:: RtioSocket for TcpAcceptor {
441446 fn socket_name ( & mut self ) -> Result < rtio:: SocketAddr , IoError > {
442447 let _m = self . fire_homing_missile ( ) ;
443- socket_name ( Tcp , self . listener . handle )
448+ socket_name ( Tcp , self . handle )
444449 }
445450}
446451
452+ impl UvHandle < uvll:: uv_tcp_t > for TcpAcceptor {
453+ fn uv_handle ( & self ) -> * mut uvll:: uv_tcp_t { self . handle }
454+ }
455+
447456impl rtio:: RtioTcpAcceptor for TcpAcceptor {
448457 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_)
450461 }
451462
452463 fn accept_simultaneously ( & mut self ) -> Result < ( ) , IoError > {
453464 let _m = self . fire_homing_missile ( ) ;
454465 status_to_io_result ( unsafe {
455- uvll:: uv_tcp_simultaneous_accepts ( self . listener . handle , 1 )
466+ uvll:: uv_tcp_simultaneous_accepts ( self . handle , 1 )
456467 } )
457468 }
458469
459470 fn dont_accept_simultaneously ( & mut self ) -> Result < ( ) , IoError > {
460471 let _m = self . fire_homing_missile ( ) ;
461472 status_to_io_result ( unsafe {
462- uvll:: uv_tcp_simultaneous_accepts ( self . listener . handle , 0 )
473+ uvll:: uv_tcp_simultaneous_accepts ( self . handle , 0 )
463474 } )
464475 }
465476
466477 fn set_timeout ( & mut self , ms : Option < u64 > ) {
467478 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 ( ) ;
471504 }
472505 }
473506}
@@ -482,8 +515,8 @@ pub struct UdpWatcher {
482515
483516 // See above for what these fields are
484517 refcount : Refcount ,
485- read_access : AccessTimeout ,
486- write_access : AccessTimeout ,
518+ read_access : AccessTimeout < ( ) > ,
519+ write_access : AccessTimeout < ( ) > ,
487520
488521 blocked_sender : Option < BlockedTask > ,
489522}
@@ -507,8 +540,8 @@ impl UdpWatcher {
507540 handle : unsafe { uvll:: malloc_handle ( uvll:: UV_UDP ) } ,
508541 home : io. make_handle ( ) ,
509542 refcount : Refcount :: new ( ) ,
510- read_access : AccessTimeout :: new ( ) ,
511- write_access : AccessTimeout :: new ( ) ,
543+ read_access : AccessTimeout :: new ( ( ) ) ,
544+ write_access : AccessTimeout :: new ( ( ) ) ,
512545 blocked_sender : None ,
513546 } ;
514547 assert_eq ! ( unsafe {
0 commit comments