diff options
author | Joe Wilm <joe@jwilm.com> | 2016-09-18 11:17:44 -0700 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-09-18 11:26:00 -0700 |
commit | 13d2d66b6bf213726ec864b84db471f2eec9f742 (patch) | |
tree | 4b2b1bbe9173bfd250d5b840e5e85dc76c9ad424 /src/main.rs | |
parent | 0d6d0dc0af028ead15c188db5d5f30e39fe0e3e7 (diff) | |
download | r-alacritty-13d2d66b6bf213726ec864b84db471f2eec9f742.tar.gz r-alacritty-13d2d66b6bf213726ec864b84db471f2eec9f742.tar.bz2 r-alacritty-13d2d66b6bf213726ec864b84db471f2eec9f742.zip |
Rewrite ansi parser using vte crate
Using the vte crate allows removal of the ansi parser state machine and
enables us to just be concerned with actions described in the protocol.
In addition to making alacritty simpler, this also improves correctness
and performance.
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 89 |
1 files changed, 52 insertions, 37 deletions
diff --git a/src/main.rs b/src/main.rs index c0685204..a803d05c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ extern crate notify; extern crate parking_lot; extern crate serde; extern crate serde_yaml; +extern crate vte; #[macro_use] extern crate bitflags; @@ -49,7 +50,6 @@ mod tty; pub mod ansi; mod term; mod util; -mod io; mod sync; use std::sync::{mpsc, Arc}; @@ -58,7 +58,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use parking_lot::{Condvar, Mutex, MutexGuard}; use config::Config; -use io::{Utf8Chars, Utf8CharsError}; use meter::Meter; use renderer::{QuadRenderer, GlyphCache}; use sync::PriorityMutex; @@ -69,6 +68,24 @@ use util::thread; /// Channel used by resize handling on mac static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None; +#[derive(Clone)] +struct Flag(Arc<AtomicBool>); +impl Flag { + pub fn new(initial_value: bool) -> Flag { + Flag(Arc::new(AtomicBool::new(initial_value))) + } + + #[inline] + pub fn get(&self) -> bool { + self.0.load(Ordering::Acquire) + } + + #[inline] + pub fn set(&self, value: bool) { + self.0.store(value, Ordering::Release) + } +} + /// Resize handling for Mac fn window_resize_handler(width: u32, height: u32) { unsafe { @@ -163,18 +180,27 @@ fn main() { resize_sender = Some(tx.clone()); } + let signal_flag = Flag::new(false); + let terminal = Arc::new(PriorityMutex::new(terminal)); let window = Arc::new(window); - let pty_reader = PtyReader::spawn(terminal.clone(), reader, window.create_window_proxy()); + let pty_reader = PtyReader::spawn( + terminal.clone(), + reader, + window.create_window_proxy(), + signal_flag.clone() + ); // Wraps a renderer and gives simple draw() api. - let mut display = Display::new(window.clone(), - terminal.clone(), - renderer, - glyph_cache, - render_timer, - rx); + let mut display = Display::new( + window.clone(), + terminal.clone(), + renderer, + glyph_cache, + render_timer, + rx + ); // Event processor let mut processor = event::Processor::new(&mut writer, terminal.clone(), tx); @@ -184,6 +210,8 @@ fn main() { // Wait for something to happen processor.process_events(&window); + signal_flag.set(false); + // Maybe draw the terminal let terminal = terminal.lock_high(); if terminal.dirty { @@ -205,45 +233,32 @@ struct PtyReader; impl PtyReader { pub fn spawn<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R, - proxy: ::glutin::WindowProxy) + proxy: ::glutin::WindowProxy, + signal_flag: Flag) -> std::thread::JoinHandle<()> where R: std::io::Read + Send + 'static { thread::spawn_named("pty reader", move || { let mut buf = [0u8; 4096]; - let mut start = 0; - let mut pty_parser = ansi::Parser::new(); + let mut pty_parser = ansi::Processor::new(); loop { - if let Ok(got) = pty.read(&mut buf[start..]) { - let mut remain = 0; - - // if `start` is nonzero, then actual bytes in buffer is > `got` by `start` bytes. - let end = start + got; - { - let mut terminal = terminal.lock_low(); - terminal.dirty = true; - for c in Utf8Chars::new(&buf[..end]) { - match c { - Ok(c) => pty_parser.advance(&mut *terminal, c), - Err(err) => match err { - Utf8CharsError::IncompleteUtf8(unused) => { - remain = unused; - break; - }, - _ => panic!("{}", err), - } - } - } + if let Ok(got) = pty.read(&mut buf[..]) { + let mut terminal = terminal.lock_high(); + + for byte in &buf[..got] { + pty_parser.advance(&mut *terminal, *byte); } - proxy.wakeup_event_loop(); + terminal.dirty = true; - // Move any leftover bytes to front of buffer - for i in 0..remain { - buf[i] = buf[end - (remain - i)]; + // Only wake up the event loop if it hasn't already been signaled. This is a + // really important optimization because waking up the event loop redundantly + // burns *a lot* of cycles. + if !signal_flag.get() { + proxy.wakeup_event_loop(); + signal_flag.set(true); } - start = remain; } else { break; } |