@@ -1149,19 +1149,47 @@ impl<T> Receiver<T> {
11491149 _ => false ,
11501150 }
11511151 }
1152+
1153+ /// Disconnects this from the channel.
1154+ ///
1155+ /// If this is the last one connected to the channel, sender start to fail and
1156+ /// the returned iterator can be used to drain any remaining sent messages. Otherwise, it
1157+ /// always returns [`None`].
1158+ pub fn disconnect ( self ) -> DisconnectIter < T > {
1159+ let was_last = unsafe {
1160+ match & self . flavor {
1161+ ReceiverFlavor :: List ( chan) => chan. release ( |c| c. disconnect_receivers ( ) ) ,
1162+ _ => {
1163+ panic ! ( ) ;
1164+ }
1165+ }
1166+ } ;
1167+ if let Some ( true ) = was_last {
1168+ DisconnectIter {
1169+ last_receiver : Some ( self ) ,
1170+ }
1171+ } else {
1172+ std:: mem:: forget ( self ) ;
1173+ DisconnectIter {
1174+ last_receiver : None ,
1175+ }
1176+ }
1177+ }
11521178}
11531179
11541180impl < T > Drop for Receiver < T > {
11551181 fn drop ( & mut self ) {
11561182 unsafe {
11571183 match & self . flavor {
11581184 ReceiverFlavor :: Array ( chan) => chan. release ( |c| c. disconnect ( ) ) ,
1159- ReceiverFlavor :: List ( chan) => chan. release ( |c| c. disconnect_receivers ( ) ) ,
1185+ ReceiverFlavor :: List ( chan) => {
1186+ chan. release ( |c| c. disconnect_receivers_and_discard_messages ( ) )
1187+ }
11601188 ReceiverFlavor :: Zero ( chan) => chan. release ( |c| c. disconnect ( ) ) ,
1161- ReceiverFlavor :: At ( _) => { }
1162- ReceiverFlavor :: Tick ( _) => { }
1163- ReceiverFlavor :: Never ( _) => { }
1164- }
1189+ ReceiverFlavor :: At ( _) => None ,
1190+ ReceiverFlavor :: Tick ( _) => None ,
1191+ ReceiverFlavor :: Never ( _) => None ,
1192+ } ;
11651193 }
11661194 }
11671195}
@@ -1289,6 +1317,39 @@ pub struct TryIter<'a, T> {
12891317 receiver : & ' a Receiver < T > ,
12901318}
12911319
1320+ /// A non-blocking draining iterator over unreceived messages after channel termination.
1321+ ///
1322+ /// Each call to [`next`] returns a message if there is still more to be received. The iterator
1323+ /// never blocks waiting for the next message as the channel don't allow sending anymore.
1324+ ///
1325+ /// [`next`]: Iterator::next
1326+ pub struct DisconnectIter < T > {
1327+ last_receiver : Option < Receiver < T > > ,
1328+ }
1329+
1330+ impl < T > FusedIterator for DisconnectIter < T > { }
1331+
1332+ impl < T > Iterator for DisconnectIter < T > {
1333+ type Item = T ;
1334+
1335+ fn next ( & mut self ) -> Option < Self :: Item > {
1336+ self . last_receiver
1337+ . as_ref ( )
1338+ . and_then ( |r| match r. try_recv ( ) {
1339+ Ok ( msg) => Some ( msg) ,
1340+ Err ( TryRecvError :: Disconnected ) => None ,
1341+ Err ( TryRecvError :: Empty ) => unreachable ! ( ) ,
1342+ } )
1343+ }
1344+ }
1345+
1346+ impl < T > DisconnectIter < T > {
1347+ /// Returns true if this was returned from the last receiver's disconnection.
1348+ pub fn is_last_receiver ( & self ) -> bool {
1349+ self . last_receiver . is_some ( )
1350+ }
1351+ }
1352+
12921353impl < T > Iterator for TryIter < ' _ , T > {
12931354 type Item = T ;
12941355
@@ -1303,6 +1364,26 @@ impl<T> fmt::Debug for TryIter<'_, T> {
13031364 }
13041365}
13051366
1367+ impl < T > fmt:: Debug for DisconnectIter < T > {
1368+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1369+ f. pad ( "DisconnectIter { .. }" )
1370+ }
1371+ }
1372+
1373+ impl < T > Drop for DisconnectIter < T > {
1374+ fn drop ( & mut self ) {
1375+ if let Some ( last_receiver) = self . last_receiver . take ( ) {
1376+ match & last_receiver. flavor {
1377+ ReceiverFlavor :: List ( chan) => chan. discard_all_messages ( ) ,
1378+ _ => {
1379+ panic ! ( ) ;
1380+ }
1381+ }
1382+ std:: mem:: forget ( last_receiver) ;
1383+ }
1384+ }
1385+ }
1386+
13061387/// A blocking iterator over messages in a channel.
13071388///
13081389/// Each call to [`next`] blocks waiting for the next message and then returns it. However, if the
0 commit comments