Skip to content

Commit

Permalink
walk: Remove a few unnecessary Arcs
Browse files Browse the repository at this point in the history
  • Loading branch information
tavianator committed Nov 1, 2023
1 parent 987ab7f commit 77f68d3
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn run() -> Result<ExitCode> {
.map(|pat| build_regex(pat, &config))
.collect::<Result<Vec<Regex>>>()?;

walk::scan(&search_paths, Arc::new(regexps), Arc::new(config))
walk::scan(&search_paths, regexps, config)
}

#[cfg(feature = "completions")]
Expand Down
78 changes: 35 additions & 43 deletions src/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ const MAX_BUFFER_LENGTH: usize = 1000;
const DEFAULT_MAX_BUFFER_TIME: Duration = Duration::from_millis(100);

/// Wrapper for the receiver thread's buffering behavior.
struct ReceiverBuffer<W> {
struct ReceiverBuffer<'a, W> {
/// The configuration.
config: Arc<Config>,
config: &'a Config,
/// For shutting down the senders.
quit_flag: Arc<AtomicBool>,
quit_flag: &'a AtomicBool,
/// The ^C notifier.
interrupt_flag: Arc<AtomicBool>,
interrupt_flag: &'a AtomicBool,
/// Receiver for worker results.
rx: Receiver<WorkerResult>,
/// Standard output.
Expand All @@ -70,15 +70,12 @@ struct ReceiverBuffer<W> {
num_results: usize,
}

impl<W: Write> ReceiverBuffer<W> {
impl<'a, W: Write> ReceiverBuffer<'a, W> {
/// Create a new receiver buffer.
fn new(
config: Arc<Config>,
quit_flag: Arc<AtomicBool>,
interrupt_flag: Arc<AtomicBool>,
rx: Receiver<WorkerResult>,
stdout: W,
) -> Self {
fn new(state: &'a WorkerState, rx: Receiver<WorkerResult>, stdout: W) -> Self {
let config = &state.config;
let quit_flag = state.quit_flag.as_ref();
let interrupt_flag = state.interrupt_flag.as_ref();
let max_buffer_time = config.max_buffer_time.unwrap_or(DEFAULT_MAX_BUFFER_TIME);
let deadline = Instant::now() + max_buffer_time;

Expand Down Expand Up @@ -214,37 +211,32 @@ impl<W: Write> ReceiverBuffer<W> {

/// State shared by the sender and receiver threads.
struct WorkerState {
/// The paths to scan.
paths: Vec<PathBuf>,
/// The search patterns.
patterns: Arc<Vec<Regex>>,
patterns: Vec<Regex>,
/// The command line configuration.
config: Arc<Config>,
config: Config,
/// Flag for cleanly shutting down the parallel walk
quit_flag: Arc<AtomicBool>,
/// Flag specifically for quitting due to ^C
interrupt_flag: Arc<AtomicBool>,
}

impl WorkerState {
fn new(paths: &[PathBuf], patterns: Arc<Vec<Regex>>, config: Arc<Config>) -> Self {
let paths = paths.iter().cloned().collect();

fn new(patterns: Vec<Regex>, config: Config) -> Self {
let quit_flag = Arc::new(AtomicBool::new(false));
let interrupt_flag = Arc::new(AtomicBool::new(false));

Self {
paths,
patterns,
config,
quit_flag,
interrupt_flag,
}
}

fn build_overrides(&self) -> Result<Override> {
let first_path = &self.paths[0];
let config = self.config.as_ref();
fn build_overrides(&self, paths: &[PathBuf]) -> Result<Override> {
let first_path = &paths[0];
let config = &self.config;

let mut builder = OverrideBuilder::new(first_path);

Expand All @@ -263,9 +255,10 @@ impl WorkerState {
.map_err(|_| anyhow!("Mismatch in exclude patterns"))
}

fn build_walker(&self) -> Result<WalkParallel> {
let first_path = &self.paths[0];
let config = self.config.as_ref();
fn build_walker(&self, paths: &[PathBuf]) -> Result<WalkParallel> {
let first_path = &paths[0];
let config = &self.config;
let overrides = self.build_overrides(paths)?;

let mut builder = WalkBuilder::new(first_path);
builder
Expand All @@ -276,7 +269,7 @@ impl WorkerState {
.git_global(config.read_vcsignore)
.git_exclude(config.read_vcsignore)
.require_git(config.require_git_to_read_vcsignore)
.overrides(self.build_overrides()?)
.overrides(overrides)
.follow_links(config.follow_links)
// No need to check for supported platforms, option is unavailable on unsupported ones
.same_file_system(config.one_file_system)
Expand Down Expand Up @@ -316,18 +309,18 @@ impl WorkerState {
}
}

for path in &self.paths[1..] {
for path in &paths[1..] {
builder.add(path);
}

Ok(builder.threads(config.threads).build_parallel())
let walker = builder.threads(config.threads).build_parallel();
Ok(walker)
}

/// Run the receiver thread.
/// Run the receiver work, either on this thread or a pool of background
/// threads (for --exec).
fn receive(&self, rx: Receiver<WorkerResult>) -> ExitCode {
let config = Arc::clone(&self.config);
let quit_flag = Arc::clone(&self.quit_flag);
let interrupt_flag = Arc::clone(&self.interrupt_flag);
let config = &self.config;

// This will be set to `Some` if the `--exec` argument was supplied.
if let Some(ref cmd) = config.command {
Expand All @@ -354,19 +347,18 @@ impl WorkerState {
})
}
} else {
let stdout = io::stdout();
let stdout = stdout.lock();
let stdout = io::stdout().lock();
let stdout = io::BufWriter::new(stdout);

ReceiverBuffer::new(config, quit_flag, interrupt_flag, rx, stdout).process()
ReceiverBuffer::new(self, rx, stdout).process()
}
}

/// Spawn the sender threads.
fn spawn_senders(&self, walker: WalkParallel, tx: Sender<WorkerResult>) {
walker.run(|| {
let config = self.config.as_ref();
let patterns = self.patterns.as_ref();
let patterns = &self.patterns;
let config = &self.config;
let quit_flag = self.quit_flag.as_ref();
let tx = tx.clone();

Expand Down Expand Up @@ -534,9 +526,9 @@ impl WorkerState {
}

/// Perform the recursive scan.
fn scan(&self) -> Result<ExitCode> {
let config = self.config.as_ref();
let walker = self.build_walker()?;
fn scan(&self, paths: &[PathBuf]) -> Result<ExitCode> {
let config = &self.config;
let walker = self.build_walker(paths)?;

if config.ls_colors.is_some() && config.is_printing() {
let quit_flag = Arc::clone(&self.quit_flag);
Expand Down Expand Up @@ -575,6 +567,6 @@ impl WorkerState {
/// If the `--exec` argument was supplied, this will create a thread pool for executing
/// jobs in parallel from a given command line and the discovered paths. Otherwise, each
/// path will simply be written to standard output.
pub fn scan(paths: &[PathBuf], patterns: Arc<Vec<Regex>>, config: Arc<Config>) -> Result<ExitCode> {
WorkerState::new(paths, patterns, config).scan()
pub fn scan(paths: &[PathBuf], patterns: Vec<Regex>, config: Config) -> Result<ExitCode> {
WorkerState::new(patterns, config).scan(paths)
}

0 comments on commit 77f68d3

Please sign in to comment.