Address feedback for removing buffering when running on a single thread

This commit is contained in:
Thayne McCombs 2021-08-09 01:02:30 -06:00
parent fcaebd2295
commit bf37c27a38
4 changed files with 35 additions and 25 deletions

View File

@ -7,18 +7,20 @@ use crate::error::print_error;
use crate::exit_codes::ExitCode; use crate::exit_codes::ExitCode;
/// Executes a command. /// Executes a command.
pub fn execute_command(mut cmd: Command, out_perm: &Mutex<()>, is_multithread: bool) -> ExitCode { pub fn execute_command(
let output; mut cmd: Command,
out_perm: &Mutex<()>,
enable_output_buffering: bool,
) -> ExitCode {
// Spawn the supplied command. // Spawn the supplied command.
if is_multithread { let output = if enable_output_buffering {
output = cmd.output(); cmd.output()
} else { } else {
// If running on only one thread, don't buffer output // If running on only one thread, don't buffer output
// Allows for viewing and interacting with intermediate command output // Allows for viewing and interacting with intermediate command output
let child = cmd.spawn().expect("Failed to execute command"); cmd.spawn().and_then(|c| c.wait_with_output())
output = child.wait_with_output(); };
}
// Then wait for the command to exit, if it was spawned. // Then wait for the command to exit, if it was spawned.
match output { match output {
Ok(output) => { Ok(output) => {

View File

@ -16,7 +16,7 @@ pub fn job(
cmd: Arc<CommandTemplate>, cmd: Arc<CommandTemplate>,
out_perm: Arc<Mutex<()>>, out_perm: Arc<Mutex<()>>,
show_filesystem_errors: bool, show_filesystem_errors: bool,
is_multithread: bool, buffer_output: bool,
) -> ExitCode { ) -> ExitCode {
let mut results: Vec<ExitCode> = Vec::new(); let mut results: Vec<ExitCode> = Vec::new();
loop { loop {
@ -35,11 +35,11 @@ pub fn job(
} }
Err(_) => break, Err(_) => break,
}; };
// Drop the lock so that other threads can read from the receiver. // Drop the lock so that other threads can read from the receiver.
drop(lock); drop(lock);
// Generate a command, execute it and store its exit code. // Generate a command, execute it and store its exit code.
results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm), is_multithread)) results.push(cmd.generate_and_execute(&value, Arc::clone(&out_perm), buffer_output))
} }
// Returns error in case of any error. // Returns error in case of any error.
merge_exitcodes(&results) merge_exitcodes(&results)
@ -49,7 +49,7 @@ pub fn batch(
rx: Receiver<WorkerResult>, rx: Receiver<WorkerResult>,
cmd: &CommandTemplate, cmd: &CommandTemplate,
show_filesystem_errors: bool, show_filesystem_errors: bool,
is_multithread: bool, buffer_output: bool,
) -> ExitCode { ) -> ExitCode {
let paths = rx.iter().filter_map(|value| match value { let paths = rx.iter().filter_map(|value| match value {
WorkerResult::Entry(val) => Some(val), WorkerResult::Entry(val) => Some(val),
@ -60,5 +60,5 @@ pub fn batch(
None None
} }
}); });
cmd.generate_and_execute_batch(paths, is_multithread) cmd.generate_and_execute_batch(paths, buffer_output)
} }

View File

@ -139,7 +139,12 @@ impl CommandTemplate {
/// ///
/// Using the internal `args` field, and a supplied `input` variable, a `Command` will be /// Using the internal `args` field, and a supplied `input` variable, a `Command` will be
/// build. Once all arguments have been processed, the command is executed. /// build. Once all arguments have been processed, the command is executed.
pub fn generate_and_execute(&self, input: &Path, out_perm: Arc<Mutex<()>>, is_multithread: bool) -> ExitCode { pub fn generate_and_execute(
&self,
input: &Path,
out_perm: Arc<Mutex<()>>,
buffer_output: bool,
) -> ExitCode {
let input = strip_current_dir(input); let input = strip_current_dir(input);
let mut cmd = Command::new(self.args[0].generate(&input, self.path_separator.as_deref())); let mut cmd = Command::new(self.args[0].generate(&input, self.path_separator.as_deref()));
@ -147,14 +152,14 @@ impl CommandTemplate {
cmd.arg(arg.generate(&input, self.path_separator.as_deref())); cmd.arg(arg.generate(&input, self.path_separator.as_deref()));
} }
execute_command(cmd, &out_perm, is_multithread) execute_command(cmd, &out_perm, buffer_output)
} }
pub fn in_batch_mode(&self) -> bool { pub fn in_batch_mode(&self) -> bool {
self.mode == ExecutionMode::Batch self.mode == ExecutionMode::Batch
} }
pub fn generate_and_execute_batch<I>(&self, paths: I, is_multithread: bool) -> ExitCode pub fn generate_and_execute_batch<I>(&self, paths: I, buffer_output: bool) -> ExitCode
where where
I: Iterator<Item = PathBuf>, I: Iterator<Item = PathBuf>,
{ {
@ -182,7 +187,7 @@ impl CommandTemplate {
} }
if has_path { if has_path {
execute_command(cmd, &Mutex::new(()), is_multithread) execute_command(cmd, &Mutex::new(()), buffer_output)
} else { } else {
ExitCode::Success ExitCode::Success
} }

View File

@ -171,16 +171,12 @@ fn spawn_receiver(
let show_filesystem_errors = config.show_filesystem_errors; let show_filesystem_errors = config.show_filesystem_errors;
let threads = config.threads; let threads = config.threads;
// This will be used to check if output should be buffered when only running a single thread // This will be used to check if output should be buffered when only running a single thread
let is_multithread: bool = if threads > 1 { let enable_output_buffering: bool = threads > 1;
true
} else {
false
};
thread::spawn(move || { thread::spawn(move || {
// This will be set to `Some` if the `--exec` argument was supplied. // This will be set to `Some` if the `--exec` argument was supplied.
if let Some(ref cmd) = config.command { if let Some(ref cmd) = config.command {
if cmd.in_batch_mode() { if cmd.in_batch_mode() {
exec::batch(rx, cmd, show_filesystem_errors, is_multithread) exec::batch(rx, cmd, show_filesystem_errors, enable_output_buffering)
} else { } else {
let shared_rx = Arc::new(Mutex::new(rx)); let shared_rx = Arc::new(Mutex::new(rx));
@ -194,8 +190,15 @@ fn spawn_receiver(
let out_perm = Arc::clone(&out_perm); let out_perm = Arc::clone(&out_perm);
// Spawn a job thread that will listen for and execute inputs. // Spawn a job thread that will listen for and execute inputs.
let handle = let handle = thread::spawn(move || {
thread::spawn(move || exec::job(rx, cmd, out_perm, show_filesystem_errors, is_multithread)); exec::job(
rx,
cmd,
out_perm,
show_filesystem_errors,
enable_output_buffering,
)
});
// Push the handle of the spawned thread into the vector for later joining. // Push the handle of the spawned thread into the vector for later joining.
handles.push(handle); handles.push(handle);