diff --git a/src/input.rs b/src/input.rs index c2715c755..5ad6260a4 100644 --- a/src/input.rs +++ b/src/input.rs @@ -21,6 +21,7 @@ use crate::threads::{assert_is_main_thread, iothread_service_main}; use crate::wchar::prelude::*; use once_cell::sync::Lazy; +use std::cell::RefMut; use std::sync::{ atomic::{AtomicU32, Ordering}, Mutex, MutexGuard, @@ -450,7 +451,7 @@ fn paste_commit(&mut self) { ))); } - fn blocking_wait(&self) -> MutexGuard> { + fn blocking_wait(&self) -> RefMut<'_, Option> { Reader::blocking_wait(self) } diff --git a/src/input_common.rs b/src/input_common.rs index 110612e30..4e644eb6e 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -27,12 +27,12 @@ use crate::wchar::{encode_byte_to_char, prelude::*}; use crate::wutil::encoding::{mbrtowc, mbstate_t, zero_mbstate}; use crate::wutil::fish_wcstol; +use std::cell::{RefCell, RefMut}; use std::collections::VecDeque; use std::os::fd::RawFd; use std::os::unix::ffi::OsStrExt; use std::ptr; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use std::sync::{Mutex, MutexGuard}; use std::time::Duration; // The range of key codes for inputrc-style keyboard functions. @@ -1628,10 +1628,7 @@ fn drop_leading_readline_events(&mut self) { } } - fn blocking_wait(&self) -> MutexGuard> { - static NO_WAIT: Mutex> = Mutex::new(None); - NO_WAIT.lock().unwrap() - } + fn blocking_wait(&self) -> RefMut<'_, Option>; fn is_blocked(&self) -> bool { self.blocking_wait().is_some() } @@ -1753,7 +1750,7 @@ pub(crate) fn decode_input_byte( invalid(out_seq, || FLOG!(reader, "Illegal codepoint")) } -pub(crate) fn unblock_input(mut wait_guard: MutexGuard>) -> bool { +pub(crate) fn unblock_input(mut wait_guard: RefMut<'_, Option>) -> bool { if wait_guard.is_none() { return false; } @@ -1787,12 +1784,14 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// A simple, concrete implementation of InputEventQueuer. pub struct InputEventQueue { data: InputData, + blocking_wait: RefCell>, } impl InputEventQueue { pub fn new(in_fd: RawFd) -> Self { Self { data: InputData::new(in_fd), + blocking_wait: RefCell::new(None), } } } @@ -1811,6 +1810,9 @@ fn select_interrupted(&mut self) { self.enqueue_interrupt_key(); } } + fn blocking_wait(&self) -> RefMut<'_, Option> { + self.blocking_wait.borrow_mut() + } } fn parse_hex(hex: &[u8]) -> Option> { diff --git a/src/parser.rs b/src/parser.rs index 10c6228c9..9acc3ed9e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -44,7 +44,7 @@ use std::rc::Rc; #[cfg(target_has_atomic = "64")] use std::sync::atomic::AtomicU64; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; pub enum BlockData { Function { @@ -440,7 +440,7 @@ pub struct Parser { /// Global event blocks. pub global_event_blocks: AtomicU64, - pub blocking_wait: Mutex>, + pub blocking_wait: RefCell>, } impl Parser { @@ -458,7 +458,7 @@ pub fn new(variables: Rc, cancel_behavior: CancelBehavior) -> Parser { cancel_behavior, profile_items: RefCell::default(), global_event_blocks: AtomicU64::new(0), - blocking_wait: Mutex::new(Some(BlockingWait::Startup(Queried::NotYet))), + blocking_wait: RefCell::new(Some(BlockingWait::Startup(Queried::NotYet))), }; match open_dir(CStr::from_bytes_with_nul(b".\0").unwrap(), BEST_O_SEARCH) { diff --git a/src/reader.rs b/src/reader.rs index a4c048e80..d7f028456 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -23,6 +23,7 @@ #[cfg(not(target_has_atomic = "64"))] use portable_atomic::AtomicU64; use std::borrow::Cow; +use std::cell::RefMut; use std::cell::UnsafeCell; use std::cmp; use std::io::BufReader; @@ -1497,8 +1498,8 @@ pub fn combine_command_and_autosuggestion( } impl<'a> Reader<'a> { - pub(crate) fn blocking_wait(&self) -> MutexGuard> { - self.parser.blocking_wait.lock().unwrap() + pub(crate) fn blocking_wait(&self) -> RefMut<'_, Option> { + self.parser.blocking_wait.borrow_mut() } pub fn request_cursor_position(&mut self, out: &mut Outputter, wait: CursorPositionWait) { diff --git a/src/tests/input.rs b/src/tests/input.rs index 27860274c..e2287b616 100644 --- a/src/tests/input.rs +++ b/src/tests/input.rs @@ -1,12 +1,14 @@ use crate::env::EnvStack; use crate::input::{EventQueuePeeker, InputMappingSet, KeyNameStyle, DEFAULT_BIND_MODE}; -use crate::input_common::{CharEvent, InputData, InputEventQueuer, KeyEvent}; +use crate::input_common::{BlockingWait, CharEvent, InputData, InputEventQueuer, KeyEvent}; use crate::key::Key; use crate::wchar::prelude::*; +use std::cell::{RefCell, RefMut}; use std::rc::Rc; struct TestInputEventQueuer { input_data: InputData, + blocking_wait: RefCell>, } impl InputEventQueuer for TestInputEventQueuer { @@ -16,6 +18,9 @@ fn get_input_data(&self) -> &InputData { fn get_input_data_mut(&mut self) -> &mut InputData { &mut self.input_data } + fn blocking_wait(&self) -> RefMut<'_, Option> { + self.blocking_wait.borrow_mut() + } } #[test] @@ -23,6 +28,7 @@ fn test_input() { let vars = Rc::new(EnvStack::new()); let mut input = TestInputEventQueuer { input_data: InputData::new(i32::MAX), // value doesn't matter since we don't read from it + blocking_wait: RefCell::new(None), }; // Ensure sequences are order independent. Here we add two bindings where the first is a prefix // of the second, and then emit the second key list. The second binding should be invoked, not