aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKunal Mohan <kunalmohan99@gmail.com>2021-04-09 21:52:46 +0530
committerKunal Mohan <kunalmohan99@gmail.com>2021-04-12 20:33:22 +0530
commit380d69978ce0adde07f63ef8c746d7f32b2d2e38 (patch)
tree876f068616f7e46c41b9364f138ebb001dabed3b /src
parentfix(performance): remove unnecessary allocations from pty (#264) (diff)
downloadsl0ppij-380d69978ce0adde07f63ef8c746d7f32b2d2e38.tar.gz
sl0ppij-380d69978ce0adde07f63ef8c746d7f32b2d2e38.tar.xz
sl0ppij-380d69978ce0adde07f63ef8c746d7f32b2d2e38.zip
make error model more autonomous
Diffstat (limited to 'src')
-rw-r--r--src/common/errors.rs12
-rw-r--r--src/common/input/handler.rs3
-rw-r--r--src/common/mod.rs63
-rw-r--r--src/common/pty_bus.rs9
4 files changed, 40 insertions, 47 deletions
diff --git a/src/common/errors.rs b/src/common/errors.rs
index 9801428c..d0b748ab 100644
--- a/src/common/errors.rs
+++ b/src/common/errors.rs
@@ -1,7 +1,7 @@
//! Error context system based on a thread-local representation of the call stack, itself based on
//! the instructions that are sent between threads.
-use super::{AppInstruction, OPENCALLS};
+use super::{AppInstruction, ASYNCOPENCALLS, OPENCALLS};
use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction;
@@ -72,6 +72,12 @@ pub fn handle_panic(
}
}
+pub fn get_current_ctx() -> ErrorContext {
+ ASYNCOPENCALLS
+ .try_with(|ctx| *ctx.borrow())
+ .unwrap_or_else(|_| OPENCALLS.with(|ctx| *ctx.borrow()))
+}
+
/// A representation of the call stack.
#[derive(Clone, Copy)]
pub struct ErrorContext {
@@ -95,7 +101,9 @@ impl ErrorContext {
break;
}
}
- OPENCALLS.with(|ctx| *ctx.borrow_mut() = *self);
+ ASYNCOPENCALLS
+ .try_with(|ctx| *ctx.borrow_mut() = *self)
+ .unwrap_or_else(|_| OPENCALLS.with(|ctx| *ctx.borrow_mut() = *self));
}
}
diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs
index 44065c67..0afcab10 100644
--- a/src/common/input/handler.rs
+++ b/src/common/input/handler.rs
@@ -58,9 +58,6 @@ impl InputHandler {
fn handle_input(&mut self) {
let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
err_ctx.add_call(ContextType::StdinHandler);
- self.send_pty_instructions.update(err_ctx);
- self.send_app_instructions.update(err_ctx);
- self.send_screen_instructions.update(err_ctx);
let keybinds = self.config.keybinds.clone();
let alt_left_bracket = vec![27, 91];
loop {
diff --git a/src/common/mod.rs b/src/common/mod.rs
index 2466aecf..19f8e4bc 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -25,9 +25,13 @@ use crate::cli::CliArgs;
use crate::common::input::config::Config;
use crate::layout::Layout;
use crate::panes::PaneId;
+use async_std::task_local;
use command_is_executing::CommandIsExecuting;
use directories_next::ProjectDirs;
-use errors::{AppContext, ContextType, ErrorContext, PluginContext, PtyContext, ScreenContext};
+use errors::{
+ get_current_ctx, AppContext, ContextType, ErrorContext, PluginContext, PtyContext,
+ ScreenContext,
+};
use input::handler::input_loop;
use os_input_output::OsApi;
use pty_bus::{PtyBus, PtyInstruction};
@@ -72,32 +76,23 @@ enum SenderType<T: Clone> {
/// synchronously or asynchronously depending on the underlying [`SenderType`].
#[derive(Clone)]
pub struct SenderWithContext<T: Clone> {
- err_ctx: ErrorContext,
sender: SenderType<T>,
}
impl<T: Clone> SenderWithContext<T> {
- fn new(err_ctx: ErrorContext, sender: SenderType<T>) -> Self {
- Self { err_ctx, sender }
+ fn new(sender: SenderType<T>) -> Self {
+ Self { sender }
}
/// Sends an event, along with the current [`ErrorContext`], on this
/// [`SenderWithContext`]'s channel.
pub fn send(&self, event: T) -> Result<(), mpsc::SendError<(T, ErrorContext)>> {
+ let err_ctx = get_current_ctx();
match self.sender {
- SenderType::Sender(ref s) => s.send((event, self.err_ctx)),
- SenderType::SyncSender(ref s) => s.send((event, self.err_ctx)),
+ SenderType::Sender(ref s) => s.send((event, err_ctx)),
+ SenderType::SyncSender(ref s) => s.send((event, err_ctx)),
}
}
-
- /// Updates this [`SenderWithContext`]'s [`ErrorContext`]. This is the way one adds
- /// a call to the error context.
- ///
- /// Updating [`ErrorContext`]s works in this way so that these contexts are only ever
- /// allocated on the stack (which is thread-specific), and not on the heap.
- pub fn update(&mut self, new_ctx: ErrorContext) {
- self.err_ctx = new_ctx;
- }
}
unsafe impl<T: Clone> Send for SenderWithContext<T> {}
@@ -109,6 +104,12 @@ thread_local!(
static OPENCALLS: RefCell<ErrorContext> = RefCell::default()
);
+task_local! {
+ /// A key to some thread local storage (TLS) that holds a representation of the task's call
+ /// stack in the form of an [`ErrorContext`].
+ static ASYNCOPENCALLS: RefCell<ErrorContext> = RefCell::default()
+}
+
/// Instructions related to the entire application.
#[derive(Clone)]
pub enum AppInstruction {
@@ -140,25 +141,23 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let (send_screen_instructions, receive_screen_instructions): ChannelWithContext<
ScreenInstruction,
> = mpsc::channel();
- let err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
- let mut send_screen_instructions =
- SenderWithContext::new(err_ctx, SenderType::Sender(send_screen_instructions));
+ let send_screen_instructions =
+ SenderWithContext::new(SenderType::Sender(send_screen_instructions));
let (send_pty_instructions, receive_pty_instructions): ChannelWithContext<PtyInstruction> =
mpsc::channel();
- let mut send_pty_instructions =
- SenderWithContext::new(err_ctx, SenderType::Sender(send_pty_instructions));
+ let send_pty_instructions = SenderWithContext::new(SenderType::Sender(send_pty_instructions));
let (send_plugin_instructions, receive_plugin_instructions): ChannelWithContext<
PluginInstruction,
> = mpsc::channel();
let send_plugin_instructions =
- SenderWithContext::new(err_ctx, SenderType::Sender(send_plugin_instructions));
+ SenderWithContext::new(SenderType::Sender(send_plugin_instructions));
let (send_app_instructions, receive_app_instructions): SyncChannelWithContext<AppInstruction> =
mpsc::sync_channel(0);
let send_app_instructions =
- SenderWithContext::new(err_ctx, SenderType::SyncSender(send_app_instructions));
+ SenderWithContext::new(SenderType::SyncSender(send_app_instructions));
let mut pty_bus = PtyBus::new(
receive_pty_instructions,
@@ -195,7 +194,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.recv()
.expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
- pty_bus.send_screen_instructions.update(err_ctx);
match event {
PtyInstruction::SpawnTerminal(file_to_open) => {
let pid = pty_bus.spawn_terminal(file_to_open);
@@ -272,8 +270,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.recv()
.expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
- screen.send_app_instructions.update(err_ctx);
- screen.send_pty_instructions.update(err_ctx);
match event {
ScreenInstruction::PtyBytes(pid, vte_bytes) => {
let active_tab = screen.get_active_tab_mut().unwrap();
@@ -433,9 +429,9 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let wasm_thread = thread::Builder::new()
.name("wasm".to_string())
.spawn({
- let mut send_pty_instructions = send_pty_instructions.clone();
- let mut send_screen_instructions = send_screen_instructions.clone();
- let mut send_app_instructions = send_app_instructions.clone();
+ let send_pty_instructions = send_pty_instructions.clone();
+ let send_screen_instructions = send_screen_instructions.clone();
+ let send_app_instructions = send_app_instructions.clone();
let store = Store::default();
let mut plugin_id = 0;
@@ -445,9 +441,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.recv()
.expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
- send_screen_instructions.update(err_ctx);
- send_pty_instructions.update(err_ctx);
- send_app_instructions.update(err_ctx);
match event {
PluginInstruction::Load(pid_tx, path) => {
let project_dirs =
@@ -556,16 +549,14 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.name("ipc_server".to_string())
.spawn({
use std::io::Read;
- let mut send_pty_instructions = send_pty_instructions.clone();
- let mut send_screen_instructions = send_screen_instructions.clone();
+ let send_pty_instructions = send_pty_instructions.clone();
+ let send_screen_instructions = send_screen_instructions.clone();
move || {
std::fs::remove_file(ZELLIJ_IPC_PIPE).ok();
let listener = std::os::unix::net::UnixListener::bind(ZELLIJ_IPC_PIPE)
.expect("could not listen on ipc socket");
let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
err_ctx.add_call(ContextType::IpcServer);
- send_pty_instructions.update(err_ctx);
- send_screen_instructions.update(err_ctx);
for stream in listener.incoming() {
match stream {
@@ -637,8 +628,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.expect("failed to receive app instruction on channel");
err_ctx.add_call(ContextType::App(AppContext::from(&app_instruction)));
- send_screen_instructions.update(err_ctx);
- send_pty_instructions.update(err_ctx);
match app_instruction {
AppInstruction::Exit => {
break;
diff --git a/src/common/pty_bus.rs b/src/common/pty_bus.rs
index 2cab8ae8..28ae62f2 100644
--- a/src/common/pty_bus.rs
+++ b/src/common/pty_bus.rs
@@ -8,11 +8,11 @@ use ::std::sync::mpsc::Receiver;
use ::std::time::{Duration, Instant};
use std::path::PathBuf;
-use super::{ScreenInstruction, SenderWithContext, OPENCALLS};
+use super::{ScreenInstruction, SenderWithContext};
use crate::os_input_output::OsApi;
use crate::utils::logging::debug_to_file;
use crate::{
- errors::{ContextType, ErrorContext},
+ errors::{get_current_ctx, ContextType, ErrorContext},
panes::PaneId,
};
use crate::{layout::Layout, wasm_vm::PluginInstruction};
@@ -89,15 +89,14 @@ pub struct PtyBus {
fn stream_terminal_bytes(
pid: RawFd,
- mut send_screen_instructions: SenderWithContext<ScreenInstruction>,
+ send_screen_instructions: SenderWithContext<ScreenInstruction>,
os_input: Box<dyn OsApi>,
debug: bool,
) -> JoinHandle<()> {
- let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
+ let mut err_ctx = get_current_ctx();
task::spawn({
async move {
err_ctx.add_call(ContextType::AsyncTask);
- send_screen_instructions.update(err_ctx);
let mut terminal_bytes = ReadFromPid::new(&pid, os_input);
let mut last_byte_receive_time: Option<Instant> = None;