7878// happens-before semantics required for the acquire / release semantics used
7979// by the queue structure.
8080
81+ use core:: future:: Future ;
8182use futures_core:: stream:: { FusedStream , Stream } ;
8283use futures_core:: task:: __internal:: AtomicWaker ;
8384use futures_core:: task:: { Context , Poll , Waker } ;
85+ use futures_core:: FusedFuture ;
8486use std:: fmt;
8587use std:: pin:: Pin ;
8688use std:: sync:: atomic:: AtomicUsize ;
@@ -167,7 +169,7 @@ enum SendErrorKind {
167169 Disconnected ,
168170}
169171
170- /// The error type returned from [`try_recv`](Receiver ::try_recv) .
172+ /// Error returned by [`Receiver:: try_recv`] or [`UnboundedReceiver ::try_recv`] .
171173#[ derive( PartialEq , Eq , Clone , Copy , Debug ) ]
172174pub enum TryRecvError {
173175 /// The channel is empty but not closed.
@@ -177,6 +179,18 @@ pub enum TryRecvError {
177179 Closed ,
178180}
179181
182+ /// Error returned by the future returned by [`Receiver::recv()`] or [`UnboundedReceiver::recv()`].
183+ /// Received when the channel is empty and closed.
184+ #[ derive( PartialEq , Eq , Clone , Copy , Debug ) ]
185+ pub struct RecvError ;
186+
187+ /// Future returned by [`Receiver::recv()`] or [`UnboundedReceiver::recv()`].
188+ #[ derive( Debug ) ]
189+ #[ must_use = "futures do nothing unless you `.await` or poll them" ]
190+ pub struct Recv < ' a , St : ?Sized > {
191+ stream : & ' a mut St ,
192+ }
193+
180194impl fmt:: Display for SendError {
181195 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
182196 if self . is_full ( ) {
@@ -189,6 +203,14 @@ impl fmt::Display for SendError {
189203
190204impl std:: error:: Error for SendError { }
191205
206+ impl fmt:: Display for RecvError {
207+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
208+ write ! ( f, "receive failed because channel is empty and closed" )
209+ }
210+ }
211+
212+ impl std:: error:: Error for RecvError { }
213+
192214impl SendError {
193215 /// Returns `true` if this error is a result of the channel being full.
194216 pub fn is_full ( & self ) -> bool {
@@ -979,6 +1001,12 @@ impl<T> fmt::Debug for UnboundedSender<T> {
9791001 */
9801002
9811003impl < T > Receiver < T > {
1004+ /// Waits for a message from the channel.
1005+ /// If the channel is empty and closed, returns [`RecvError`].
1006+ pub fn recv ( & mut self ) -> Recv < ' _ , Self > {
1007+ Recv :: new ( self )
1008+ }
1009+
9821010 /// Closes the receiving half of a channel, without dropping it.
9831011 ///
9841012 /// This prevents any further messages from being sent on the channel while
@@ -1121,6 +1149,31 @@ impl<T> Stream for Receiver<T> {
11211149 }
11221150}
11231151
1152+ impl < St : ?Sized + Unpin > Unpin for Recv < ' _ , St > { }
1153+ impl < ' a , St : ?Sized + Stream + Unpin > Recv < ' a , St > {
1154+ fn new ( stream : & ' a mut St ) -> Self {
1155+ Self { stream }
1156+ }
1157+ }
1158+
1159+ impl < St : ?Sized + FusedStream + Unpin > FusedFuture for Recv < ' _ , St > {
1160+ fn is_terminated ( & self ) -> bool {
1161+ self . stream . is_terminated ( )
1162+ }
1163+ }
1164+
1165+ impl < St : ?Sized + Stream + Unpin > Future for Recv < ' _ , St > {
1166+ type Output = Result < St :: Item , RecvError > ;
1167+
1168+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
1169+ match Pin :: new ( & mut self . stream ) . poll_next ( cx) {
1170+ Poll :: Ready ( Some ( msg) ) => Poll :: Ready ( Ok ( msg) ) ,
1171+ Poll :: Ready ( None ) => Poll :: Ready ( Err ( RecvError ) ) ,
1172+ Poll :: Pending => Poll :: Pending ,
1173+ }
1174+ }
1175+ }
1176+
11241177impl < T > Drop for Receiver < T > {
11251178 fn drop ( & mut self ) {
11261179 // Drain the channel of all pending messages
@@ -1164,6 +1217,12 @@ impl<T> fmt::Debug for Receiver<T> {
11641217}
11651218
11661219impl < T > UnboundedReceiver < T > {
1220+ /// Waits for a message from the channel.
1221+ /// If the channel is empty and closed, returns [`RecvError`].
1222+ pub fn recv ( & mut self ) -> Recv < ' _ , Self > {
1223+ Recv :: new ( self )
1224+ }
1225+
11671226 /// Closes the receiving half of a channel, without dropping it.
11681227 ///
11691228 /// This prevents any further messages from being sent on the channel while
0 commit comments