diff --git a/src/backend/blt.rs b/src/backend/blt.rs index 4969ca7..7c44037 100644 --- a/src/backend/blt.rs +++ b/src/backend/blt.rs @@ -305,9 +305,6 @@ impl backend::Backend for Backend { terminal::print_xy(pos.x as i32, pos.y as i32, text); } - fn start_input_thread(&mut self, _event_sink: chan::Sender) { - } - fn prepare_input(&mut self, event_sink: &chan::Sender, timeout: Duration) { // Wait for up to `timeout_ms`. let start = Instant::now(); diff --git a/src/backend/curses/n.rs b/src/backend/curses/n.rs index da2908e..08effcf 100644 --- a/src/backend/curses/n.rs +++ b/src/backend/curses/n.rs @@ -15,6 +15,8 @@ use std::fs::File; use std::io; use std::io::{Write}; use std::thread; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use libc; use chan; @@ -262,13 +264,13 @@ impl backend::Backend for Backend { ncurses::has_colors() } - fn start_input_thread(&mut self, event_sink: chan::Sender) { + fn start_input_thread(&mut self, event_sink: chan::Sender, running: Arc) { let mut parser = InputParser::new(event_sink); // Start an input thread thread::spawn(move || { // TODO: use an atomic boolean to stop the thread on finish - loop { + while running.load(Ordering::Relaxed) { parser.parse_next(); } }); diff --git a/src/backend/curses/pan.rs b/src/backend/curses/pan.rs index 98b2495..c4fea49 100644 --- a/src/backend/curses/pan.rs +++ b/src/backend/curses/pan.rs @@ -12,6 +12,7 @@ use vec::Vec2; use std::sync::Arc; use chan; use std::thread; +use std::sync::atomic::{AtomicBool, Ordering}; pub struct Backend { // Used @@ -419,11 +420,11 @@ impl backend::Backend for Backend { self.window.mvaddstr(pos.y as i32, pos.x as i32, text); } - fn start_input_thread(&mut self, event_sink: chan::Sender) { + fn start_input_thread(&mut self, event_sink: chan::Sender, running: Arc) { let mut input_parser = InputParser::new(event_sink, Arc::clone(&self.window)); thread::spawn(move || { - loop { + while running.load(Ordering::Relaxed) { input_parser.parse_next(); } }); diff --git a/src/backend/dummy.rs b/src/backend/dummy.rs index ff45055..e22bb7f 100644 --- a/src/backend/dummy.rs +++ b/src/backend/dummy.rs @@ -32,9 +32,6 @@ impl backend::Backend for Backend { (1, 1).into() } - fn start_input_thread(&mut self, _event_sink: chan::Sender) { - } - fn prepare_input(&mut self, event_sink: &chan::Sender, _timeout: Duration) { event_sink.send(event::Event::Exit) } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 818b885..356a9dc 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -15,6 +15,8 @@ use chan::Sender; use vec::Vec2; use std::time::Duration; +use std::sync::Arc; +use std::sync::atomic::AtomicBool; pub mod dummy; @@ -32,7 +34,11 @@ pub trait Backend { fn finish(&mut self); /// Starts a thread to collect input and send it to the given channel. - fn start_input_thread(&mut self, event_sink: Sender); + fn start_input_thread(&mut self, event_sink: Sender, running: Arc) { + // Dummy implementation for some backends. + let _ = event_sink; + let _ = running; + } /// Prepares the backend to collect input. /// diff --git a/src/backend/termion.rs b/src/backend/termion.rs index 7a5aa7e..011c9e4 100644 --- a/src/backend/termion.rs +++ b/src/backend/termion.rs @@ -24,6 +24,8 @@ use std::io::{Stdout, Write}; use std::thread; use theme; use vec::Vec2; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; pub struct Backend { terminal: AlternateScreen>>, @@ -265,10 +267,10 @@ impl backend::Backend for Backend { ); } - fn start_input_thread(&mut self, event_sink: chan::Sender) { + fn start_input_thread(&mut self, event_sink: chan::Sender, running: Arc) { let mut parser = InputParser::new(event_sink); thread::spawn(move || { - loop { + while running.load(Ordering::Relaxed) { parser.parse_next(); } }); diff --git a/src/cursive.rs b/src/cursive.rs index b1a9c5f..4a3d30a 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -7,6 +7,8 @@ use std::any::Any; use std::collections::HashMap; use std::time::Duration; use std::path::Path; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use theme; use vec::Vec2; use view::{self, Finder, IntoBoxedView, Position, View}; @@ -42,6 +44,8 @@ pub struct Cursive { event_source: chan::Receiver, event_sink: chan::Sender, + + input_running: Arc, } /// Describes one of the possible interruptions we should handle. @@ -124,7 +128,9 @@ impl Cursive { let (cb_sink, cb_source) = chan::async(); let (event_sink, event_source) = chan::async(); - backend.start_input_thread(event_sink.clone()); + let input_running = Arc::new(AtomicBool::new(true)); + + backend.start_input_thread(event_sink.clone(), input_running.clone()); Cursive { fps: 0, @@ -139,6 +145,7 @@ impl Cursive { cb_sink, event_source, event_sink, + input_running, backend: backend, } } @@ -768,6 +775,7 @@ impl Cursive { impl Drop for Cursive { fn drop(&mut self) { + self.input_running.store(false, Ordering::Relaxed); self.backend.finish(); } }