@@ -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;
}
}
}