Skip to content

Commit

Permalink
Implement parallel processing of multiple roots (fixes #24)
Browse files Browse the repository at this point in the history
  • Loading branch information
AMDmi3 committed Mar 6, 2024
1 parent 340f1f1 commit 8b595b2
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 4 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ harness = false
assert_cmd = "2.0.13"
clap = { version = "4.5.0", features = ["derive"] }
glob = "0.3.1"
num_cpus = "1.16.0"
pest = "2.7.7"
pest_derive = "2.7.7"
regex = { version = "1.10.3", default-features = false, features = ["std", "unicode-perl"] }
scoped_threadpool = "0.1.9"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
tempdir = "0.3.7"
Expand Down
26 changes: 22 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ use crate::formatters::json as format_json;
use crate::formatters::text as format_text;
use crate::r#match::MatchResult;
use clap::{Parser, ValueEnum};
use scoped_threadpool::Pool as ThreadPool;
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};

const CONFIG_FILE_NAME: &str = "omnilinter.conf";

Expand Down Expand Up @@ -60,6 +62,10 @@ struct Args {
#[arg(long, value_name = "EXITCODE")]
error_exitcode: Option<i32>,

/// If any matches are found, exit with given code
#[arg(short = 'j', long = "jobs", value_name = "COUNT")]
num_threads: Option<usize>,

/// Directories to operate on
#[arg(value_name = "TARGET_DIR")]
roots: Vec<PathBuf>,
Expand Down Expand Up @@ -105,11 +111,23 @@ fn main() {

let ruleset = config.ruleset.compile();

let mut result = MatchResult::new();
let result = Arc::new(Mutex::new(MatchResult::new()));

for root in &roots {
result.append(apply_ruleset(&ruleset, &root));
}
let num_threads = args.num_threads.unwrap_or_else(|| num_cpus::get());
let mut pool = ThreadPool::new(num_threads.try_into().unwrap_or(1));

pool.scoped(|scope| {
let ruleset = &ruleset;
for root in &roots {
let result = result.clone();
scope.execute(move || {
let res = apply_ruleset(&ruleset, &root);
result.lock().unwrap().append(res);
});
}
});

let result = Arc::into_inner(result).unwrap().into_inner().unwrap();

match args.output_format {
OutputFormat::ByRoot => {
Expand Down
5 changes: 5 additions & 0 deletions src/match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ impl<'a> MatchResult<'a> {
}
}

// Although MatchResult contains Rc<> in individual matches, it is safe
// to transfer across thread boundaries as a whole, because Rc's are only
// shared inside of it
unsafe impl Send for MatchResult<'_> {}

pub struct Match<'a> {
pub rule: &'a Rule,
pub root: &'a Path,
Expand Down

0 comments on commit 8b595b2

Please sign in to comment.