From 06da330087c903b83e22f62cc422227eba1d6b82 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Thu, 21 Nov 2019 15:44:21 -0800 Subject: [PATCH] add low pri spawn queue Refs: https://github.com/wez/wezterm/issues/65 --- src/frontend/gui/mod.rs | 17 +++++++++++++ src/frontend/mod.rs | 14 +++++++++++ src/frontend/muxserver/mod.rs | 4 +++ src/mux/mod.rs | 4 +-- window/src/os/macos/connection.rs | 4 +++ window/src/os/windows/connection.rs | 4 +++ window/src/os/x11/connection.rs | 4 +++ window/src/spawn.rs | 38 +++++++++++++++++++++++------ 8 files changed, 79 insertions(+), 10 deletions(-) diff --git a/src/frontend/gui/mod.rs b/src/frontend/gui/mod.rs index 4e66eb207..cdb4b193f 100644 --- a/src/frontend/gui/mod.rs +++ b/src/frontend/gui/mod.rs @@ -57,11 +57,28 @@ impl Executor for GuiExecutor { } } +struct LowPriGuiExecutor {} +impl BasicExecutor for LowPriGuiExecutor { + fn execute(&self, f: SpawnFunc) { + Connection::low_pri_executor().execute(f) + } +} + +impl Executor for LowPriGuiExecutor { + fn clone_executor(&self) -> Box { + Box::new(Self {}) + } +} + impl FrontEnd for GuiFrontEnd { fn executor(&self) -> Box { Box::new(GuiExecutor {}) } + fn low_pri_executor(&self) -> Box { + Box::new(GuiExecutor {}) + } + fn run_forever(&self) -> Fallible<()> { // We run until we've run out of windows in the Mux. // When we're running ssh we have a transient window diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 2513f1670..4437f67fd 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -30,6 +30,7 @@ impl Default for FrontEndSelection { lazy_static! { static ref EXECUTOR: Mutex>> = Mutex::new(None); + static ref LOW_PRI_EXECUTOR: Mutex>> = Mutex::new(None); } thread_local! { static FRONT_END: RefCell>> = RefCell::new(None); @@ -43,6 +44,14 @@ pub fn executor() -> Box { } } +pub fn low_pri_executor() -> Box { + let locked = LOW_PRI_EXECUTOR.lock().unwrap(); + match locked.as_ref() { + Some(exec) => exec.clone_executor(), + None => panic!("executor machinery not yet configured"), + } +} + pub fn front_end() -> Option> { let mut res = None; FRONT_END.with(|f| { @@ -63,6 +72,10 @@ impl FrontEndSelection { }?; EXECUTOR.lock().unwrap().replace(front_end.executor()); + LOW_PRI_EXECUTOR + .lock() + .unwrap() + .replace(front_end.low_pri_executor()); FRONT_END.with(|f| *f.borrow_mut() = Some(Rc::clone(&front_end))); Ok(front_end) @@ -105,5 +118,6 @@ pub trait FrontEnd: Downcast { ) -> Fallible<()>; fn executor(&self) -> Box; + fn low_pri_executor(&self) -> Box; } impl_downcast!(FrontEnd); diff --git a/src/frontend/muxserver/mod.rs b/src/frontend/muxserver/mod.rs index ee75c3c70..433274b00 100644 --- a/src/frontend/muxserver/mod.rs +++ b/src/frontend/muxserver/mod.rs @@ -65,6 +65,10 @@ impl FrontEnd for MuxServerFrontEnd { }) } + fn low_pri_executor(&self) -> Box { + self.executor() + } + fn run_forever(&self) -> Result<(), Error> { loop { match self.rx.recv() { diff --git a/src/mux/mod.rs b/src/mux/mod.rs index 715f11bb3..b680d9d0f 100644 --- a/src/mux/mod.rs +++ b/src/mux/mod.rs @@ -1,5 +1,5 @@ use crate::config::Config; -use crate::frontend::executor; +use crate::frontend::{executor, low_pri_executor}; use crate::mux::tab::{Tab, TabId}; use crate::mux::window::{Window, WindowId}; use crate::ratelim::RateLimiter; @@ -75,7 +75,7 @@ fn read_from_tab_pty(config: Arc, tab_id: TabId, mut reader: Box impl BasicExecutor { SpawnQueueExecutor {} } + + pub fn low_pri_executor() -> impl BasicExecutor { + LowPriSpawnQueueExecutor {} + } } impl ConnectionOps for Connection { diff --git a/window/src/os/windows/connection.rs b/window/src/os/windows/connection.rs index e76bf2d13..9cf2a83d3 100644 --- a/window/src/os/windows/connection.rs +++ b/window/src/os/windows/connection.rs @@ -127,6 +127,10 @@ impl Connection { SpawnQueueExecutor {} } + pub fn low_pri_executor() -> impl BasicExecutor { + LowPriSpawnQueueExecutor {} + } + fn get_window(&self, handle: HWindow) -> Option>> { self.windows.borrow().get(&handle).map(Rc::clone) } diff --git a/window/src/os/x11/connection.rs b/window/src/os/x11/connection.rs index 009afa50a..9f68bbd51 100644 --- a/window/src/os/x11/connection.rs +++ b/window/src/os/x11/connection.rs @@ -482,6 +482,10 @@ impl Connection { SpawnQueueExecutor {} } + pub fn low_pri_executor() -> impl BasicExecutor { + LowPriSpawnQueueExecutor {} + } + pub(crate) fn with_window_inner( window: xcb::xproto::Window, mut f: F, diff --git a/window/src/spawn.rs b/window/src/spawn.rs index 0fe8480f3..0baa8b372 100644 --- a/window/src/spawn.rs +++ b/window/src/spawn.rs @@ -20,6 +20,7 @@ lazy_static::lazy_static! { pub(crate) struct SpawnQueue { spawned_funcs: Mutex>, + spawned_funcs_low_pri: Mutex>, #[cfg(windows)] pub event_handle: EventHandle, @@ -36,7 +37,7 @@ impl SpawnQueue { } pub fn spawn(&self, f: SpawnFunc) { - self.spawn_impl(f) + self.spawn_impl(f, true) } pub fn run(&self) -> bool { @@ -47,7 +48,20 @@ impl SpawnQueue { // in order for the lock to be released before we call the // returned function fn pop_func(&self) -> Option { - self.spawned_funcs.lock().unwrap().pop_front() + if let Some(func) = self.spawned_funcs.lock().unwrap().pop_front() { + Some(func) + } else { + self.spawned_funcs_low_pri.lock().unwrap().pop_front() + } + } + + fn queue_func(&self, f: SpawnFunc, high_pri: bool) { + if high_pri { + self.spawned_funcs.lock().unwrap() + } else { + self.spawned_funcs_low_pri.lock().unwrap() + } + .push_back(f); } } @@ -62,8 +76,8 @@ impl SpawnQueue { }) } - fn spawn_impl(&self, f: SpawnFunc) { - self.spawned_funcs.lock().unwrap().push_back(f); + fn spawn_impl(&self, f: SpawnFunc, high_pri: bool) { + self.queue_func(f, high_pri); self.event_handle.set_event(); } @@ -99,15 +113,16 @@ impl SpawnQueue { } Ok(Self { spawned_funcs: Mutex::new(VecDeque::new()), + spawned_funcs_low_pri: Mutex::new(VecDeque::new()), write: Mutex::new(pipe.write), read: Mutex::new(pipe.read), }) } - fn spawn_impl(&self, f: SpawnFunc) { + fn spawn_impl(&self, f: SpawnFunc, high_pri: bool) { use std::io::Write; - self.spawned_funcs.lock().unwrap().push_back(f); + self.queue_func(f, high_pri); self.write.lock().unwrap().write(b"x").ok(); } @@ -193,8 +208,8 @@ impl SpawnQueue { } } - fn spawn_impl(&self, f: SpawnFunc) { - self.spawned_funcs.lock().unwrap().push_back(f); + fn spawn_impl(&self, f: SpawnFunc, high_pri: bool) { + self.queue_func(f, high_pri); self.queue_wakeup(); } @@ -214,3 +229,10 @@ impl BasicExecutor for SpawnQueueExecutor { SPAWN_QUEUE.spawn(f) } } + +pub struct LowPriSpawnQueueExecutor; +impl BasicExecutor for LowPriSpawnQueueExecutor { + fn execute(&self, f: SpawnFunc) { + SPAWN_QUEUE.spawn_impl(f, false) + } +}