@@ -559,6 +559,8 @@ impl<T, const N: usize> Drop for Receiver<'_, T, N> {
559
559
560
560
#[ cfg( test) ]
561
561
mod tests {
562
+ use cassette:: Cassette ;
563
+
562
564
use super :: * ;
563
565
564
566
#[ test]
@@ -684,4 +686,43 @@ mod tests {
684
686
fn tuple_channel ( ) {
685
687
let _ = make_channel ! ( ( i32 , u32 ) , 10 ) ;
686
688
}
689
+
690
+ fn freeq < const N : usize , T , F , R > ( channel : & Channel < T , N > , f : F ) -> R
691
+ where
692
+ F : FnOnce ( & mut Deque < u8 , N > ) -> R ,
693
+ {
694
+ critical_section:: with ( |cs| f ( channel. access ( cs) . freeq ) )
695
+ }
696
+
697
+ #[ test]
698
+ fn dropping_waked_send_returns_freeq_item ( ) {
699
+ let ( mut tx, mut rx) = make_channel ! ( u8 , 1 ) ;
700
+
701
+ tx. try_send ( 0 ) . unwrap ( ) ;
702
+ assert ! ( freeq( & rx. 0 , |q| q. is_empty( ) ) ) ;
703
+
704
+ // Running this in a separate thread scope to ensure that `pinned_future` is dropped fully.
705
+ //
706
+ // Calling drop explicitly gets hairy because dropping things behind a `Pin` is not easy.
707
+ std:: thread:: scope ( |scope| {
708
+ scope. spawn ( || {
709
+ let pinned_future = core:: pin:: pin!( tx. send( 1 ) ) ;
710
+ let mut future = Cassette :: new ( pinned_future) ;
711
+
712
+ future. poll_on ( ) ;
713
+
714
+ assert ! ( freeq( & rx. 0 , |q| q. is_empty( ) ) ) ;
715
+ assert ! ( !rx. 0 . wait_queue. is_empty( ) ) ;
716
+
717
+ assert_eq ! ( rx. try_recv( ) , Ok ( 0 ) ) ;
718
+
719
+ assert ! ( freeq( & rx. 0 , |q| q. is_empty( ) ) ) ;
720
+ } ) ;
721
+ } ) ;
722
+
723
+ assert ! ( !freeq( & rx. 0 , |q| q. is_empty( ) ) ) ;
724
+
725
+ // Make sure that rx & tx are alive until here for good measure.
726
+ drop ( ( tx, rx) ) ;
727
+ }
687
728
}
0 commit comments