Improve runner API

This commit is contained in:
Matt Green 2016-10-25 05:15:08 -04:00
parent 918fd668a5
commit 3d3915844a
2 changed files with 59 additions and 29 deletions

View File

@ -118,17 +118,17 @@ fn main() {
} }
let cmd = args.cmd; let cmd = args.cmd;
let mut runner = Runner::new(); let (mut runner, child_rx) = Runner::new();
let mut child_process = None;
if args.run_initially { if args.run_initially {
if args.clear_screen { if args.clear_screen {
runner.clear_screen(); runner.clear_screen();
} }
runner.run_command(&cmd, vec![]); child_process = runner.run_command(&cmd, vec![]);
} }
let mut child_wait_rx = None;
while !interrupt_handler::interrupt_requested() { while !interrupt_handler::interrupt_requested() {
match wait(&rx, &interrupt_rx, &filter) { match wait(&rx, &interrupt_rx, &filter) {
Some(paths) => { Some(paths) => {
@ -136,12 +136,13 @@ fn main() {
.map(|p| p.to_str().unwrap()) .map(|p| p.to_str().unwrap())
.collect(); .collect();
if let Some(mut child) = child_process {
if args.restart { if args.restart {
runner.kill(); debug!("Killing child process");
child.kill();
} }
debug!("Waiting for process to exit..."); debug!("Waiting for process to exit...");
if let Some(child_rx) = child_wait_rx {
select! { select! {
_ = child_rx.recv() => {}, _ = child_rx.recv() => {},
_ = interrupt_rx.recv() => break _ = interrupt_rx.recv() => break
@ -152,7 +153,7 @@ fn main() {
runner.clear_screen(); runner.clear_screen();
} }
child_wait_rx = Some(runner.run_command(&cmd, updated)); child_process = runner.run_command(&cmd, updated);
} }
None => { None => {
// interrupted // interrupted

View File

@ -1,19 +1,21 @@
use std::process::Command; use std::process::Command;
use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::{channel, Receiver, Sender};
use threadpool::ThreadPool; use threadpool::ThreadPool;
pub struct Runner { pub struct Runner {
pool: ThreadPool, pool: ThreadPool,
process: Option<platform::Process>, tx: Sender<()>,
} }
impl Runner { impl Runner {
pub fn new() -> Runner { pub fn new() -> (Runner, Receiver<()>) {
Runner { let (tx, rx) = channel();
(Runner {
pool: ThreadPool::new(1), pool: ThreadPool::new(1),
process: None, tx: tx,
} },
rx)
} }
#[cfg(target_family = "windows")] #[cfg(target_family = "windows")]
@ -26,30 +28,53 @@ impl Runner {
let _ = Command::new("clear").status(); let _ = Command::new("clear").status();
} }
pub fn kill(&mut self) { pub fn run_command(&mut self,
if let Some(ref mut process) = self.process { cmd: &str,
process.kill(); updated_paths: Vec<&str>)
} -> Option<Process> {
} let child = Process::new(cmd, updated_paths);
pub fn run_command(&mut self, cmd: &str, updated_paths: Vec<&str>) -> Receiver<()> { if let Some(ref process) = child {
let (tx, rx) = channel(); let tx = self.tx.clone();
let mut p = process.as_platform_process();
if let Some(mut process) = platform::Process::new(cmd, updated_paths) {
self.process = Some(process.clone());
self.pool.execute(move || { self.pool.execute(move || {
process.wait(); p.wait();
let _ = tx.send(()); let _ = tx.send(());
}); });
} }
rx child
} }
} }
impl Drop for Runner { pub struct Process {
process: platform::Process
}
impl Process {
pub fn new(cmd: &str, updated_paths: Vec<&str>) -> Option<Process> {
platform::Process::new(cmd, updated_paths).and_then(|p| {
Some(Process { process: p })
})
}
fn as_platform_process(&self) -> platform::Process {
self.process.clone()
}
pub fn kill(&mut self) {
self.process.kill();
}
#[allow(dead_code)]
pub fn wait(&mut self) {
self.process.wait();
}
}
impl Drop for Process {
fn drop(&mut self) { fn drop(&mut self) {
self.kill(); self.kill();
} }
@ -85,7 +110,11 @@ mod platform {
.ok(); .ok();
match c { match c {
Some(process) => Some(Process { child_pid: process.id() as i32 }), Some(process) => {
Some(Process {
child_pid: process.id() as i32,
})
}
None => None, None => None,
} }
} }