2
2
//!
3
3
//! See also:
4
4
//! - [C API reference: Module coio](https://www.tarantool.io/en/doc/latest/dev_guide/reference_capi/coio/)
5
+ use std:: cell:: { Cell , RefCell } ;
6
+ use std:: collections:: VecDeque ;
5
7
use std:: convert:: TryFrom ;
6
8
use std:: ffi:: c_void;
7
- use std:: io;
8
- use std:: io:: { Read , Write } ;
9
+ use std:: io:: { self , Read , Write } ;
9
10
use std:: mem:: forget;
10
11
use std:: net:: { SocketAddr , TcpListener , TcpStream , ToSocketAddrs } ;
11
12
use std:: os:: raw:: c_char;
12
13
use std:: os:: unix:: io:: { AsRawFd , IntoRawFd , RawFd } ;
14
+ use std:: rc:: Rc ;
13
15
use std:: time:: Duration ;
14
16
15
17
use failure:: _core:: ptr:: null_mut;
18
+ use num_traits:: Zero ;
16
19
17
20
use crate :: error:: { Error , TarantoolError } ;
18
21
use crate :: ffi:: tarantool as ffi;
19
22
use crate :: fiber:: { unpack_callback, Cond } ;
20
- use std:: cell:: RefCell ;
21
- use std:: collections:: VecDeque ;
22
- use std:: rc:: Rc ;
23
23
24
24
const TIMEOUT_INFINITY : f64 = 365.0 * 86400.0 * 100.0 ;
25
25
@@ -294,6 +294,8 @@ pub fn channel<T>(capacity: usize) -> (Sender<T>, Receiver<T>) {
294
294
let chan = Rc :: new ( Chan {
295
295
buffer : RefCell :: new ( VecDeque :: with_capacity ( capacity) ) ,
296
296
cond : Cond :: new ( ) ,
297
+ tx_count : Cell :: new ( 1 ) ,
298
+ rx_is_active : Cell :: new ( true ) ,
297
299
} ) ;
298
300
299
301
( Sender ( chan. clone ( ) ) , Receiver ( chan) )
@@ -302,49 +304,65 @@ pub fn channel<T>(capacity: usize) -> (Sender<T>, Receiver<T>) {
302
304
pub struct Sender < T > ( Rc < Chan < T > > ) ;
303
305
304
306
impl < T > Sender < T > {
305
- pub fn send ( & self , value : T ) {
306
- self . 0 . send ( value)
307
+ pub fn send ( & self , value : T ) -> Result < ( ) , io:: Error > {
308
+ if !self . 0 . rx_is_active . get ( ) {
309
+ return Err ( io:: ErrorKind :: NotConnected . into ( ) ) ;
310
+ }
311
+
312
+ let was_empty = {
313
+ let mut buffer = self . 0 . buffer . borrow_mut ( ) ;
314
+ let was_empty = buffer. len ( ) == 0 ;
315
+ buffer. push_back ( value) ;
316
+ was_empty
317
+ } ;
318
+
319
+ if was_empty {
320
+ self . 0 . cond . signal ( ) ;
321
+ }
322
+
323
+ Ok ( ( ) )
307
324
}
308
325
}
309
326
310
327
impl < T > Clone for Sender < T > {
311
328
fn clone ( & self ) -> Self {
329
+ self . 0 . tx_count . set ( self . 0 . tx_count . get ( ) + 1 ) ;
312
330
Sender ( self . 0 . clone ( ) )
313
331
}
314
332
}
315
333
316
- pub struct Receiver < T > ( Rc < Chan < T > > ) ;
317
-
318
- impl < T > Receiver < T > {
319
- pub fn recv ( & self ) -> T {
320
- self . 0 . recv ( )
334
+ impl < T > Drop for Sender < T > {
335
+ fn drop ( & mut self ) {
336
+ self . 0 . tx_count . set ( self . 0 . tx_count . get ( ) - 1 ) ;
337
+ self . 0 . cond . signal ( ) ;
321
338
}
322
339
}
323
340
324
- struct Chan < T > {
325
- buffer : RefCell < VecDeque < T > > ,
326
- cond : Cond ,
327
- }
341
+ pub struct Receiver < T > ( Rc < Chan < T > > ) ;
328
342
329
- impl < T > Chan < T > {
330
- fn send ( & self , value : T ) {
331
- let was_empty = {
332
- let mut buffer = self . buffer . borrow_mut ( ) ;
333
- let was_empty = buffer. len ( ) == 0 ;
334
- buffer. push_back ( value) ;
335
- was_empty
336
- } ;
343
+ impl < T > Receiver < T > {
344
+ pub fn recv ( & self ) -> Option < T > {
345
+ if self . 0 . buffer . borrow ( ) . len ( ) == 0 {
346
+ if self . 0 . tx_count . get ( ) . is_zero ( ) {
347
+ return None ;
348
+ }
337
349
338
- if was_empty {
339
- self . cond . signal ( ) ;
350
+ self . 0 . cond . wait ( ) ;
340
351
}
341
- }
342
352
343
- fn recv ( & self ) -> T {
344
- while self . buffer . borrow ( ) . len ( ) == 0 {
345
- self . cond . wait ( ) ;
346
- }
353
+ self . 0 . buffer . borrow_mut ( ) . pop_front ( )
354
+ }
355
+ }
347
356
348
- self . buffer . borrow_mut ( ) . pop_front ( ) . unwrap ( )
357
+ impl < T > Drop for Receiver < T > {
358
+ fn drop ( & mut self ) {
359
+ self . 0 . rx_is_active . set ( false ) ;
349
360
}
350
361
}
362
+
363
+ struct Chan < T > {
364
+ buffer : RefCell < VecDeque < T > > ,
365
+ cond : Cond ,
366
+ tx_count : Cell < usize > ,
367
+ rx_is_active : Cell < bool > ,
368
+ }
0 commit comments