1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-21 03:39:16 +03:00

add low pri spawn queue

Refs: https://github.com/wez/wezterm/issues/65
This commit is contained in:
Wez Furlong 2019-11-21 15:44:21 -08:00
parent b3032f8a5a
commit 06da330087
8 changed files with 79 additions and 10 deletions

View File

@ -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<dyn Executor> {
Box::new(Self {})
}
}
impl FrontEnd for GuiFrontEnd {
fn executor(&self) -> Box<dyn Executor> {
Box::new(GuiExecutor {})
}
fn low_pri_executor(&self) -> Box<dyn Executor> {
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

View File

@ -30,6 +30,7 @@ impl Default for FrontEndSelection {
lazy_static! {
static ref EXECUTOR: Mutex<Option<Box<dyn Executor>>> = Mutex::new(None);
static ref LOW_PRI_EXECUTOR: Mutex<Option<Box<dyn Executor>>> = Mutex::new(None);
}
thread_local! {
static FRONT_END: RefCell<Option<Rc<dyn FrontEnd>>> = RefCell::new(None);
@ -43,6 +44,14 @@ pub fn executor() -> Box<dyn Executor> {
}
}
pub fn low_pri_executor() -> Box<dyn Executor> {
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<Rc<dyn FrontEnd>> {
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<dyn Executor>;
fn low_pri_executor(&self) -> Box<dyn Executor>;
}
impl_downcast!(FrontEnd);

View File

@ -65,6 +65,10 @@ impl FrontEnd for MuxServerFrontEnd {
})
}
fn low_pri_executor(&self) -> Box<dyn Executor> {
self.executor()
}
fn run_forever(&self) -> Result<(), Error> {
loop {
match self.rx.recv() {

View File

@ -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<Config>, tab_id: TabId, mut reader: Box<dyn std
let len = len as usize;
let data = buf[pos..pos + len].to_vec();
pos += len;
Future::with_executor(executor(), move || {
Future::with_executor(low_pri_executor(), move || {
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) {
tab.advance_bytes(

View File

@ -67,6 +67,10 @@ impl Connection {
pub fn executor() -> impl BasicExecutor {
SpawnQueueExecutor {}
}
pub fn low_pri_executor() -> impl BasicExecutor {
LowPriSpawnQueueExecutor {}
}
}
impl ConnectionOps for Connection {

View File

@ -127,6 +127,10 @@ impl Connection {
SpawnQueueExecutor {}
}
pub fn low_pri_executor() -> impl BasicExecutor {
LowPriSpawnQueueExecutor {}
}
fn get_window(&self, handle: HWindow) -> Option<Rc<RefCell<WindowInner>>> {
self.windows.borrow().get(&handle).map(Rc::clone)
}

View File

@ -482,6 +482,10 @@ impl Connection {
SpawnQueueExecutor {}
}
pub fn low_pri_executor() -> impl BasicExecutor {
LowPriSpawnQueueExecutor {}
}
pub(crate) fn with_window_inner<F: FnMut(&mut WindowInner) + Send + 'static>(
window: xcb::xproto::Window,
mut f: F,

View File

@ -20,6 +20,7 @@ lazy_static::lazy_static! {
pub(crate) struct SpawnQueue {
spawned_funcs: Mutex<VecDeque<SpawnFunc>>,
spawned_funcs_low_pri: Mutex<VecDeque<SpawnFunc>>,
#[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<SpawnFunc> {
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)
}
}