@@ -242,6 +242,35 @@ impl<T> Sender<T> {
242
242
}
243
243
}
244
244
245
+ /// Sends a message into this channel using the blocking strategy.
246
+ ///
247
+ /// If the channel is full, this method will block until there is room.
248
+ /// If the channel is closed, this method returns an error.
249
+ ///
250
+ /// # Blocking
251
+ ///
252
+ /// Rather than using asynchronous waiting, like the [`send`] method,
253
+ /// this method will block the current thread until the message is sent.
254
+ ///
255
+ /// This method should not be used in an asynchronous context. It is intended
256
+ /// to be used such that a channel can be used in both asynchronous and synchronous contexts.
257
+ /// Calling this method in an asynchronous context may result in deadlocks.
258
+ ///
259
+ /// # Examples
260
+ ///
261
+ /// ```
262
+ /// use async_channel::{unbounded, SendError};
263
+ ///
264
+ /// let (s, r) = unbounded();
265
+ ///
266
+ /// assert_eq!(s.send_blocking(1), Ok(()));
267
+ /// drop(r);
268
+ /// assert_eq!(s.send_blocking(2), Err(SendError(2)));
269
+ /// ```
270
+ pub fn send_blocking ( & self , msg : T ) -> Result < ( ) , SendError < T > > {
271
+ self . send ( msg) . wait ( )
272
+ }
273
+
245
274
/// Closes the channel.
246
275
///
247
276
/// Returns `true` if this call has closed the channel and it was not closed already.
@@ -511,6 +540,38 @@ impl<T> Receiver<T> {
511
540
}
512
541
}
513
542
543
+ /// Receives a message from the channel using the blocking strategy.
544
+ ///
545
+ /// If the channel is empty, this method waits until there is a message.
546
+ /// If the channel is closed, this method receives a message or returns an error if there are
547
+ /// no more messages.
548
+ ///
549
+ /// # Blocking
550
+ ///
551
+ /// Rather than using asynchronous waiting, like the [`recv`] method,
552
+ /// this method will block the current thread until the message is sent.
553
+ ///
554
+ /// This method should not be used in an asynchronous context. It is intended
555
+ /// to be used such that a channel can be used in both asynchronous and synchronous contexts.
556
+ /// Calling this method in an `async` block may result in deadlocks.
557
+ ///
558
+ /// # Examples
559
+ ///
560
+ /// ```
561
+ /// use async_channel::{unbounded, RecvError};
562
+ ///
563
+ /// let (s, r) = unbounded();
564
+ ///
565
+ /// assert_eq!(s.send_blocking(1), Ok(()));
566
+ /// drop(s);
567
+ ///
568
+ /// assert_eq!(r.recv_blocking(), Ok(1));
569
+ /// assert_eq!(r.recv_blocking(), Err(RecvError));
570
+ /// ```
571
+ pub fn recv_blocking ( & self ) -> Result < T , RecvError > {
572
+ self . recv ( ) . wait ( )
573
+ }
574
+
514
575
/// Closes the channel.
515
576
///
516
577
/// Returns `true` if this call has closed the channel and it was not closed already.
@@ -895,50 +956,62 @@ pub struct Send<'a, T> {
895
956
msg : Option < T > ,
896
957
}
897
958
898
- impl < ' a , T > Unpin for Send < ' a , T > { }
899
-
900
- impl < ' a , T > Future for Send < ' a , T > {
901
- type Output = Result < ( ) , SendError < T > > ;
902
-
903
- fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
904
- let mut this = Pin :: new ( self ) ;
905
-
959
+ impl < ' a , T > Send < ' a , T > {
960
+ /// Run this future with the given `Strategy`.
961
+ fn run_with_strategy < S : Strategy > (
962
+ & mut self ,
963
+ cx : & mut S :: Context ,
964
+ ) -> Poll < Result < ( ) , SendError < T > > > {
906
965
loop {
907
- let msg = this . msg . take ( ) . unwrap ( ) ;
966
+ let msg = self . msg . take ( ) . unwrap ( ) ;
908
967
// Attempt to send a message.
909
- match this . sender . try_send ( msg) {
968
+ match self . sender . try_send ( msg) {
910
969
Ok ( ( ) ) => {
911
970
// If the capacity is larger than 1, notify another blocked send operation.
912
- match this . sender . channel . queue . capacity ( ) {
971
+ match self . sender . channel . queue . capacity ( ) {
913
972
Some ( 1 ) => { }
914
- Some ( _) | None => this . sender . channel . send_ops . notify ( 1 ) ,
973
+ Some ( _) | None => self . sender . channel . send_ops . notify ( 1 ) ,
915
974
}
916
975
return Poll :: Ready ( Ok ( ( ) ) ) ;
917
976
}
918
977
Err ( TrySendError :: Closed ( msg) ) => return Poll :: Ready ( Err ( SendError ( msg) ) ) ,
919
- Err ( TrySendError :: Full ( m) ) => this . msg = Some ( m) ,
978
+ Err ( TrySendError :: Full ( m) ) => self . msg = Some ( m) ,
920
979
}
921
980
922
981
// Sending failed - now start listening for notifications or wait for one.
923
- match & mut this . listener {
982
+ match self . listener . take ( ) {
924
983
None => {
925
984
// Start listening and then try sending again.
926
- this . listener = Some ( this . sender . channel . send_ops . listen ( ) ) ;
985
+ self . listener = Some ( self . sender . channel . send_ops . listen ( ) ) ;
927
986
}
928
987
Some ( l) => {
929
- // Wait for a notification.
930
- match Pin :: new ( l) . poll ( cx) {
931
- Poll :: Ready ( _) => {
932
- this. listener = None ;
933
- continue ;
934
- }
935
-
936
- Poll :: Pending => return Poll :: Pending ,
988
+ // Poll using the given strategy
989
+ if let Err ( l) = S :: poll ( l, cx) {
990
+ self . listener = Some ( l) ;
991
+ return Poll :: Pending ;
937
992
}
938
993
}
939
994
}
940
995
}
941
996
}
997
+
998
+ /// Run using the blocking strategy.
999
+ fn wait ( mut self ) -> Result < ( ) , SendError < T > > {
1000
+ match self . run_with_strategy :: < Blocking > ( & mut ( ) ) {
1001
+ Poll :: Ready ( res) => res,
1002
+ Poll :: Pending => unreachable ! ( ) ,
1003
+ }
1004
+ }
1005
+ }
1006
+
1007
+ impl < ' a , T > Unpin for Send < ' a , T > { }
1008
+
1009
+ impl < ' a , T > Future for Send < ' a , T > {
1010
+ type Output = Result < ( ) , SendError < T > > ;
1011
+
1012
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
1013
+ self . run_with_strategy :: < NonBlocking < ' _ > > ( cx)
1014
+ }
942
1015
}
943
1016
944
1017
/// A future returned by [`Receiver::recv()`].
@@ -951,22 +1024,22 @@ pub struct Recv<'a, T> {
951
1024
952
1025
impl < ' a , T > Unpin for Recv < ' a , T > { }
953
1026
954
- impl < ' a , T > Future for Recv < ' a , T > {
955
- type Output = Result < T , RecvError > ;
956
-
957
- fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
958
- let mut this = Pin :: new ( self ) ;
959
-
1027
+ impl < ' a , T > Recv < ' a , T > {
1028
+ /// Run this future with the given `Strategy`.
1029
+ fn run_with_strategy < S : Strategy > (
1030
+ & mut self ,
1031
+ cx : & mut S :: Context ,
1032
+ ) -> Poll < Result < T , RecvError > > {
960
1033
loop {
961
1034
// Attempt to receive a message.
962
- match this . receiver . try_recv ( ) {
1035
+ match self . receiver . try_recv ( ) {
963
1036
Ok ( msg) => {
964
1037
// If the capacity is larger than 1, notify another blocked receive operation.
965
1038
// There is no need to notify stream operations because all of them get
966
1039
// notified every time a message is sent into the channel.
967
- match this . receiver . channel . queue . capacity ( ) {
1040
+ match self . receiver . channel . queue . capacity ( ) {
968
1041
Some ( 1 ) => { }
969
- Some ( _) | None => this . receiver . channel . recv_ops . notify ( 1 ) ,
1042
+ Some ( _) | None => self . receiver . channel . recv_ops . notify ( 1 ) ,
970
1043
}
971
1044
return Poll :: Ready ( Ok ( msg) ) ;
972
1045
}
@@ -975,23 +1048,73 @@ impl<'a, T> Future for Recv<'a, T> {
975
1048
}
976
1049
977
1050
// Receiving failed - now start listening for notifications or wait for one.
978
- match & mut this . listener {
1051
+ match self . listener . take ( ) {
979
1052
None => {
980
1053
// Start listening and then try receiving again.
981
- this . listener = Some ( this . receiver . channel . recv_ops . listen ( ) ) ;
1054
+ self . listener = Some ( self . receiver . channel . recv_ops . listen ( ) ) ;
982
1055
}
983
1056
Some ( l) => {
984
- // Wait for a notification.
985
- match Pin :: new ( l) . poll ( cx) {
986
- Poll :: Ready ( _) => {
987
- this. listener = None ;
988
- continue ;
989
- }
990
-
991
- Poll :: Pending => return Poll :: Pending ,
1057
+ // Poll using the given strategy.
1058
+ if let Err ( l) = S :: poll ( l, cx) {
1059
+ self . listener = Some ( l) ;
1060
+ return Poll :: Pending ;
992
1061
}
993
1062
}
994
1063
}
995
1064
}
996
1065
}
1066
+
1067
+ /// Run with the blocking strategy.
1068
+ fn wait ( mut self ) -> Result < T , RecvError > {
1069
+ match self . run_with_strategy :: < Blocking > ( & mut ( ) ) {
1070
+ Poll :: Ready ( res) => res,
1071
+ Poll :: Pending => unreachable ! ( ) ,
1072
+ }
1073
+ }
1074
+ }
1075
+
1076
+ impl < ' a , T > Future for Recv < ' a , T > {
1077
+ type Output = Result < T , RecvError > ;
1078
+
1079
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
1080
+ self . run_with_strategy :: < NonBlocking < ' _ > > ( cx)
1081
+ }
1082
+ }
1083
+
1084
+ /// A strategy used to poll an `EventListener`.
1085
+ trait Strategy {
1086
+ /// Context needed to be provided to the `poll` method.
1087
+ type Context ;
1088
+
1089
+ /// Polls the given `EventListener`.
1090
+ ///
1091
+ /// Returns the `EventListener` back if it was not completed; otherwise,
1092
+ /// returns `Ok(())`.
1093
+ fn poll ( evl : EventListener , cx : & mut Self :: Context ) -> Result < ( ) , EventListener > ;
1094
+ }
1095
+
1096
+ /// Non-blocking strategy for use in asynchronous code.
1097
+ struct NonBlocking < ' a > ( & ' a mut ( ) ) ;
1098
+
1099
+ impl < ' a > Strategy for NonBlocking < ' a > {
1100
+ type Context = Context < ' a > ;
1101
+
1102
+ fn poll ( mut evl : EventListener , cx : & mut Context < ' a > ) -> Result < ( ) , EventListener > {
1103
+ match Pin :: new ( & mut evl) . poll ( cx) {
1104
+ Poll :: Ready ( ( ) ) => Ok ( ( ) ) ,
1105
+ Poll :: Pending => Err ( evl) ,
1106
+ }
1107
+ }
1108
+ }
1109
+
1110
+ /// Blocking strategy for use in synchronous code.
1111
+ struct Blocking ;
1112
+
1113
+ impl Strategy for Blocking {
1114
+ type Context = ( ) ;
1115
+
1116
+ fn poll ( evl : EventListener , _cx : & mut ( ) ) -> Result < ( ) , EventListener > {
1117
+ evl. wait ( ) ;
1118
+ Ok ( ( ) )
1119
+ }
997
1120
}
0 commit comments