diff options
-rw-r--r-- | Cargo.lock | 6 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/main.rs | 122 |
3 files changed, 98 insertions, 32 deletions
@@ -7,7 +7,7 @@ dependencies = [ "errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "font 0.1.0", "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c)", + "glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403)", "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "notify 2.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -285,7 +285,7 @@ dependencies = [ [[package]] name = "glutin" version = "0.6.1" -source = "git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c#45092a8e2f6706a7b2c613ff212341754e346c9c" +source = "git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403#16ed800f68022a37203434bd3b542ff5400c1403" dependencies = [ "android_glue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -906,7 +906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "65256ec4dc2592e6f05bfc1ca3b956a4e0698aa90b1dff1f5687d55a5a3fd59a" "checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55" "checksum gleam 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "13a363b2a5264b600e530db2f14b3c487098e6dee0655f2810ea779385cbac5a" -"checksum glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c)" = "<none>" +"checksum glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403)" = "<none>" "checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c" "checksum inotify 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8458c07bdbdaf309c80e2c3304d14c3db64e7465d4f07cf589ccb83fd0ff31a" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" @@ -13,7 +13,7 @@ notify = "2.6" bitflags = "*" font = { path = "./font" } errno = "0.1.6" -parking_lot = "0.3.1" +parking_lot = { version = "0.3.1", features = ["nightly"] } serde = "0.8" serde_yaml = "0.4" serde_macros = "0.8" diff --git a/src/main.rs b/src/main.rs index 29201adf..5c1bca68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,21 +52,45 @@ mod io; mod sync; use std::sync::{mpsc, Arc}; +use std::sync::atomic::{AtomicBool, Ordering}; -use sync::PriorityMutex; +use parking_lot::{Condvar, Mutex}; use config::Config; +use io::{Utf8Chars, Utf8CharsError}; use meter::Meter; use renderer::{QuadRenderer, GlyphCache}; +use sync::PriorityMutex; use term::Term; use tty::process_should_exit; use util::thread; -use io::{Utf8Chars, Utf8CharsError}; - /// Channel used by resize handling on mac static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None; +struct Waiter { + mutex: Mutex<bool>, + cond: Condvar, +} + +impl Waiter { + pub fn new() -> Waiter { + Waiter { + mutex: Mutex::new(false), + cond: Condvar::new(), + } + } + + pub fn notify(&self) { + self.cond.notify_one(); + } + + pub fn wait(&self) { + let mut guard = self.mutex.lock(); + self.cond.wait(&mut guard); + } +} + /// Resize handling for Mac fn window_resize_handler(width: u32, height: u32) { unsafe { @@ -126,6 +150,9 @@ fn main() { let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr); + let waiter = Arc::new(Waiter::new()); + let dirty = Arc::new(AtomicBool::new(false)); + // Create renderer let mut renderer = QuadRenderer::new(width, height); @@ -163,7 +190,11 @@ fn main() { let terminal = Arc::new(PriorityMutex::new(terminal)); - let pty_reader_thread = spawn_pty_reader(terminal.clone(), reader); + let pty_reader_thread = spawn_pty_reader(terminal.clone(), + reader, + waiter.clone(), + dirty.clone(), + window.create_window_proxy()); let window = Arc::new(window); @@ -173,11 +204,15 @@ fn main() { renderer, glyph_cache, render_timer, - rx); + rx, + waiter.clone(), + dirty); handle_window_events(&mut writer, terminal, window); pty_reader_thread.join().ok(); + + waiter.notify(); render_thread.join().ok(); println!("Goodbye"); } @@ -219,12 +254,23 @@ fn handle_window_events<W>(writer: &mut W, &mut input::WriteNotifier(writer), *terminal.mode()) }, + glutin::Event::Awakened => { + if process_should_exit() { + println!("input thread exitting"); + break; + } + } _ => (), } + } } -fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::thread::JoinHandle<()> +fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, + mut pty: R, + waiter: Arc<Waiter>, + dirty: Arc<AtomicBool>, + proxy: ::glutin::WindowProxy) -> std::thread::JoinHandle<()> where R: std::io::Read + Send + 'static, { thread::spawn_named("pty reader", move || { @@ -233,40 +279,51 @@ fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::t let mut pty_parser = ansi::Parser::new(); loop { - let got = pty.read(&mut buf[start..]).expect("pty fd active"); - let mut remain = 0; + 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(); - 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 `start` is nonzero, then actual bytes in buffer is > `got` by `start` bytes. + let end = start + got; + { + let mut terminal = terminal.lock_low(); + 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), + } + } } } - } - // Move any leftover bytes to front of buffer - for i in 0..remain { - buf[i] = buf[end - (remain - i)]; + dirty.store(true, Ordering::Release); + waiter.notify(); + + // Move any leftover bytes to front of buffer + for i in 0..remain { + buf[i] = buf[end - (remain - i)]; + } + start = remain; + } else { + proxy.wakeup_event_loop(); + break; } - start = remain; } }) } fn spawn_renderer(window: Arc<glutin::Window>, - terminal: Arc<PriorityMutex<Term>>, + terminal_mutex: Arc<PriorityMutex<Term>>, mut renderer: QuadRenderer, mut glyph_cache: GlyphCache, render_timer: bool, - rx: mpsc::Receiver<(u32, u32)>) -> std::thread::JoinHandle<()> { + rx: mpsc::Receiver<(u32, u32)>, + waiter: Arc<Waiter>, + dirty: Arc<AtomicBool>) -> std::thread::JoinHandle<()> { thread::spawn_named("render", move || { unsafe { let _ = window.make_current(); @@ -277,7 +334,15 @@ fn spawn_renderer(window: Arc<glutin::Window>, // Scope ensures terminal lock isn't held when calling swap_buffers { // Acquire term lock - let mut terminal = terminal.lock_high(); + let mut terminal = terminal_mutex.lock_high(); + + if !dirty.load(Ordering::Acquire) { + drop(terminal); + waiter.wait(); + terminal = terminal_mutex.lock_high(); + } + + dirty.store(false, Ordering::Release); // Resize events new_size and are handled outside the poll_events // iterator. This has the effect of coalescing multiple resize @@ -328,6 +393,7 @@ fn spawn_renderer(window: Arc<glutin::Window>, if process_should_exit() { break; + } else { } } }) |