mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-12-28 02:35:03 +00:00
Merge pull request #45 from byteprelude/master
making Exa.load() stat files in parallel
This commit is contained in:
commit
d2df70ef41
81
src/main.rs
81
src/main.rs
@ -18,6 +18,9 @@ extern crate git2;
|
|||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::old_io::{fs, FileType};
|
use std::old_io::{fs, FileType};
|
||||||
|
use std::os::num_cpus;
|
||||||
|
use std::sync::mpsc::{channel, sync_channel};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
use dir::Dir;
|
use dir::Dir;
|
||||||
use file::File;
|
use file::File;
|
||||||
@ -52,31 +55,75 @@ impl<'a> Exa<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load<T>(&mut self, iter: T) where T: Iterator<Item = &'a String> {
|
fn load(&mut self, files: &[String]) {
|
||||||
// Separate the user-supplied paths into directories and files.
|
// Separate the user-supplied paths into directories and files.
|
||||||
// Files are shown first, and then each directory is expanded
|
// Files are shown first, and then each directory is expanded
|
||||||
// and listed second.
|
// and listed second.
|
||||||
for file in iter {
|
|
||||||
let path = Path::new(file);
|
let is_tree = self.options.dir_action.is_tree();
|
||||||
match fs::stat(&path) {
|
let total_files = files.len();
|
||||||
Ok(stat) => {
|
|
||||||
if stat.kind == FileType::Directory {
|
// Denotes the maxinum number of concurrent threads
|
||||||
if self.options.dir_action.is_tree() {
|
let (thread_capacity_tx, thread_capacity_rs) = sync_channel(8 * num_cpus());
|
||||||
self.files.push(File::with_stat(stat, &path, None, true));
|
|
||||||
|
// Communication between consumer thread and producer threads
|
||||||
|
enum StatResult<'a> {
|
||||||
|
File(File<'a>),
|
||||||
|
Path(Path),
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
let (results_tx, results_rx) = channel();
|
||||||
|
|
||||||
|
// Spawn consumer thread
|
||||||
|
let _consumer = thread::scoped(move || {
|
||||||
|
for _ in 0..total_files {
|
||||||
|
|
||||||
|
// Make room for more producer threads
|
||||||
|
let _ = thread_capacity_rs.recv();
|
||||||
|
|
||||||
|
// Receive a producer's result
|
||||||
|
match results_rx.recv() {
|
||||||
|
Ok(result) => match result {
|
||||||
|
StatResult::File(file) => self.files.push(file),
|
||||||
|
StatResult::Path(path) => self.dirs.push(path),
|
||||||
|
StatResult::Error => ()
|
||||||
|
},
|
||||||
|
Err(_) => unreachable!()
|
||||||
|
}
|
||||||
|
self.count += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for file in files.iter() {
|
||||||
|
let file = file.clone();
|
||||||
|
let results_tx = results_tx.clone();
|
||||||
|
|
||||||
|
// Block until there is room for another thread
|
||||||
|
let _ = thread_capacity_tx.send(());
|
||||||
|
|
||||||
|
// Spawn producer thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
let path = Path::new(file.clone());
|
||||||
|
let _ = results_tx.send(match fs::stat(&path) {
|
||||||
|
Ok(stat) => {
|
||||||
|
if stat.kind != FileType::Directory {
|
||||||
|
StatResult::File(File::with_stat(stat, &path, None, false))
|
||||||
|
}
|
||||||
|
else if is_tree {
|
||||||
|
StatResult::File(File::with_stat(stat, &path, None, true))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.dirs.push(path);
|
StatResult::Path(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
Err(e) => {
|
||||||
self.files.push(File::with_stat(stat, &path, None, false));
|
println!("{}: {}", file, e);
|
||||||
|
StatResult::Error
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
Err(e) => println!("{}: {}", file, e),
|
});
|
||||||
}
|
|
||||||
|
|
||||||
self.count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_files(&self) {
|
fn print_files(&self) {
|
||||||
@ -154,7 +201,7 @@ fn main() {
|
|||||||
match Options::getopts(args.tail()) {
|
match Options::getopts(args.tail()) {
|
||||||
Ok((options, paths)) => {
|
Ok((options, paths)) => {
|
||||||
let mut exa = Exa::new(options);
|
let mut exa = Exa::new(options);
|
||||||
exa.load(paths.iter());
|
exa.load(&paths);
|
||||||
exa.print_files();
|
exa.print_files();
|
||||||
exa.print_dirs();
|
exa.print_dirs();
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user