Skip to content

Commit 6ddf69c

Browse files
authored
Merge pull request #2064 from TheBlueMatt/2023-03-debug-futures
Make waking after a future completes propagates to the next future
2 parents f114515 + cd03cb6 commit 6ddf69c

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

lightning/src/util/wakers.rs

+65-2
Original file line numberDiff line numberDiff line change
@@ -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

163166
impl 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

Comments
 (0)