1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 06:54:45 +03:00

migrate some more code to the newer spawn mechanism

This commit is contained in:
Wez Furlong 2020-01-16 09:15:07 -08:00
parent 75eb16bec4
commit 9ec4694d89
10 changed files with 159 additions and 83 deletions

95
Cargo.lock generated
View File

@ -131,6 +131,31 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
[[package]]
name = "async-std"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf6039b315300e057d198b9d3ab92ee029e31c759b7f1afae538145e6f18a3e"
dependencies = [
"async-task",
"crossbeam-channel 0.4.0",
"crossbeam-deque",
"crossbeam-utils 0.7.0",
"futures-core",
"futures-io",
"futures-timer",
"kv-log-macro",
"log",
"memchr",
"mio",
"mio-uds",
"num_cpus",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "async-task" name = "async-task"
version = "1.2.1" version = "1.2.1"
@ -500,6 +525,15 @@ dependencies = [
"crossbeam-utils 0.6.6", "crossbeam-utils 0.6.6",
] ]
[[package]]
name = "crossbeam-channel"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
dependencies = [
"crossbeam-utils 0.7.0",
]
[[package]] [[package]]
name = "crossbeam-deque" name = "crossbeam-deque"
version = "0.7.2" version = "0.7.2"
@ -977,6 +1011,24 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures-core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866"
[[package]]
name = "futures-io"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff"
[[package]]
name = "futures-timer"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.1.14" version = "0.1.14"
@ -1073,7 +1125,7 @@ checksum = "08d331ebcdbca4acbefe5da8c3299b2e246f198a8294cc5163354e743398b89d"
dependencies = [ dependencies = [
"base64", "base64",
"byteorder", "byteorder",
"crossbeam-channel", "crossbeam-channel 0.3.9",
"flate2", "flate2",
"nom 4.2.3", "nom 4.2.3",
"num-traits 0.2.11", "num-traits 0.2.11",
@ -1232,6 +1284,15 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kv-log-macro"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb"
dependencies = [
"log",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -1504,6 +1565,17 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "mio-uds"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
dependencies = [
"iovec",
"libc",
"mio",
]
[[package]] [[package]]
name = "miow" name = "miow"
version = "0.2.1" version = "0.2.1"
@ -1755,6 +1827,12 @@ dependencies = [
"objc", "objc",
] ]
[[package]]
name = "once_cell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5941ec2d5ee5916c709580d71553b81a633df245bcc73c04dcbd62152ceefc4"
[[package]] [[package]]
name = "open" name = "open"
version = "1.3.2" version = "1.3.2"
@ -1919,6 +1997,18 @@ dependencies = [
"siphasher", "siphasher",
] ]
[[package]]
name = "pin-project-lite"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8822eb8bb72452f038ebf6048efa02c3fe22bf83f76519c9583e47fc194a422"
[[package]]
name = "pin-utils"
version = "0.1.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.17" version = "0.3.17"
@ -2020,6 +2110,7 @@ name = "promise"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-std",
"async-task", "async-task",
"lazy_static", "lazy_static",
"thiserror", "thiserror",
@ -3153,7 +3244,7 @@ dependencies = [
"core-foundation 0.7.0", "core-foundation 0.7.0",
"core-graphics 0.19.0", "core-graphics 0.19.0",
"core-text 15.0.0", "core-text 15.0.0",
"crossbeam-channel", "crossbeam-channel 0.3.9",
"daemonize", "daemonize",
"dirs 1.0.5", "dirs 1.0.5",
"downcast-rs", "downcast-rs",

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
async-task = "1.2" async-task = "1.2"
async-std = "1.4"
anyhow = "1.0" anyhow = "1.0"
thiserror = "1.0" thiserror = "1.0"
lazy_static = "1.3" lazy_static = "1.3"

View File

@ -148,3 +148,6 @@ where
task.schedule(); task.schedule();
handle handle
} }
/// Block the current thread until the passed future completes.
pub use async_std::task::block_on;

View File

@ -5,10 +5,10 @@ use super::utilsprites::RenderMetrics;
use crate::config::{configuration, ConfigHandle}; use crate::config::{configuration, ConfigHandle};
use crate::font::units::*; use crate::font::units::*;
use crate::font::FontConfiguration; use crate::font::FontConfiguration;
use crate::frontend::front_end;
use crate::frontend::gui::scrollbar::*; use crate::frontend::gui::scrollbar::*;
use crate::frontend::gui::selection::*; use crate::frontend::gui::selection::*;
use crate::frontend::gui::tabbar::{TabBarItem, TabBarState}; use crate::frontend::gui::tabbar::{TabBarItem, TabBarState};
use crate::frontend::{executor, front_end};
use crate::keyassignment::{KeyAssignment, KeyMap, SpawnTabDomain}; use crate::keyassignment::{KeyAssignment, KeyMap, SpawnTabDomain};
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition}; use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
use crate::mux::tab::{Tab, TabId}; use crate::mux::tab::{Tab, TabId};
@ -178,12 +178,11 @@ impl<'a> term::TerminalHost for Host<'a> {
// of our window loop; on Windows it can cause a panic due to // of our window loop; on Windows it can cause a panic due to
// triggering our WndProc recursively. // triggering our WndProc recursively.
let link = link.clone(); let link = link.clone();
promise::Future::with_executor(executor(), move || { promise::spawn::spawn(async move {
log::error!("clicking {}", link.uri()); log::error!("clicking {}", link.uri());
if let Err(err) = open::that(link.uri()) { if let Err(err) = open::that(link.uri()) {
log::error!("failed to open {}: {:?}", link.uri(), err); log::error!("failed to open {}: {:?}", link.uri(), err);
} }
Ok(())
}); });
} }
} }
@ -1161,13 +1160,10 @@ impl TermWindow {
let future = self.window.as_ref().unwrap().get_clipboard(); let future = self.window.as_ref().unwrap().get_clipboard();
promise::spawn::spawn(async move { promise::spawn::spawn(async move {
if let Ok(clip) = future.await { if let Ok(clip) = future.await {
promise::Future::with_executor(executor(), move || {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) { if let Some(tab) = mux.get_tab(tab_id) {
tab.trickle_paste(clip)?; tab.trickle_paste(clip).ok();
} }
Ok(())
});
} }
}); });
} }
@ -1202,7 +1198,7 @@ impl TermWindow {
} }
pub fn spawn_new_window(&mut self) { pub fn spawn_new_window(&mut self) {
promise::Future::with_executor(executor(), move || { async fn new_window() -> anyhow::Result<()> {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
let fonts = Rc::new(FontConfiguration::new()); let fonts = Rc::new(FontConfiguration::new());
let window_id = mux.new_empty_window(); let window_id = mux.new_empty_window();
@ -1212,6 +1208,9 @@ impl TermWindow {
let front_end = front_end().expect("to be called on gui thread"); let front_end = front_end().expect("to be called on gui thread");
front_end.spawn_new_window(&fonts, &tab, window_id)?; front_end.spawn_new_window(&fonts, &tab, window_id)?;
Ok(()) Ok(())
}
promise::spawn::spawn(async move {
new_window().await.ok();
}); });
} }
@ -2536,12 +2535,11 @@ impl TermWindow {
// of our window loop; on Windows it can cause a panic due to // of our window loop; on Windows it can cause a panic due to
// triggering our WndProc recursively. // triggering our WndProc recursively.
let link = self.current_highlight.as_ref().unwrap().clone(); let link = self.current_highlight.as_ref().unwrap().clone();
promise::Future::with_executor(executor(), move || { promise::spawn::spawn(async move {
log::error!("clicking {}", link.uri()); log::error!("clicking {}", link.uri());
if let Err(err) = open::that(link.uri()) { if let Err(err) = open::that(link.uri()) {
log::error!("failed to open {}: {:?}", link.uri(), err); log::error!("failed to open {}: {:?}", link.uri(), err);
} }
Ok(())
}); });
} else { } else {
self.window.as_ref().unwrap().set_clipboard(text); self.window.as_ref().unwrap().set_clipboard(text);
@ -2656,13 +2654,10 @@ impl TermWindow {
let future = self.window.as_ref().unwrap().get_clipboard(); let future = self.window.as_ref().unwrap().get_clipboard();
promise::spawn::spawn(async move { promise::spawn::spawn(async move {
if let Ok(clip) = future.await { if let Ok(clip) = future.await {
promise::Future::with_executor(executor(), move || {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) { if let Some(tab) = mux.get_tab(tab_id) {
tab.trickle_paste(clip)?; tab.trickle_paste(clip).ok();
} }
Ok(())
});
} }
}); });
return; return;

View File

@ -44,14 +44,6 @@ 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>> { pub fn front_end() -> Option<Rc<dyn FrontEnd>> {
let mut res = None; let mut res = None;
FRONT_END.with(|f| { FRONT_END.with(|f| {

View File

@ -1,4 +1,3 @@
use crate::frontend::{executor, low_pri_executor};
use crate::mux::tab::{Tab, TabId}; use crate::mux::tab::{Tab, TabId};
use crate::mux::window::{Window, WindowId}; use crate::mux::window::{Window, WindowId};
use crate::ratelim::RateLimiter; use crate::ratelim::RateLimiter;
@ -7,7 +6,6 @@ use anyhow::{anyhow, Error};
use domain::{Domain, DomainId}; use domain::{Domain, DomainId};
use log::{debug, error}; use log::{debug, error};
use portable_pty::ExitStatus; use portable_pty::ExitStatus;
use promise::Future;
use std::cell::{Ref, RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Read; use std::io::Read;
@ -68,7 +66,7 @@ fn read_from_tab_pty(tab_id: TabId, mut reader: Box<dyn std::io::Read>) {
let len = len as usize; let len = len as usize;
let data = buf[pos..pos + len].to_vec(); let data = buf[pos..pos + len].to_vec();
pos += len; pos += len;
Future::with_executor(low_pri_executor(), move || { promise::spawn::spawn_into_main_thread_with_low_priority(async move {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) { if let Some(tab) = mux.get_tab(tab_id) {
tab.advance_bytes( tab.advance_bytes(
@ -79,7 +77,6 @@ fn read_from_tab_pty(tab_id: TabId, mut reader: Box<dyn std::io::Read>) {
); );
mux.notify(MuxNotification::TabOutput(tab_id)); mux.notify(MuxNotification::TabOutput(tab_id));
} }
Ok(())
}); });
} }
Err(delay) => { Err(delay) => {
@ -91,10 +88,9 @@ fn read_from_tab_pty(tab_id: TabId, mut reader: Box<dyn std::io::Read>) {
} }
} }
} }
Future::with_executor(executor(), move || { promise::spawn::spawn_into_main_thread(async move {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
mux.remove_tab(tab_id); mux.remove_tab(tab_id);
Ok(())
}); });
} }

View File

@ -1,4 +1,3 @@
use crate::frontend::executor;
use crate::mux::domain::DomainId; use crate::mux::domain::DomainId;
use crate::mux::renderable::Renderable; use crate::mux::renderable::Renderable;
use crate::mux::Mux; use crate::mux::Mux;
@ -27,7 +26,7 @@ struct Paste {
fn schedule_next_paste(paste: &Arc<Mutex<Paste>>) { fn schedule_next_paste(paste: &Arc<Mutex<Paste>>) {
let paste = Arc::clone(paste); let paste = Arc::clone(paste);
promise::Future::with_executor(executor(), move || { promise::spawn::spawn(async move {
let mut locked = paste.lock().unwrap(); let mut locked = paste.lock().unwrap();
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
let tab = mux.get_tab(locked.tab_id).unwrap(); let tab = mux.get_tab(locked.tab_id).unwrap();
@ -42,8 +41,6 @@ fn schedule_next_paste(paste: &Arc<Mutex<Paste>>) {
locked.offset += chunk; locked.offset += chunk;
schedule_next_paste(&paste); schedule_next_paste(&paste);
} }
Ok(())
}); });
} }

View File

@ -56,7 +56,7 @@ fn password_prompt(
(output, unicode_column_width(placeholder) * cursor_position) (output, unicode_column_width(placeholder) * cursor_position)
} }
} }
match termwiztermtab::run(60, 10, move |mut term| { match promise::spawn::block_on(termwiztermtab::run(60, 10, move |mut term| {
term.render(&[ term.render(&[
// Change::Attribute(AttributeChange::Intensity(Intensity::Bold)), // Change::Attribute(AttributeChange::Intensity(Intensity::Bold)),
Change::Title(title.to_string()), Change::Title(title.to_string()),
@ -73,9 +73,7 @@ fn password_prompt(
} else { } else {
bail!("prompt cancelled"); bail!("prompt cancelled");
} }
}) })) {
.wait()
{
Ok(p) => Some(p), Ok(p) => Some(p),
Err(p) => { Err(p) => {
log::error!("failed to prompt for pw: {}", p); log::error!("failed to prompt for pw: {}", p);
@ -95,7 +93,7 @@ fn input_prompt(
"SSH Authentication for {} @ {}\r\n{}\r\n{}\r\n", "SSH Authentication for {} @ {}\r\n{}\r\n{}\r\n",
username, remote_address, instructions, prompt username, remote_address, instructions, prompt
); );
match termwiztermtab::run(60, 10, move |mut term| { match promise::spawn::block_on(termwiztermtab::run(60, 10, move |mut term| {
term.render(&[ term.render(&[
Change::Title(title.to_string()), Change::Title(title.to_string()),
Change::Text(text.to_string()), Change::Text(text.to_string()),
@ -110,9 +108,7 @@ fn input_prompt(
} else { } else {
bail!("prompt cancelled"); bail!("prompt cancelled");
} }
}) })) {
.wait()
{
Ok(p) => Some(p), Ok(p) => Some(p),
Err(p) => { Err(p) => {
log::error!("failed to prompt for pw: {}", p); log::error!("failed to prompt for pw: {}", p);
@ -229,7 +225,8 @@ pub fn ssh_connect(remote_address: &str, username: &str) -> anyhow::Result<ssh2:
remote_address, key_type, fingerprint remote_address, key_type, fingerprint
); );
let allow = termwiztermtab::run(80, 10, move |mut term| { let allow =
promise::spawn::block_on(termwiztermtab::run(80, 10, move |mut term| {
let title = "🔐 wezterm: SSH authentication".to_string(); let title = "🔐 wezterm: SSH authentication".to_string();
term.render(&[Change::Title(title), Change::Text(message.to_string())])?; term.render(&[Change::Title(title), Change::Text(message.to_string())])?;
@ -248,8 +245,7 @@ pub fn ssh_connect(remote_address: &str, username: &str) -> anyhow::Result<ssh2:
_ => continue, _ => continue,
} }
} }
}) }))?;
.wait()?;
if !allow { if !allow {
bail!("user declined to trust host"); bail!("user declined to trust host");

View File

@ -5,7 +5,7 @@
use crate::config::configuration; use crate::config::configuration;
use crate::font::FontConfiguration; use crate::font::FontConfiguration;
use crate::frontend::{executor, front_end}; use crate::frontend::{front_end};
use crate::mux::domain::{alloc_domain_id, Domain, DomainId, DomainState}; use crate::mux::domain::{alloc_domain_id, Domain, DomainId, DomainState};
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition}; use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
use crate::mux::tab::{alloc_tab_id, Tab, TabId}; use crate::mux::tab::{alloc_tab_id, Tab, TabId};
@ -15,7 +15,6 @@ use anyhow::{bail, Error};
use crossbeam_channel::{unbounded as channel, Receiver, Sender}; use crossbeam_channel::{unbounded as channel, Receiver, Sender};
use filedescriptor::Pipe; use filedescriptor::Pipe;
use portable_pty::*; use portable_pty::*;
use promise::{Future, Promise};
use rangeset::RangeSet; use rangeset::RangeSet;
use std::cell::RefCell; use std::cell::RefCell;
use std::cell::RefMut; use std::cell::RefMut;
@ -375,11 +374,14 @@ impl termwiz::terminal::Terminal for TermWizTerminal {
/// from the terminal window. /// from the terminal window.
/// When it completes its loop it will fulfil a promise and yield /// When it completes its loop it will fulfil a promise and yield
/// the return value from the function. /// the return value from the function.
pub fn run<T: Send + 'static, F: Send + 'static + Fn(TermWizTerminal) -> anyhow::Result<T>>( pub async fn run<
T: Send + 'static,
F: Send + 'static + Fn(TermWizTerminal) -> anyhow::Result<T>,
>(
width: usize, width: usize,
height: usize, height: usize,
f: F, f: F,
) -> Future<T> { ) -> anyhow::Result<T> {
let (render_tx, render_rx) = channel(); let (render_tx, render_rx) = channel();
let (input_tx, input_rx) = channel(); let (input_tx, input_rx) = channel();
@ -394,10 +396,12 @@ pub fn run<T: Send + 'static, F: Send + 'static + Fn(TermWizTerminal) -> anyhow:
}, },
}; };
let mut promise = Promise::new(); async fn register_tab(
let future = promise.get_future().expect("just made the promise"); input_tx: Sender<InputEvent>,
render_rx: Receiver<Vec<Change>>,
Future::with_executor(executor(), move || { width: usize,
height: usize,
) -> anyhow::Result<()> {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
// TODO: make a singleton // TODO: make a singleton
@ -426,20 +430,22 @@ pub fn run<T: Send + 'static, F: Send + 'static + Fn(TermWizTerminal) -> anyhow:
gui.spawn_new_window(&fontconfig, &tab, window_id)?; gui.spawn_new_window(&fontconfig, &tab, window_id)?;
Ok(()) Ok(())
}
promise::spawn::spawn_into_main_thread(async move {
register_tab(input_tx, render_rx, width, height).await.ok();
}); });
std::thread::spawn(move || { promise::spawn::spawn_into_new_thread(move || f(tw_term))
promise.result(f(tw_term)); .await
}); .unwrap_or_else(|| bail!("task panicked or was cancelled"))
future
} }
pub fn message_box_ok(message: &str) { pub fn message_box_ok(message: &str) {
let title = "wezterm"; let title = "wezterm";
let message = message.to_string(); let message = message.to_string();
run(60, 10, move |mut term| { promise::spawn::block_on(run(60, 10, move |mut term| {
term.render(&[ term.render(&[
Change::Title(title.to_string()), Change::Title(title.to_string()),
Change::Text(message.to_string()), Change::Text(message.to_string()),
@ -452,7 +458,6 @@ pub fn message_box_ok(message: &str) {
let mut host = NopLineEditorHost::default(); let mut host = NopLineEditorHost::default();
editor.read_line(&mut host).ok(); editor.read_line(&mut host).ok();
Ok(()) Ok(())
}) }))
.wait()
.ok(); .ok();
} }

View File

@ -488,7 +488,7 @@ impl Display for ITermFileData {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
write!(f, "File")?; write!(f, "File")?;
let mut sep = "="; let mut sep = "=";
let emit_sep = |sep, f: &mut Formatter| { let emit_sep = |sep, f: &mut Formatter| -> Result<&str, FmtError> {
write!(f, "{}", sep)?; write!(f, "{}", sep)?;
Ok(";") Ok(";")
}; };