Skip to content

Commit 2c98720

Browse files
committed
Split lists of Waker and directly-registered Future callbacks
In the next commit we'll fix a memory leak due to keeping too many `std::task::Waker` callbacks in `FutureState` from redundant `poll` calls, but first we need to split handling of `StdWaker`-based future wake callbacks from normal ones, which we do here.
1 parent 73da722 commit 2c98720

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

lightning/src/util/wakers.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl Notifier {
6969
} else {
7070
let state = Arc::new(Mutex::new(FutureState {
7171
callbacks: Vec::new(),
72+
std_future_callbacks: Vec::new(),
7273
callbacks_with_state: Vec::new(),
7374
complete: lock.0,
7475
callbacks_made: false,
@@ -109,25 +110,29 @@ define_callback!(Send);
109110
define_callback!();
110111

111112
pub(crate) struct FutureState {
112-
// When we're tracking whether a callback counts as having woken the user's code, we check the
113-
// first bool - set to false if we're just calling a Waker, and true if we're calling an actual
114-
// user-provided function.
115-
callbacks: Vec<(bool, Box<dyn FutureCallback>)>,
116-
callbacks_with_state: Vec<(bool, Box<dyn Fn(&Arc<Mutex<FutureState>>) -> () + Send>)>,
113+
// `callbacks` count as having woken the users' code (as they go direct to the user), but
114+
// `std_future_callbacks` and `callbacks_with_state` do not (as the first just wakes a future,
115+
// we only count it after another `poll()` and the second wakes a `Sleeper` which handles
116+
// setting `callbacks_made` itself).
117+
callbacks: Vec<Box<dyn FutureCallback>>,
118+
std_future_callbacks: Vec<StdWaker>,
119+
callbacks_with_state: Vec<Box<dyn Fn(&Arc<Mutex<FutureState>>) -> () + Send>>,
117120
complete: bool,
118121
callbacks_made: bool,
119122
}
120123

121124
fn complete_future(this: &Arc<Mutex<FutureState>>) -> bool {
122125
let mut state_lock = this.lock().unwrap();
123126
let state = &mut *state_lock;
124-
for (counts_as_call, callback) in state.callbacks.drain(..) {
127+
for callback in state.callbacks.drain(..) {
125128
callback.call();
126-
state.callbacks_made |= counts_as_call;
129+
state.callbacks_made = true;
127130
}
128-
for (counts_as_call, callback) in state.callbacks_with_state.drain(..) {
131+
for waker in state.std_future_callbacks.drain(..) {
132+
waker.0.wake_by_ref();
133+
}
134+
for callback in state.callbacks_with_state.drain(..) {
129135
(callback)(this);
130-
state.callbacks_made |= counts_as_call;
131136
}
132137
state.complete = true;
133138
state.callbacks_made
@@ -153,7 +158,7 @@ impl Future {
153158
mem::drop(state);
154159
callback.call();
155160
} else {
156-
state.callbacks.push((true, callback));
161+
state.callbacks.push(callback);
157162
}
158163
}
159164

@@ -193,9 +198,6 @@ impl Future {
193198

194199
use core::task::Waker;
195200
struct StdWaker(pub Waker);
196-
impl FutureCallback for StdWaker {
197-
fn call(&self) { self.0.wake_by_ref() }
198-
}
199201

200202
/// This is not exported to bindings users as Rust Futures aren't usable in language bindings.
201203
impl<'a> StdFuture for Future {
@@ -208,7 +210,7 @@ impl<'a> StdFuture for Future {
208210
Poll::Ready(())
209211
} else {
210212
let waker = cx.waker().clone();
211-
state.callbacks.push((false, Box::new(StdWaker(waker))));
213+
state.std_future_callbacks.push(StdWaker(waker));
212214
Poll::Pending
213215
}
214216
}
@@ -251,10 +253,10 @@ impl Sleeper {
251253
*notified_fut_mtx.lock().unwrap() = Some(Arc::clone(&notifier_mtx));
252254
break;
253255
}
254-
notifier.callbacks_with_state.push((false, Box::new(move |notifier_ref| {
256+
notifier.callbacks_with_state.push(Box::new(move |notifier_ref| {
255257
*notified_fut_ref.lock().unwrap() = Some(Arc::clone(notifier_ref));
256258
cv_ref.notify_all();
257-
})));
259+
}));
258260
}
259261
}
260262
(cv, notified_fut_mtx)
@@ -455,6 +457,7 @@ mod tests {
455457
let future = Future {
456458
state: Arc::new(Mutex::new(FutureState {
457459
callbacks: Vec::new(),
460+
std_future_callbacks: Vec::new(),
458461
callbacks_with_state: Vec::new(),
459462
complete: false,
460463
callbacks_made: false,
@@ -514,6 +517,7 @@ mod tests {
514517
let mut future = Future {
515518
state: Arc::new(Mutex::new(FutureState {
516519
callbacks: Vec::new(),
520+
std_future_callbacks: Vec::new(),
517521
callbacks_with_state: Vec::new(),
518522
complete: false,
519523
callbacks_made: false,

0 commit comments

Comments
 (0)