@@ -105,7 +105,10 @@ impl Notifier {
105105 pub ( crate ) fn notify ( & self ) {
106106 let mut lock = self . notify_pending . lock ( ) . unwrap ( ) ;
107107 if let Some ( future_state) = & lock. 1 {
108- future_state. lock ( ) . unwrap ( ) . complete ( ) ;
108+ if future_state. lock ( ) . unwrap ( ) . complete ( ) {
109+ lock. 1 = None ;
110+ return ;
111+ }
109112 }
110113 lock. 0 = true ;
111114 mem:: drop ( lock) ;
@@ -161,12 +164,13 @@ pub(crate) struct FutureState {
161164}
162165
163166impl FutureState {
164- fn complete ( & mut self ) {
167+ fn complete ( & mut self ) -> bool {
165168 for ( counts_as_call, callback) in self . callbacks . drain ( ..) {
166169 callback. call ( ) ;
167170 self . callbacks_made |= counts_as_call;
168171 }
169172 self . complete = true ;
173+ self . callbacks_made
170174 }
171175}
172176
@@ -469,4 +473,63 @@ mod tests {
469473 assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
470474 assert ! ( !notifier. wait_timeout( Duration :: from_millis( 1 ) ) ) ;
471475 }
476+
477+ #[ test]
478+ fn test_poll_post_notify_completes ( ) {
479+ // Tests that if we have a future state that has completed, and we haven't yet requested a
480+ // new future, if we get a notify prior to requesting that second future it is generated
481+ // pre-completed.
482+ let notifier = Notifier :: new ( ) ;
483+
484+ notifier. notify ( ) ;
485+ let mut future = notifier. get_future ( ) ;
486+ let ( woken, waker) = create_waker ( ) ;
487+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
488+ assert ! ( !woken. load( Ordering :: SeqCst ) ) ;
489+
490+ notifier. notify ( ) ;
491+ let mut future = notifier. get_future ( ) ;
492+ let ( woken, waker) = create_waker ( ) ;
493+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
494+ assert ! ( !woken. load( Ordering :: SeqCst ) ) ;
495+
496+ let mut future = notifier. get_future ( ) ;
497+ let ( woken, waker) = create_waker ( ) ;
498+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Pending ) ;
499+ assert ! ( !woken. load( Ordering :: SeqCst ) ) ;
500+
501+ notifier. notify ( ) ;
502+ assert ! ( woken. load( Ordering :: SeqCst ) ) ;
503+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
504+ }
505+
506+ #[ test]
507+ fn test_poll_post_notify_completes_initial_notified ( ) {
508+ // Identical to the previous test, but the first future completes via a wake rather than an
509+ // immediate `Poll::Ready`.
510+ let notifier = Notifier :: new ( ) ;
511+
512+ let mut future = notifier. get_future ( ) ;
513+ let ( woken, waker) = create_waker ( ) ;
514+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Pending ) ;
515+
516+ notifier. notify ( ) ;
517+ assert ! ( woken. load( Ordering :: SeqCst ) ) ;
518+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
519+
520+ notifier. notify ( ) ;
521+ let mut future = notifier. get_future ( ) ;
522+ let ( woken, waker) = create_waker ( ) ;
523+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
524+ assert ! ( !woken. load( Ordering :: SeqCst ) ) ;
525+
526+ let mut future = notifier. get_future ( ) ;
527+ let ( woken, waker) = create_waker ( ) ;
528+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Pending ) ;
529+ assert ! ( !woken. load( Ordering :: SeqCst ) ) ;
530+
531+ notifier. notify ( ) ;
532+ assert ! ( woken. load( Ordering :: SeqCst ) ) ;
533+ assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
534+ }
472535}
0 commit comments