Skip to content

Commit

Permalink
scanner: Print partial results as they come out of the parallel itera…
Browse files Browse the repository at this point in the history
…tor.

This relies on a proposed serial bridge as per rayon-rs/rayon#858. As that project is licensed the same as Ruffle itself and the submitter intended it to be included in Rayon, I believe it's legal to copy this code.
  • Loading branch information
kmeisthax committed Sep 8, 2021
1 parent 5664dfb commit 9f4392a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion scanner/Cargo.toml
Expand Up @@ -16,4 +16,5 @@ csv = "1.1"
indicatif = "0.16"
path-slash = "0.1.4"
swf = { path = "../swf" }
rayon = "1.5.1"
rayon = "1.5.1"
crossbeam-channel = "0.5"
67 changes: 59 additions & 8 deletions scanner/src/main.rs
Expand Up @@ -288,6 +288,55 @@ fn scan_file(file: DirEntry, name: String) -> FileResults {
}
}

/// Parallel-to-serial iterator bridge trait
///
/// Proposed in and copied from https://github.com/rayon-rs/rayon/issues/858
pub trait SerBridge<T>
where
T: Send + 'static,
Self: ParallelIterator<Item = T> + 'static,
{
fn ser_bridge(self) -> SerBridgeImpl<T> {
SerBridgeImpl::new(self)
}
}

impl<PI, T> SerBridge<T> for PI
where
T: Send + 'static,
PI: ParallelIterator<Item = T> + 'static,
{
}

/// Parallel-to-serial iterator bridge
///
/// Proposed in and copied from https://github.com/rayon-rs/rayon/issues/858
pub struct SerBridgeImpl<T> {
rx: crossbeam_channel::Receiver<T>,
}

impl<T: Send + 'static> SerBridgeImpl<T> {
pub fn new<PI>(par_iterable: impl IntoParallelIterator<Item = T, Iter = PI>) -> Self
where
PI: ParallelIterator<Item = T> + 'static,
{
let par_iter = par_iterable.into_par_iter();
let (tx, rx) = crossbeam_channel::bounded(0);
std::thread::spawn(move || {
let _ = par_iter.try_for_each(|item| tx.send(item));
});
SerBridgeImpl { rx }
}
}

impl<T> Iterator for SerBridgeImpl<T> {
type Item = T;

fn next(&mut self) -> Option<T> {
self.rx.recv().ok()
}
}

fn main() -> Result<(), std::io::Error> {
ThreadLocalScanLogger::init();

Expand All @@ -314,25 +363,27 @@ fn main() -> Result<(), std::io::Error> {

writer.write_record(&["Filename", "Progress", "Error", "AVM Version"])?;

let mut results = Vec::new();
to_scan
let input_path = opt.input_path;
let closure_progress = progress.clone();

let result_iter = to_scan
.into_par_iter()
.map(|file| {
.map(move |file| {
let name = file
.path()
.strip_prefix(&opt.input_path)
.strip_prefix(&input_path)
.unwrap_or_else(|_| file.path())
.to_slash_lossy();
let result = scan_file(file, name.clone());

progress.inc(1);
progress.set_message(name);
closure_progress.inc(1);
closure_progress.set_message(name);

result
})
.collect_into_vec(&mut results);
.ser_bridge();

for result in results {
for result in result_iter {
if result.error.is_none() {
good += 1;
} else {
Expand Down

0 comments on commit 9f4392a

Please sign in to comment.