summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-08-31 21:16:17 -0700
committerJoe Wilm <joe@jwilm.com>2016-08-31 21:16:17 -0700
commit0517f376be3054ab736006dcfc24b404dcd8626c (patch)
tree6c979c71585544f96c8c27023a7dd14d9d5018af
parent0a94ccfccadfb4d560daa0c15763edb9be4c3040 (diff)
downloadalacritty-0517f376be3054ab736006dcfc24b404dcd8626c.tar.gz
alacritty-0517f376be3054ab736006dcfc24b404dcd8626c.zip
Eliminate extra renders
Currently has a bug where screen is blank at startup. That aside, Alacritty uses basically 0 CPU now. The input thread is still separate from the render thread, but, given the ability to wake the event loop, it may be possible to merge them again. I'm not sure if that's actually desirable. Performance is seemingly unchanged.
-rw-r--r--Cargo.lock6
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs122
3 files changed, 98 insertions, 32 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3c9f89f6..7b630691 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index d556a26c..9e8f8b81 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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 {
}
}
})