From 7fa8b8dc4cf78b9995150f0118a4e272bc242f3d Mon Sep 17 00:00:00 2001 From: bluss Date: Mon, 19 Dec 2016 14:01:46 +0100 Subject: [PATCH 1/2] Add method fold_with to Producer and UnindexedProducer This method allows the producers to customize the inner loop. This is useful for iterators that can provide a more efficient inner loop than the default for loop. Example: multidimensional arrays. --- src/par_iter/internal.rs | 50 +++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/par_iter/internal.rs b/src/par_iter/internal.rs index a1bada924..5ffff9669 100644 --- a/src/par_iter/internal.rs +++ b/src/par_iter/internal.rs @@ -28,6 +28,22 @@ pub trait Producer: IntoIterator + Send + Sized { /// Split into two producers; one produces items `0..index`, the /// other `index..N`. Index must be less than `N`. fn split_at(self, index: usize) -> (Self, Self); + + /// Iterate the producer, feeding each element to `folder`, and + /// stop when the folder is full (or all elements have been consumed). + /// + /// The provided implementation is sufficient for most iterables. + fn fold_with(self, mut folder: F) -> F + where F: Folder, + { + for item in self { + folder = folder.consume(item); + if folder.full() { + break; + } + } + folder + } } /// A consumer which consumes items that are fed to it. @@ -95,6 +111,22 @@ pub trait UnindexedConsumer: Consumer { pub trait UnindexedProducer: IntoIterator + Send + Sized { fn can_split(&self) -> bool; fn split(self) -> (Self, Self); + + /// Iterate the producer, feeding each element to `folder`, and + /// stop when the folder is full (or all elements have been consumed). + /// + /// The provided implementation is sufficient for most iterables. + fn fold_with(self, mut folder: F) -> F + where F: Folder, + { + for item in self { + folder = folder.consume(item); + if folder.full() { + break; + } + } + folder + } } /// A splitter controls the policy for splitting into smaller work items. @@ -207,14 +239,7 @@ pub fn bridge_producer_consumer(len: usize, mut producer: P, mut consumer: || helper(len - mid, splitter, right_producer, right_consumer)); reducer.reduce(left_result, right_result) } else { - let mut folder = consumer.into_folder(); - for item in producer { - folder = folder.consume(item); - if folder.full() { - break; - } - } - folder.complete() + producer.fold_with(consumer.into_folder()).complete() } } } @@ -245,13 +270,6 @@ fn bridge_unindexed_producer_consumer(mut splitter: Splitter, || bridge_unindexed_producer_consumer(splitter, right_producer, right_consumer)); reducer.reduce(left_result, right_result) } else { - let mut folder = consumer.into_folder(); - for item in producer { - folder = folder.consume(item); - if folder.full() { - break; - } - } - folder.complete() + producer.fold_with(consumer.into_folder()).complete() } } From 31449c82d869c19bf805240bf64bc340e2790565 Mon Sep 17 00:00:00 2001 From: bluss Date: Mon, 19 Dec 2016 19:03:55 +0100 Subject: [PATCH 2/2] Implement fold_with for ChainProducer --- src/par_iter/chain.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/par_iter/chain.rs b/src/par_iter/chain.rs index e15b373d1..34b33778c 100644 --- a/src/par_iter/chain.rs +++ b/src/par_iter/chain.rs @@ -185,6 +185,17 @@ impl Producer for ChainProducer ChainProducer::new(0, a_right, b_right)) } } + + fn fold_with(self, mut folder: F) -> F + where F: Folder, + { + folder = self.a.fold_with(folder); + if folder.full() { + folder + } else { + self.b.fold_with(folder) + } + } } impl IntoIterator for ChainProducer