Do not consume input before exit

This commit is contained in:
Alexandre Bury 2018-06-08 19:48:01 -07:00
parent 70cddae454
commit 3f5b37951b
5 changed files with 34 additions and 24 deletions

View File

@ -15,8 +15,6 @@ 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;
@ -267,15 +265,19 @@ impl backend::Backend for Backend {
ncurses::has_colors() ncurses::has_colors()
} }
fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, running: Arc<AtomicBool>) { fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, stops: chan::Receiver<bool>) {
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 loop {
while running.load(Ordering::Relaxed) {
// This sends events to the event sender. // This sends events to the event sender.
parser.parse_next(); parser.parse_next();
if stops.recv() != Some(false) {
// If the channel was closed or if `true` was sent, abort.
break;
}
} }
}); });
} }

View File

@ -12,7 +12,6 @@ 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
@ -420,12 +419,17 @@ 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>, running: Arc<AtomicBool>) { fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, stops: chan::Receiver<bool>) {
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 || {
while running.load(Ordering::Relaxed) { loop {
input_parser.parse_next(); input_parser.parse_next();
if stops.recv() != Some(false) {
// If the channel was closed or if `true` was sent, abort.
break;
}
} }
}); });

View File

@ -10,13 +10,11 @@
use event; use event;
use theme; use theme;
use chan::Sender; use chan::{Receiver, 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;
@ -34,7 +32,7 @@ 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>, running: Arc<AtomicBool>) { fn start_input_thread(&mut self, event_sink: Sender<event::Event>, running: Receiver<bool>) {
// Dummy implementation for some backends. // Dummy implementation for some backends.
let _ = event_sink; let _ = event_sink;
let _ = running; let _ = running;

View File

@ -24,8 +24,6 @@ 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>>>,
@ -267,11 +265,17 @@ impl backend::Backend for Backend {
); );
} }
fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, running: Arc<AtomicBool>) { fn start_input_thread(&mut self, event_sink: chan::Sender<Event>, stops: chan::Receiver<bool>) {
let mut parser = InputParser::new(event_sink); let mut parser = InputParser::new(event_sink);
thread::spawn(move || { thread::spawn(move || {
while running.load(Ordering::Relaxed) { loop {
// This sends events to the event sender.
parser.parse_next(); parser.parse_next();
if stops.recv() != Some(false) {
// If the channel was closed or if `true` was sent, abort.
break;
}
} }
}); });
} }

View File

@ -7,8 +7,6 @@ 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};
@ -45,7 +43,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>, // Sends true or false after each event.
stop_sink: chan::Sender<bool>,
} }
/// Describes one of the possible interruptions we should handle. /// Describes one of the possible interruptions we should handle.
@ -128,9 +127,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();
let input_running = Arc::new(AtomicBool::new(true)); let (stop_sink, stop_source) = chan::async();
backend.start_input_thread(event_sink.clone(), input_running.clone()); backend.start_input_thread(event_sink.clone(), stop_source);
Cursive { Cursive {
fps: 0, fps: 0,
@ -145,8 +144,8 @@ impl Cursive {
cb_sink, cb_sink,
event_source, event_source,
event_sink, event_sink,
input_running, backend,
backend: backend, stop_sink,
} }
} }
@ -758,6 +757,10 @@ impl Cursive {
EventResult::Consumed(Some(cb)) => cb(self), EventResult::Consumed(Some(cb)) => cb(self),
} }
} }
// Ok, we processed the event.
// Now tell the backend whether he sould keep receiving.
self.stop_sink.send(!self.running);
}, },
Interruption::Callback(cb) => { Interruption::Callback(cb) => {
cb.call_box(self); cb.call_box(self);
@ -775,7 +778,6 @@ 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();
} }
} }