@@ -1149,19 +1149,47 @@ impl<T> Receiver<T> {
1149
1149
_ => false ,
1150
1150
}
1151
1151
}
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
+ }
1152
1178
}
1153
1179
1154
1180
impl < T > Drop for Receiver < T > {
1155
1181
fn drop ( & mut self ) {
1156
1182
unsafe {
1157
1183
match & self . flavor {
1158
1184
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
+ }
1160
1188
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
+ } ;
1165
1193
}
1166
1194
}
1167
1195
}
@@ -1289,6 +1317,39 @@ pub struct TryIter<'a, T> {
1289
1317
receiver : & ' a Receiver < T > ,
1290
1318
}
1291
1319
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
+
1292
1353
impl < T > Iterator for TryIter < ' _ , T > {
1293
1354
type Item = T ;
1294
1355
@@ -1303,6 +1364,26 @@ impl<T> fmt::Debug for TryIter<'_, T> {
1303
1364
}
1304
1365
}
1305
1366
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
+
1306
1387
/// A blocking iterator over messages in a channel.
1307
1388
///
1308
1389
/// Each call to [`next`] blocks waiting for the next message and then returns it. However, if the
0 commit comments