@@ -586,4 +586,42 @@ mod tests {
586586 notifier_a. notify ( ) ;
587587 Sleeper :: from_two_futures ( notifier_a. get_future ( ) , notifier_b. get_future ( ) ) . wait ( ) ;
588588 }
589+
590+ #[ test]
591+ fn sleeper_with_pending_callbacks ( ) {
592+ // This is similar to the above `test_multi_future_sleep` test, but in addition registers
593+ // "normal" callbacks which will cause the futures to assume notification has occurred,
594+ // rather than waiting for a woken sleeper.
595+ let notifier_a = Notifier :: new ( ) ;
596+ let notifier_b = Notifier :: new ( ) ;
597+
598+ // Set both notifiers as woken without sleeping yet.
599+ notifier_a. notify ( ) ;
600+ notifier_b. notify ( ) ;
601+
602+ // After sleeping one future (not guaranteed which one, however) will have its notification
603+ // bit cleared.
604+ Sleeper :: from_two_futures ( notifier_a. get_future ( ) , notifier_b. get_future ( ) ) . wait ( ) ;
605+
606+ // By registering a callback on the futures for both notifiers, one will complete
607+ // immediately, but one will remain tied to the notifier, and will complete once the
608+ // notifier is next woken, which will be considered the completion of the notification.
609+ let callback_a = Arc :: new ( AtomicBool :: new ( false ) ) ;
610+ let callback_b = Arc :: new ( AtomicBool :: new ( false ) ) ;
611+ let callback_a_ref = Arc :: clone ( & callback_a) ;
612+ let callback_b_ref = Arc :: clone ( & callback_b) ;
613+ notifier_a. get_future ( ) . register_callback ( Box :: new ( move || assert ! ( !callback_a_ref. fetch_or( true , Ordering :: SeqCst ) ) ) ) ;
614+ notifier_b. get_future ( ) . register_callback ( Box :: new ( move || assert ! ( !callback_b_ref. fetch_or( true , Ordering :: SeqCst ) ) ) ) ;
615+ assert ! ( callback_a. load( Ordering :: SeqCst ) ^ callback_b. load( Ordering :: SeqCst ) ) ;
616+
617+ // If we now notify both notifiers again, the other callback will fire, completing the
618+ // notification, and we'll be back to one pending notification.
619+ notifier_a. notify ( ) ;
620+ notifier_b. notify ( ) ;
621+
622+ assert ! ( callback_a. load( Ordering :: SeqCst ) && callback_b. load( Ordering :: SeqCst ) ) ;
623+ Sleeper :: from_two_futures ( notifier_a. get_future ( ) , notifier_b. get_future ( ) ) . wait ( ) ;
624+ assert ! ( !Sleeper :: from_two_futures( notifier_a. get_future( ) , notifier_b. get_future( ) )
625+ . wait_timeout( Duration :: from_millis( 10 ) ) ) ;
626+ }
589627}
0 commit comments