Backend: add AtomicBool to stop input thread

This commit is contained in:
Alexandre Bury 2018-05-20 10:55:13 -07:00
parent 0b6e5b6ad4
commit c8d39910ab
7 changed files with 27 additions and 14 deletions

View File

@ -305,9 +305,6 @@ impl backend::Backend for Backend {
terminal::print_xy(pos.x as i32, pos.y as i32, text); terminal::print_xy(pos.x as i32, pos.y as i32, text);
} }
fn start_input_thread(&mut self, _event_sink: chan::Sender<Event>) {
}
fn prepare_input(&mut self, event_sink: &chan::Sender<Event>, timeout: Duration) { fn prepare_input(&mut self, event_sink: &chan::Sender<Event>, timeout: Duration) {
// Wait for up to `timeout_ms`. // Wait for up to `timeout_ms`.
let start = Instant::now(); let start = Instant::now();

View File

@ -15,6 +15,8 @@ use std::fs::File;
use std::io; use std::io;
use std::io::{Write}; use std::io::{Write};
use std::thread; use std::thread;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use libc; use libc;
use chan; use chan;
@ -262,13 +264,13 @@ impl backend::Backend for Backend {
ncurses::has_colors() ncurses::has_colors()
} }
fn start_input_thread(&mut self, event_sink: chan::Sender<Event>) { fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, running: Arc<AtomicBool>) {
let mut parser = InputParser::new(event_sink); let mut parser = InputParser::new(event_sink);
// Start an input thread // Start an input thread
thread::spawn(move || { thread::spawn(move || {
// TODO: use an atomic boolean to stop the thread on finish // TODO: use an atomic boolean to stop the thread on finish
loop { while running.load(Ordering::Relaxed) {
parser.parse_next(); parser.parse_next();
} }
}); });

View File

@ -12,6 +12,7 @@ use vec::Vec2;
use std::sync::Arc; use std::sync::Arc;
use chan; use chan;
use std::thread; use std::thread;
use std::sync::atomic::{AtomicBool, Ordering};
pub struct Backend { pub struct Backend {
// Used // Used
@ -419,11 +420,11 @@ impl backend::Backend for Backend {
self.window.mvaddstr(pos.y as i32, pos.x as i32, text); self.window.mvaddstr(pos.y as i32, pos.x as i32, text);
} }
fn start_input_thread(&mut self, event_sink: chan::Sender<Event>) { fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, running: Arc<AtomicBool>) {
let mut input_parser = InputParser::new(event_sink, Arc::clone(&self.window)); let mut input_parser = InputParser::new(event_sink, Arc::clone(&self.window));
thread::spawn(move || { thread::spawn(move || {
loop { while running.load(Ordering::Relaxed) {
input_parser.parse_next(); input_parser.parse_next();
} }
}); });

View File

@ -32,9 +32,6 @@ impl backend::Backend for Backend {
(1, 1).into() (1, 1).into()
} }
fn start_input_thread(&mut self, _event_sink: chan::Sender<event::Event>) {
}
fn prepare_input(&mut self, event_sink: &chan::Sender<event::Event>, _timeout: Duration) { fn prepare_input(&mut self, event_sink: &chan::Sender<event::Event>, _timeout: Duration) {
event_sink.send(event::Event::Exit) event_sink.send(event::Event::Exit)
} }

View File

@ -15,6 +15,8 @@ use chan::Sender;
use vec::Vec2; use vec::Vec2;
use std::time::Duration; use std::time::Duration;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
pub mod dummy; pub mod dummy;
@ -32,7 +34,11 @@ pub trait Backend {
fn finish(&mut self); fn finish(&mut self);
/// Starts a thread to collect input and send it to the given channel. /// Starts a thread to collect input and send it to the given channel.
fn start_input_thread(&mut self, event_sink: Sender<event::Event>); fn start_input_thread(&mut self, event_sink: Sender<event::Event>, running: Arc<AtomicBool>) {
// Dummy implementation for some backends.
let _ = event_sink;
let _ = running;
}
/// Prepares the backend to collect input. /// Prepares the backend to collect input.
/// ///

View File

@ -24,6 +24,8 @@ use std::io::{Stdout, Write};
use std::thread; use std::thread;
use theme; use theme;
use vec::Vec2; use vec::Vec2;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
pub struct Backend { pub struct Backend {
terminal: AlternateScreen<MouseTerminal<RawTerminal<Stdout>>>, terminal: AlternateScreen<MouseTerminal<RawTerminal<Stdout>>>,
@ -265,10 +267,10 @@ impl backend::Backend for Backend {
); );
} }
fn start_input_thread(&mut self, event_sink: chan::Sender<Event>) { fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, running: Arc<AtomicBool>) {
let mut parser = InputParser::new(event_sink); let mut parser = InputParser::new(event_sink);
thread::spawn(move || { thread::spawn(move || {
loop { while running.load(Ordering::Relaxed) {
parser.parse_next(); parser.parse_next();
} }
}); });

View File

@ -7,6 +7,8 @@ use std::any::Any;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Duration; use std::time::Duration;
use std::path::Path; use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use theme; use theme;
use vec::Vec2; use vec::Vec2;
use view::{self, Finder, IntoBoxedView, Position, View}; use view::{self, Finder, IntoBoxedView, Position, View};
@ -42,6 +44,8 @@ pub struct Cursive {
event_source: chan::Receiver<Event>, event_source: chan::Receiver<Event>,
event_sink: chan::Sender<Event>, event_sink: chan::Sender<Event>,
input_running: Arc<AtomicBool>,
} }
/// Describes one of the possible interruptions we should handle. /// Describes one of the possible interruptions we should handle.
@ -124,7 +128,9 @@ impl Cursive {
let (cb_sink, cb_source) = chan::async(); let (cb_sink, cb_source) = chan::async();
let (event_sink, event_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 { Cursive {
fps: 0, fps: 0,
@ -139,6 +145,7 @@ impl Cursive {
cb_sink, cb_sink,
event_source, event_source,
event_sink, event_sink,
input_running,
backend: backend, backend: backend,
} }
} }
@ -768,6 +775,7 @@ impl Cursive {
impl Drop for Cursive { impl Drop for Cursive {
fn drop(&mut self) { fn drop(&mut self) {
self.input_running.store(false, Ordering::Relaxed);
self.backend.finish(); self.backend.finish();
} }
} }