@@ -55,6 +55,9 @@ struct Channel<T> {
55
55
/// Stream operations while the channel is empty and not closed.
56
56
stream_ops : Event ,
57
57
58
+ /// Sink operations while the channel is empty and not closed.
59
+ sink_ops : Event ,
60
+
58
61
/// The number of currently active `Sender`s.
59
62
sender_count : AtomicUsize ,
60
63
@@ -112,12 +115,15 @@ pub fn bounded<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
112
115
send_ops : Event :: new ( ) ,
113
116
recv_ops : Event :: new ( ) ,
114
117
stream_ops : Event :: new ( ) ,
118
+ sink_ops : Event :: new ( ) ,
115
119
sender_count : AtomicUsize :: new ( 1 ) ,
116
120
receiver_count : AtomicUsize :: new ( 1 ) ,
117
121
} ) ;
118
122
119
123
let s = Sender {
120
124
channel : channel. clone ( ) ,
125
+ listener : None ,
126
+ sending_msg : None ,
121
127
} ;
122
128
let r = Receiver {
123
129
channel,
@@ -151,12 +157,15 @@ pub fn unbounded<T>() -> (Sender<T>, Receiver<T>) {
151
157
send_ops : Event :: new ( ) ,
152
158
recv_ops : Event :: new ( ) ,
153
159
stream_ops : Event :: new ( ) ,
160
+ sink_ops : Event :: new ( ) ,
154
161
sender_count : AtomicUsize :: new ( 1 ) ,
155
162
receiver_count : AtomicUsize :: new ( 1 ) ,
156
163
} ) ;
157
164
158
165
let s = Sender {
159
166
channel : channel. clone ( ) ,
167
+ listener : None ,
168
+ sending_msg : None ,
160
169
} ;
161
170
let r = Receiver {
162
171
channel,
@@ -174,6 +183,11 @@ pub fn unbounded<T>() -> (Sender<T>, Receiver<T>) {
174
183
pub struct Sender < T > {
175
184
/// Inner channel state.
176
185
channel : Arc < Channel < T > > ,
186
+
187
+ /// Listens for a recv or close event to unblock this stream.
188
+ listener : Option < EventListener > ,
189
+
190
+ sending_msg : Option < T > ,
177
191
}
178
192
179
193
impl < T > Sender < T > {
@@ -421,6 +435,91 @@ impl<T> Sender<T> {
421
435
pub fn sender_count ( & self ) -> usize {
422
436
self . channel . sender_count . load ( Ordering :: SeqCst )
423
437
}
438
+
439
+ /// Attempts to send a message into the channel.
440
+ /// This method takes the message inside the `message` argument and buffer it if the channel is full.
441
+ /// This method returns `Pending` if the channel is full and `Ready(SendError<T>)` if it is closed.
442
+ /// # Panics
443
+ /// Panics if call this method with `None` message in the first call.
444
+ /// # Examples
445
+ ///
446
+ /// ```
447
+ /// use async_channel::{bounded, SendError};
448
+ /// use futures_lite::future;
449
+ /// use std::task::Poll;
450
+
451
+ /// future::block_on(async {
452
+ /// future::poll_fn(|cx| -> Poll<()> {
453
+ /// let (mut s, r) = bounded::<u32>(1);
454
+ /// assert_eq!(s.poll_send(cx, &mut Some(1)), Poll::Ready(Ok(())));
455
+ /// assert_eq!(s.poll_send(cx, &mut Some(2)), Poll::Pending);
456
+ /// drop(r);
457
+ /// assert_eq!(
458
+ /// s.poll_send(cx, &mut Some(3)),
459
+ /// Poll::Ready(Err(SendError(3)))
460
+ /// );
461
+ /// Poll::Ready(())
462
+ /// })
463
+ /// .await;
464
+ /// });
465
+ /// ```
466
+ pub fn poll_send (
467
+ & mut self ,
468
+ cx : & mut Context < ' _ > ,
469
+ msg : & mut Option < T > ,
470
+ ) -> Poll < Result < ( ) , SendError < T > > > {
471
+ // take() the message when calling this function for the first time.
472
+
473
+ if let Some ( msg) = msg. take ( ) {
474
+ self . sending_msg = Some ( msg) ;
475
+ }
476
+
477
+ loop {
478
+ // If this sink is listening for events, first wait for a notification.
479
+ if let Some ( listener) = & mut self . listener {
480
+ futures_core:: ready!( Pin :: new( listener) . poll( cx) ) ;
481
+ self . listener = None ;
482
+ }
483
+
484
+ loop {
485
+ let message = self . sending_msg . take ( ) . unwrap ( ) ;
486
+ // Attempt to send the item immediately
487
+ match self . try_send ( message) {
488
+ Ok ( _) => {
489
+ // Great! The item has been sent sucessfully.
490
+ // The stream is not blocked on an event - drop the listener.
491
+ self . listener = None ;
492
+ return Poll :: Ready ( Ok ( ( ) ) ) ;
493
+ }
494
+ Err ( e) => match e {
495
+ TrySendError :: Full ( item) => {
496
+ // The channel is full now.
497
+ // Store the item back to the struct for the next loop or polling.
498
+ self . sending_msg = Some ( item) ;
499
+ }
500
+ TrySendError :: Closed ( item) => {
501
+ // The channel is closed.
502
+ // The stream is not blocked on an event - drop the listener.
503
+ self . listener = None ;
504
+ return Poll :: Ready ( Err ( SendError ( item) ) ) ;
505
+ }
506
+ } ,
507
+ }
508
+
509
+ // Receiving failed - now start listening for notifications or wait for one.
510
+ match & mut self . listener {
511
+ Some ( _) => {
512
+ // Create a listener and try sending the message again.
513
+ break ;
514
+ }
515
+ None => {
516
+ // Go back to the outer loop to poll the listener.
517
+ self . listener = Some ( self . channel . sink_ops . listen ( ) ) ;
518
+ }
519
+ }
520
+ }
521
+ }
522
+ }
424
523
}
425
524
426
525
impl < T > Drop for Sender < T > {
@@ -449,6 +548,8 @@ impl<T> Clone for Sender<T> {
449
548
450
549
Sender {
451
550
channel : self . channel . clone ( ) ,
551
+ listener : None ,
552
+ sending_msg : None ,
452
553
}
453
554
}
454
555
}
@@ -497,6 +598,8 @@ impl<T> Receiver<T> {
497
598
// message or gets canceled, it will notify another blocked send operation.
498
599
self . channel . send_ops . notify ( 1 ) ;
499
600
601
+ self . channel . sink_ops . notify ( usize:: MAX ) ;
602
+
500
603
Ok ( msg)
501
604
}
502
605
Err ( PopError :: Empty ) => Err ( TryRecvError :: Empty ) ,
@@ -725,6 +828,7 @@ impl<T> Drop for Receiver<T> {
725
828
if self . channel . receiver_count . fetch_sub ( 1 , Ordering :: AcqRel ) == 1 {
726
829
self . channel . close ( ) ;
727
830
}
831
+ self . channel . sink_ops . notify ( usize:: MAX ) ;
728
832
}
729
833
}
730
834
0 commit comments