gpui(windows): Fix apps not quitting if they overwhelm the foreground thread with tasks (#43896)
Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
@@ -815,12 +815,14 @@ impl WindowsPlatformInner {
|
||||
fn run_foreground_task(&self) -> Option<isize> {
|
||||
const MAIN_TASK_TIMEOUT: u128 = 10;
|
||||
|
||||
let mut start = std::time::Instant::now();
|
||||
loop {
|
||||
loop {
|
||||
let start = std::time::Instant::now();
|
||||
'tasks: loop {
|
||||
'timeout_loop: loop {
|
||||
if start.elapsed().as_millis() >= MAIN_TASK_TIMEOUT {
|
||||
// we spent our budget on gpui tasks, we likely have a lot of work queued so drain system events first
|
||||
// before returning to main thread task work
|
||||
log::debug!("foreground task timeout reached");
|
||||
// we spent our budget on gpui tasks, we likely have a lot of work queued so drain system events first to stay responsive
|
||||
// then quit out of foreground work to allow us to process other gpui events first before returning back to foreground task work
|
||||
// if we don't we might not for example process window quit events
|
||||
let mut msg = MSG::default();
|
||||
let process_message = |msg: &_| {
|
||||
if translate_accelerator(msg).is_none() {
|
||||
@@ -831,39 +833,40 @@ impl WindowsPlatformInner {
|
||||
let peek_msg = |msg: &mut _, msg_kind| unsafe {
|
||||
PeekMessageW(msg, None, 0, 0, PM_REMOVE | msg_kind).as_bool()
|
||||
};
|
||||
// We process a paint at the start and end only to prevent getting stuck in a paint loop
|
||||
// due to on going gpui animations
|
||||
if peek_msg(&mut msg, PM_QS_PAINT) {
|
||||
process_message(&msg);
|
||||
}
|
||||
while peek_msg(&mut msg, PM_QS_INPUT) {
|
||||
process_message(&msg);
|
||||
}
|
||||
if peek_msg(&mut msg, PM_QS_PAINT) {
|
||||
process_message(&msg);
|
||||
// Allow the main loop to process other gpui events before going back into `run_foreground_task`
|
||||
unsafe {
|
||||
if let Err(_) = PostMessageW(
|
||||
Some(self.dispatcher.platform_window_handle.as_raw()),
|
||||
WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD,
|
||||
WPARAM(self.validation_number),
|
||||
LPARAM(0),
|
||||
) {
|
||||
self.dispatcher.wake_posted.store(false, Ordering::Release);
|
||||
};
|
||||
}
|
||||
start = std::time::Instant::now();
|
||||
break 'tasks;
|
||||
}
|
||||
match self.main_receiver.try_recv() {
|
||||
Err(_) => break,
|
||||
Err(_) => break 'timeout_loop,
|
||||
Ok(runnable) => WindowsDispatcher::execute_runnable(runnable),
|
||||
}
|
||||
}
|
||||
|
||||
// Someone could enqueue a Runnable here. The flag is still true, so they will not PostMessage.
|
||||
// We need to check for those Runnables after we clear the flag.
|
||||
let dispatcher = self.dispatcher.clone();
|
||||
|
||||
dispatcher.wake_posted.store(false, Ordering::Release);
|
||||
self.dispatcher.wake_posted.store(false, Ordering::Release);
|
||||
match self.main_receiver.try_recv() {
|
||||
Err(_) => break 'tasks,
|
||||
Ok(runnable) => {
|
||||
let _ = dispatcher.wake_posted.swap(true, Ordering::AcqRel);
|
||||
self.dispatcher.wake_posted.store(true, Ordering::Release);
|
||||
|
||||
WindowsDispatcher::execute_runnable(runnable);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user