@@ -105,7 +105,10 @@ impl Notifier {
105
105
pub ( crate ) fn notify ( & self ) {
106
106
let mut lock = self . notify_pending . lock ( ) . unwrap ( ) ;
107
107
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
+ }
109
112
}
110
113
lock. 0 = true ;
111
114
mem:: drop ( lock) ;
@@ -161,12 +164,13 @@ pub(crate) struct FutureState {
161
164
}
162
165
163
166
impl FutureState {
164
- fn complete ( & mut self ) {
167
+ fn complete ( & mut self ) -> bool {
165
168
for ( counts_as_call, callback) in self . callbacks . drain ( ..) {
166
169
callback. call ( ) ;
167
170
self . callbacks_made |= counts_as_call;
168
171
}
169
172
self . complete = true ;
173
+ self . callbacks_made
170
174
}
171
175
}
172
176
@@ -469,4 +473,63 @@ mod tests {
469
473
assert_eq ! ( Pin :: new( & mut future) . poll( & mut Context :: from_waker( & waker) ) , Poll :: Ready ( ( ) ) ) ;
470
474
assert ! ( !notifier. wait_timeout( Duration :: from_millis( 1 ) ) ) ;
471
475
}
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
+ }
472
535
}
0 commit comments