Update how timeouts are cleared to avoid possible double-clearing

This commit is contained in:
Ryan Goldstein 2019-06-23 14:38:35 -07:00
parent cf28751ae3
commit a0f280e71f

View file

@ -340,18 +340,14 @@ impl<T: 'static> EventLoopRunnerShared<T> {
} else { } else {
(match runner.control { (match runner.control {
ControlFlowStatus::Init => StartCause::Init, ControlFlowStatus::Init => StartCause::Init,
ControlFlowStatus::Poll { ref timeout } => { ControlFlowStatus::Poll { .. } => {
timeout.clear();
StartCause::Poll StartCause::Poll
} }
ControlFlowStatus::Wait { start } => StartCause::WaitCancelled { ControlFlowStatus::Wait { start } => StartCause::WaitCancelled {
start, start,
requested_resume: None, requested_resume: None,
}, },
ControlFlowStatus::WaitUntil { start, end, ref timeout } => { ControlFlowStatus::WaitUntil { start, end, .. } => {
timeout.clear();
StartCause::WaitCancelled { StartCause::WaitCancelled {
start, start,
requested_resume: Some(end) requested_resume: Some(end)
@ -398,7 +394,7 @@ impl<T: 'static> EventLoopRunnerShared<T> {
runner.is_busy = true; runner.is_busy = true;
(runner.event_handler)(event, control); (runner.event_handler)(event, control);
// Maintain closed state, even if the callback changes it // Maintain closed state, even if the callback changes it
if closed { if closed {
*control = ControlFlow::Exit; *control = ControlFlow::Exit;
@ -425,11 +421,11 @@ impl<T: 'static> EventLoopRunnerShared<T> {
// Apply the new ControlFlow that has been selected by the user // Apply the new ControlFlow that has been selected by the user
// Start any necessary timeouts etc // Start any necessary timeouts etc
fn apply_control_flow(&self, control_flow: ControlFlow) { fn apply_control_flow(&self, control_flow: ControlFlow) {
let control_flow_status = match control_flow { let mut control_flow_status = match control_flow {
ControlFlow::Poll => { ControlFlow::Poll => {
let cloned = self.clone(); let cloned = self.clone();
ControlFlowStatus::Poll { ControlFlowStatus::Poll {
timeout: window().set_clearable_timeout(move || cloned.send_event(Event::NewEvents(StartCause::Poll)), 0) timeout: window().set_clearable_timeout(move || cloned.send_event(Event::NewEvents(StartCause::Poll)), 1)
} }
} }
ControlFlow::Wait => ControlFlowStatus::Wait { start: Instant::now() }, ControlFlow::Wait => ControlFlowStatus::Wait { start: Instant::now() },
@ -452,7 +448,15 @@ impl<T: 'static> EventLoopRunnerShared<T> {
match *self.0.runner.borrow_mut() { match *self.0.runner.borrow_mut() {
Some(ref mut runner) => { Some(ref mut runner) => {
runner.control = control_flow_status; // Put the new control flow status in the runner, and take out the old one
// This way we can safely take ownership of the TimeoutHandle and clear it,
// so that we don't get 'ghost' invocations of Poll or WaitUntil from earlier
// set_timeout invocations
std::mem::swap(&mut runner.control, &mut control_flow_status);
match control_flow_status {
ControlFlowStatus::Poll { timeout } | ControlFlowStatus::WaitUntil { timeout, .. } => timeout.clear(),
_ => (),
}
} }
None => () None => ()
} }