@@ -41,7 +41,6 @@ use std::usize;
41
41
use concurrent_queue:: { ConcurrentQueue , PopError , PushError } ;
42
42
use event_listener:: { Event , EventListener } ;
43
43
use futures_core:: stream:: Stream ;
44
- use futures_sink:: Sink ;
45
44
46
45
struct Channel < T > {
47
46
/// Inner message queue.
@@ -56,6 +55,9 @@ struct Channel<T> {
56
55
/// Stream operations while the channel is empty and not closed.
57
56
stream_ops : Event ,
58
57
58
+ /// Sink operations while the channel is empty and not closed.
59
+ sink_ops : Event ,
60
+
59
61
/// The number of currently active `Sender`s.
60
62
sender_count : AtomicUsize ,
61
63
@@ -113,13 +115,15 @@ pub fn bounded<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
113
115
send_ops : Event :: new ( ) ,
114
116
recv_ops : Event :: new ( ) ,
115
117
stream_ops : Event :: new ( ) ,
118
+ sink_ops : Event :: new ( ) ,
116
119
sender_count : AtomicUsize :: new ( 1 ) ,
117
120
receiver_count : AtomicUsize :: new ( 1 ) ,
118
121
} ) ;
119
122
120
123
let s = Sender {
121
124
channel : channel. clone ( ) ,
122
125
listener : None ,
126
+ sending_msg : None ,
123
127
} ;
124
128
let r = Receiver {
125
129
channel,
@@ -153,13 +157,15 @@ pub fn unbounded<T>() -> (Sender<T>, Receiver<T>) {
153
157
send_ops : Event :: new ( ) ,
154
158
recv_ops : Event :: new ( ) ,
155
159
stream_ops : Event :: new ( ) ,
160
+ sink_ops : Event :: new ( ) ,
156
161
sender_count : AtomicUsize :: new ( 1 ) ,
157
162
receiver_count : AtomicUsize :: new ( 1 ) ,
158
163
} ) ;
159
164
160
165
let s = Sender {
161
166
channel : channel. clone ( ) ,
162
167
listener : None ,
168
+ sending_msg : None ,
163
169
} ;
164
170
let r = Receiver {
165
171
channel,
@@ -180,6 +186,8 @@ pub struct Sender<T> {
180
186
181
187
/// Listens for a recv or close event to unblock this stream.
182
188
listener : Option < EventListener > ,
189
+
190
+ sending_msg : Option < T > ,
183
191
}
184
192
185
193
impl < T > Sender < T > {
@@ -427,6 +435,91 @@ impl<T> Sender<T> {
427
435
pub fn sender_count ( & self ) -> usize {
428
436
self . channel . sender_count . load ( Ordering :: SeqCst )
429
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
+ }
430
523
}
431
524
432
525
impl < T > Drop for Sender < T > {
@@ -456,55 +549,11 @@ impl<T> Clone for Sender<T> {
456
549
Sender {
457
550
channel : self . channel . clone ( ) ,
458
551
listener : None ,
552
+ sending_msg : None ,
459
553
}
460
554
}
461
555
}
462
556
463
- impl < T > Sink < T > for Sender < T > {
464
- type Error = TrySendError < T > ;
465
-
466
- fn poll_ready ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) , Self :: Error > > {
467
- loop {
468
- if let Some ( l) = & mut self . listener {
469
- futures_core:: ready!( Pin :: new( l) . poll( cx) ) ;
470
- self . listener = None ;
471
- }
472
-
473
- if self . is_full ( ) {
474
- let listener = self . channel . recv_ops . listen ( ) ;
475
- self . listener = Some ( listener) ;
476
- } else {
477
- return Poll :: Ready ( Ok ( ( ) ) ) ;
478
- }
479
- }
480
- }
481
-
482
- fn poll_close ( self : Pin < & mut Self > , _: & mut Context < ' _ > ) -> Poll < Result < ( ) , Self :: Error > > {
483
- self . close ( ) ;
484
- Poll :: Ready ( Ok ( ( ) ) )
485
- }
486
-
487
- fn poll_flush ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) , Self :: Error > > {
488
- loop {
489
- if let Some ( l) = & mut self . listener {
490
- futures_core:: ready!( Pin :: new( l) . poll( cx) ) ;
491
- self . listener = None ;
492
- }
493
-
494
- if self . is_empty ( ) {
495
- return Poll :: Ready ( Ok ( ( ) ) ) ;
496
- } else {
497
- let listener = self . channel . recv_ops . listen ( ) ;
498
- self . listener = Some ( listener) ;
499
- }
500
- }
501
- }
502
-
503
- fn start_send ( self : Pin < & mut Self > , item : T ) -> Result < ( ) , Self :: Error > {
504
- self . try_send ( item)
505
- }
506
- }
507
-
508
557
/// The receiving side of a channel.
509
558
///
510
559
/// Receivers can be cloned and shared among threads. When all receivers associated with a channel
@@ -549,6 +598,8 @@ impl<T> Receiver<T> {
549
598
// message or gets canceled, it will notify another blocked send operation.
550
599
self . channel . send_ops . notify ( 1 ) ;
551
600
601
+ self . channel . sink_ops . notify ( usize:: MAX ) ;
602
+
552
603
Ok ( msg)
553
604
}
554
605
Err ( PopError :: Empty ) => Err ( TryRecvError :: Empty ) ,
@@ -777,6 +828,7 @@ impl<T> Drop for Receiver<T> {
777
828
if self . channel . receiver_count . fetch_sub ( 1 , Ordering :: AcqRel ) == 1 {
778
829
self . channel . close ( ) ;
779
830
}
831
+ self . channel . sink_ops . notify ( usize:: MAX ) ;
780
832
}
781
833
}
782
834
0 commit comments