| @@ -1,4 +1,4 @@ | |||
| use super::{Folder, Reducer}; | |||
| use super::{Folder, Reducer, WithSetup}; | |||
| /// A consumer is effectively a [generalized "fold" operation][fold], | |||
| /// and in fact each consumer will eventually be converted into a | |||
| @@ -14,7 +14,7 @@ use super::{Folder, Reducer}; | |||
| /// [fold]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold | |||
| /// [`Folder`]: trait.Folder.html | |||
| /// [`Producer`]: trait.Producer.html | |||
| pub trait Consumer<I>: Send + Sized { | |||
| pub trait Consumer<I>: WithSetup + Send + Sized { | |||
| /// The type of folder that this consumer can be converted into. | |||
| type Folder: Folder<I, Result = Self::Result>; | |||
| @@ -9,6 +9,7 @@ mod into_iter; | |||
| mod iterator; | |||
| mod producer; | |||
| mod reducer; | |||
| mod setup; | |||
| pub use consumer::Consumer; | |||
| pub use drain::{ParallelDrainFull, ParallelDrainRange}; | |||
| @@ -21,3 +22,4 @@ pub use into_iter::{IntoParallelIterator, IntoParallelRefIterator, IntoParallelR | |||
| pub use iterator::{IndexedParallelIterator, ParallelIterator}; | |||
| pub use producer::{IndexedProducer, IndexedProducerCallback, Producer, ProducerCallback}; | |||
| pub use reducer::Reducer; | |||
| pub use setup::{Setup, WithSetup}; | |||
| @@ -1,4 +1,4 @@ | |||
| use super::Folder; | |||
| use super::{Folder, WithSetup}; | |||
| /// A variant on `Producer` which does not know its exact length or | |||
| /// cannot represent it in a `usize`. These producers act like | |||
| @@ -8,7 +8,7 @@ use super::Folder; | |||
| /// (In principle, `Producer` could extend this trait; however, it | |||
| /// does not because to do so would require producers to carry their | |||
| /// own length with them.) | |||
| pub trait Producer: Send + Sized { | |||
| pub trait Producer: WithSetup + Send + Sized { | |||
| /// The type of item returned by this producer. | |||
| type Item; | |||
| @@ -22,11 +22,6 @@ pub trait Producer: Send + Sized { | |||
| /// Split midway into a new producer if possible, otherwise return `None`. | |||
| fn split(self) -> (Self, Option<Self>); | |||
| /// Number of splits/threads this iterator will use to proceed. | |||
| fn splits(&self) -> Option<usize> { | |||
| None | |||
| } | |||
| /// Iterate the producer, feeding each element to `folder`, and | |||
| /// stop when the folder is full (or all elements have been consumed). | |||
| /// | |||
| @@ -64,7 +59,7 @@ pub trait Producer: Send + Sized { | |||
| /// [r]: https://github.com/rayon-rs/rayon/blob/master/src/iter/plumbing/README.md | |||
| /// [20671]: https://github.com/rust-lang/rust/issues/20671 | |||
| #[allow(clippy::len_without_is_empty)] | |||
| pub trait IndexedProducer: Send + Sized { | |||
| pub trait IndexedProducer: WithSetup + Send + Sized { | |||
| /// The type of item that will be produced by this producer once | |||
| /// it is converted into an iterator. | |||
| type Item; | |||
| @@ -84,38 +79,6 @@ pub trait IndexedProducer: Send + Sized { | |||
| /// other `index..N`. Index must be less than or equal to `N`. | |||
| fn split_at(self, index: usize) -> (Self, Self); | |||
| /// Number of splits/threads this iterator will use to proceed. | |||
| fn splits(&self) -> Option<usize> { | |||
| None | |||
| } | |||
| /// The minimum number of items that we will process | |||
| /// sequentially. Defaults to 1, which means that we will split | |||
| /// all the way down to a single item. This can be raised higher | |||
| /// using the [`with_min_len`] method, which will force us to | |||
| /// create sequential tasks at a larger granularity. Note that | |||
| /// Rayon automatically normally attempts to adjust the size of | |||
| /// parallel splits to reduce overhead, so this should not be | |||
| /// needed. | |||
| /// | |||
| /// [`with_min_len`]: ../trait.IndexedParallelIterator.html#method.with_min_len | |||
| fn min_len(&self) -> Option<usize> { | |||
| None | |||
| } | |||
| /// The maximum number of items that we will process | |||
| /// sequentially. Defaults to MAX, which means that we can choose | |||
| /// not to split at all. This can be lowered using the | |||
| /// [`with_max_len`] method, which will force us to create more | |||
| /// parallel tasks. Note that Rayon automatically normally | |||
| /// attempts to adjust the size of parallel splits to reduce | |||
| /// overhead, so this should not be needed. | |||
| /// | |||
| /// [`with_max_len`]: ../trait.IndexedParallelIterator.html#method.with_max_len | |||
| fn max_len(&self) -> Option<usize> { | |||
| None | |||
| } | |||
| /// Iterate the producer, feeding each element to `folder`, and | |||
| /// stop when the folder is full (or all elements have been consumed). | |||
| /// | |||
| @@ -0,0 +1,59 @@ | |||
| use std::cmp::{max, min}; | |||
| pub trait WithSetup { | |||
| /// Setup to drive the iterator with. | |||
| fn setup(&self) -> Setup { | |||
| Setup::default() | |||
| } | |||
| } | |||
| #[derive(Debug, Default, Clone)] | |||
| pub struct Setup { | |||
| /// Number of splits/threads this iterator will use to proceed. | |||
| pub splits: Option<usize>, | |||
| /// The minimum number of items that we will process | |||
| /// sequentially. Defaults to 1, which means that we will split | |||
| /// all the way down to a single item. This can be raised higher | |||
| /// using the [`with_min_len`] method, which will force us to | |||
| /// create sequential tasks at a larger granularity. Note that | |||
| /// Rayon automatically normally attempts to adjust the size of | |||
| /// parallel splits to reduce overhead, so this should not be | |||
| /// needed. | |||
| /// | |||
| /// [`with_min_len`]: ../trait.IndexedParallelIterator.html#method.with_min_len | |||
| pub min_len: Option<usize>, | |||
| /// The maximum number of items that we will process | |||
| /// sequentially. Defaults to MAX, which means that we can choose | |||
| /// not to split at all. This can be lowered using the | |||
| /// [`with_max_len`] method, which will force us to create more | |||
| /// parallel tasks. Note that Rayon automatically normally | |||
| /// attempts to adjust the size of parallel splits to reduce | |||
| /// overhead, so this should not be needed. | |||
| /// | |||
| /// [`with_max_len`]: ../trait.IndexedParallelIterator.html#method.with_max_len | |||
| pub max_len: Option<usize>, | |||
| } | |||
| impl Setup { | |||
| pub fn merge(mut self, other: Self) -> Self { | |||
| self.splits = other.splits.or(self.splits); | |||
| self.min_len = match (self.min_len, other.min_len) { | |||
| (Some(a), Some(b)) => Some(max(a, b)), | |||
| (Some(a), None) => Some(a), | |||
| (None, Some(b)) => Some(b), | |||
| (None, None) => None, | |||
| }; | |||
| self.max_len = match (self.max_len, other.max_len) { | |||
| (Some(a), Some(b)) => Some(min(a, b)), | |||
| (Some(a), None) => Some(a), | |||
| (None, Some(b)) => Some(b), | |||
| (None, None) => None, | |||
| }; | |||
| self | |||
| } | |||
| } | |||
| @@ -42,7 +42,8 @@ where | |||
| C: Consumer<P::Item, Result = T1, Reducer = R> + 'a, | |||
| R: Reducer<T1> + Send + 'a, | |||
| { | |||
| let splits = producer.splits().unwrap_or(self.splits); | |||
| let setup = producer.setup().merge(consumer.setup()); | |||
| let splits = setup.splits.unwrap_or(self.splits); | |||
| let splitter = Splitter::new(splits); | |||
| exec(splitter, producer, consumer) | |||
| @@ -54,13 +55,9 @@ where | |||
| C: Consumer<P::Item, Result = T1, Reducer = R> + 'a, | |||
| R: Reducer<T1> + Send + 'a, | |||
| { | |||
| let splits = producer.splits().unwrap_or(self.splits); | |||
| let splitter = IndexedSplitter::new( | |||
| splits, | |||
| producer.len(), | |||
| producer.min_len(), | |||
| producer.max_len(), | |||
| ); | |||
| let setup = producer.setup().merge(consumer.setup()); | |||
| let splits = setup.splits.unwrap_or(self.splits); | |||
| let splitter = IndexedSplitter::new(splits, producer.len(), setup.min_len, setup.max_len); | |||
| exec_indexed(splitter, producer, consumer) | |||
| } | |||
| @@ -1,9 +1,8 @@ | |||
| use std::cmp::{max, min}; | |||
| use std::iter::{DoubleEndedIterator, ExactSizeIterator, Iterator}; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Chain */ | |||
| @@ -215,6 +214,26 @@ struct ChainProducer<P1, P2> { | |||
| producer_2: Option<P2>, | |||
| } | |||
| impl<P1, P2> WithSetup for ChainProducer<P1, P2> | |||
| where | |||
| P1: WithSetup, | |||
| P2: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| let mut ret = Setup::default(); | |||
| if let Some(p) = &self.producer_1 { | |||
| ret = ret.merge(p.setup()); | |||
| } | |||
| if let Some(p) = &self.producer_2 { | |||
| ret = ret.merge(p.setup()); | |||
| } | |||
| ret | |||
| } | |||
| } | |||
| impl<'a, P1, P2, T> Producer for ChainProducer<P1, P2> | |||
| where | |||
| P1: Producer<Item = T>, | |||
| @@ -276,17 +295,6 @@ where | |||
| } | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| let splits_1 = self.producer_1.as_ref().and_then(|p| p.splits()); | |||
| let splits_2 = self.producer_2.as_ref().and_then(|p| p.splits()); | |||
| match (splits_1, splits_2) { | |||
| (Some(splits), _) => Some(splits), | |||
| (None, Some(splits)) => Some(splits), | |||
| (None, None) => None, | |||
| } | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -412,31 +420,6 @@ where | |||
| } | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| let splits_1 = self.producer_1.as_ref().and_then(|p| p.splits()); | |||
| let splits_2 = self.producer_2.as_ref().and_then(|p| p.splits()); | |||
| match (splits_1, splits_2) { | |||
| (Some(splits), _) => Some(splits), | |||
| (None, Some(splits)) => Some(splits), | |||
| (None, None) => None, | |||
| } | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| let min_1 = self.producer_1.as_ref().and_then(|p| p.min_len()); | |||
| let min_2 = self.producer_2.as_ref().and_then(|p| p.min_len()); | |||
| min(min_1, min_2) | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| let max_1 = self.producer_1.as_ref().and_then(|p| p.max_len()); | |||
| let max_2 = self.producer_2.as_ref().and_then(|p| p.max_len()); | |||
| max(max_1, max_2) | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Cloned */ | |||
| @@ -79,6 +79,15 @@ struct ClonedConsumer<C> { | |||
| base: C, | |||
| } | |||
| impl<C> WithSetup for ClonedConsumer<C> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, T, C> Consumer<&'a T> for ClonedConsumer<C> | |||
| where | |||
| T: Clone, | |||
| @@ -196,6 +205,15 @@ struct ClonedProducer<P> { | |||
| base: P, | |||
| } | |||
| impl<P> WithSetup for ClonedProducer<P> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, T, P> Producer for ClonedProducer<P> | |||
| where | |||
| T: Clone + 'a, | |||
| @@ -217,10 +235,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -254,18 +268,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Copied */ | |||
| @@ -79,6 +79,15 @@ struct CopiedConsumer<C> { | |||
| base: C, | |||
| } | |||
| impl<C> WithSetup for CopiedConsumer<C> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, T, C> Consumer<&'a T> for CopiedConsumer<C> | |||
| where | |||
| T: Copy, | |||
| @@ -196,6 +205,15 @@ struct CopiedProducer<P> { | |||
| base: P, | |||
| } | |||
| impl<P> WithSetup for CopiedProducer<P> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, T, P> Producer for CopiedProducer<P> | |||
| where | |||
| T: Copy + 'a, | |||
| @@ -217,10 +235,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -254,18 +268,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -1,4 +1,7 @@ | |||
| use crate::{Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer}; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer, Setup, | |||
| WithSetup, | |||
| }; | |||
| /* Filter */ | |||
| @@ -54,6 +57,15 @@ struct FilterConsumer<C, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, O> WithSetup for FilterConsumer<C, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, O, T> Consumer<T> for FilterConsumer<C, O> | |||
| where | |||
| C: Consumer<T>, | |||
| @@ -179,6 +191,15 @@ struct FilterProducer<P, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, O> WithSetup for FilterProducer<P, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, O, T> Producer for FilterProducer<P, O> | |||
| where | |||
| P: Producer<Item = T>, | |||
| @@ -207,10 +228,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -1,4 +1,7 @@ | |||
| use crate::{Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer}; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer, Setup, | |||
| WithSetup, | |||
| }; | |||
| /* FilterMap */ | |||
| @@ -55,6 +58,15 @@ struct FilterMapConsumer<C, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, O> WithSetup for FilterMapConsumer<C, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, O, T, S> Consumer<T> for FilterMapConsumer<C, O> | |||
| where | |||
| C: Consumer<S>, | |||
| @@ -182,6 +194,15 @@ struct FilterMapProducer<P, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, O> WithSetup for FilterMapProducer<P, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, O, T, S> Producer for FilterMapProducer<P, O> | |||
| where | |||
| P: Producer<Item = T>, | |||
| @@ -211,10 +232,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -3,7 +3,7 @@ use std::sync::{ | |||
| Arc, | |||
| }; | |||
| use crate::{Consumer, Driver, Executor, Folder, ParallelIterator, Reducer}; | |||
| use crate::{Consumer, Driver, Executor, Folder, ParallelIterator, Reducer, WithSetup}; | |||
| #[derive(Copy, Clone, Eq, PartialEq)] | |||
| pub enum FindMatch { | |||
| @@ -174,6 +174,8 @@ struct FindConsumer<O> { | |||
| find_match: FindMatch, | |||
| } | |||
| impl<O> WithSetup for FindConsumer<O> {} | |||
| impl<O, T> Consumer<T> for FindConsumer<O> | |||
| where | |||
| O: Fn(&T) -> bool + Clone + Send, | |||
| @@ -1,6 +1,9 @@ | |||
| use std::iter::IntoIterator; | |||
| use crate::{Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer}; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer, Setup, | |||
| WithSetup, | |||
| }; | |||
| /* FlattenIter */ | |||
| @@ -105,6 +108,15 @@ struct FlatMapIterConsumer<C, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, O> WithSetup for FlatMapIterConsumer<C, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, O, T, SI> Consumer<T> for FlatMapIterConsumer<C, O> | |||
| where | |||
| C: Consumer<SI::Item>, | |||
| @@ -233,6 +245,15 @@ struct FlatMapIterProducer<P, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, O> WithSetup for FlatMapIterProducer<P, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, O, T, SI> Producer for FlatMapIterProducer<P, O> | |||
| where | |||
| P: Producer<Item = T>, | |||
| @@ -262,10 +283,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -1,4 +1,7 @@ | |||
| use crate::{Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer}; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer, Setup, | |||
| WithSetup, | |||
| }; | |||
| /* Fold */ | |||
| @@ -131,6 +134,15 @@ struct FoldConsumer<C, S, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, S, O> WithSetup for FoldConsumer<C, S, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, S, O, T, U> Consumer<T> for FoldConsumer<C, S, O> | |||
| where | |||
| C: Consumer<U>, | |||
| @@ -224,6 +236,15 @@ struct FoldProducer<P, S, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, S, O> WithSetup for FoldProducer<P, S, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, S, O, U> Producer for FoldProducer<P, S, O> | |||
| where | |||
| P: Producer, | |||
| @@ -259,10 +280,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -1,4 +1,4 @@ | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator}; | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, WithSetup}; | |||
| use super::noop::NoOpReducer; | |||
| @@ -38,6 +38,8 @@ pub struct ForEachConsumer<O> { | |||
| operation: O, | |||
| } | |||
| impl<O> WithSetup for ForEachConsumer<O> {} | |||
| impl<O, I> Consumer<I> for ForEachConsumer<O> | |||
| where | |||
| O: Fn(I) + Clone + Send, | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Inspect */ | |||
| @@ -97,6 +97,15 @@ struct InspectConsumer<C, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, O> WithSetup for InspectConsumer<C, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, O, T> Consumer<T> for InspectConsumer<C, O> | |||
| where | |||
| C: Consumer<T>, | |||
| @@ -240,6 +249,15 @@ struct InspectProducer<P, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, O> WithSetup for InspectProducer<P, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, O, T> Producer for InspectProducer<P, O> | |||
| where | |||
| P: Producer<Item = T>, | |||
| @@ -268,10 +286,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -316,18 +330,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -2,7 +2,7 @@ use std::iter::{once, DoubleEndedIterator, ExactSizeIterator, Fuse, Iterator}; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Intersperse */ | |||
| @@ -161,6 +161,15 @@ struct IntersperseProducer<P, I> { | |||
| clone_first: bool, | |||
| } | |||
| impl<P, I> WithSetup for IntersperseProducer<P, I> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<P, I> Producer for IntersperseProducer<P, I> | |||
| where | |||
| P: Producer<Item = I>, | |||
| @@ -200,10 +209,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, base: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -284,18 +289,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn fold_with<F>(self, base: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -462,6 +455,15 @@ struct IntersperseConsumer<C, I> { | |||
| clone_first: bool, | |||
| } | |||
| impl<C, I> WithSetup for IntersperseConsumer<C, I> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<C, I> Consumer<I> for IntersperseConsumer<C, I> | |||
| where | |||
| C: Consumer<I>, | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Map */ | |||
| @@ -140,6 +140,15 @@ struct MapProducer<P, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, O> WithSetup for MapProducer<P, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<P, O, T> Producer for MapProducer<P, O> | |||
| where | |||
| P: Producer, | |||
| @@ -195,22 +204,10 @@ where | |||
| self.base.into_iter().map(self.operation) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn len(&self) -> usize { | |||
| self.base.len() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn split_at(self, index: usize) -> (Self, Self) { | |||
| let (left, right) = self.base.split_at(index); | |||
| @@ -246,6 +243,15 @@ struct MapConsumer<C, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, O> WithSetup for MapConsumer<C, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<C, O> MapConsumer<C, O> { | |||
| fn new(base: C, operation: O) -> Self { | |||
| Self { base, operation } | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| use super::map_with::{MapWithFolder, MapWithIter}; | |||
| @@ -157,6 +157,15 @@ struct MapInitProducer<P, S, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, S, O> WithSetup for MapInitProducer<P, S, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<P, S, O, T, U> Producer for MapInitProducer<P, S, O> | |||
| where | |||
| P: Producer, | |||
| @@ -226,22 +235,10 @@ where | |||
| } | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn len(&self) -> usize { | |||
| self.base.len() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn split_at(self, index: usize) -> (Self, Self) { | |||
| let (left, right) = self.base.split_at(index); | |||
| @@ -281,6 +278,15 @@ struct MapInitConsumer<C, S, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, S, O> WithSetup for MapInitConsumer<C, S, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<C, S, O> MapInitConsumer<C, S, O> { | |||
| fn new(base: C, init: S, operation: O) -> Self { | |||
| Self { | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* MapWith */ | |||
| @@ -155,6 +155,15 @@ struct MapWithProducer<P, S, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, S, O> WithSetup for MapWithProducer<P, S, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<P, S, O, T> Producer for MapWithProducer<P, S, O> | |||
| where | |||
| P: Producer, | |||
| @@ -224,22 +233,10 @@ where | |||
| } | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn len(&self) -> usize { | |||
| self.base.len() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn split_at(self, index: usize) -> (Self, Self) { | |||
| let (left, right) = self.base.split_at(index); | |||
| @@ -324,6 +321,15 @@ struct MapWithConsumer<C, S, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, S, O> WithSetup for MapWithConsumer<C, S, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<C, S, O> MapWithConsumer<C, S, O> { | |||
| fn new(base: C, item: S, operation: O) -> Self { | |||
| Self { | |||
| @@ -71,7 +71,7 @@ mod tests { | |||
| move || j.fetch_add(2, Ordering::Relaxed), | |||
| |init, (init2, item)| (*init, init2, item), | |||
| ) | |||
| .with_splits(4) | |||
| .with_splits(16) | |||
| .inspect(|x| { | |||
| println!( | |||
| "Thread ID = {:?}; Item = {:?}", | |||
| @@ -1,7 +1,9 @@ | |||
| use crate::{Consumer, Folder, Reducer}; | |||
| use crate::{Consumer, Folder, Reducer, WithSetup}; | |||
| pub struct NoOpConsumer; | |||
| impl WithSetup for NoOpConsumer {} | |||
| impl<T> Consumer<T> for NoOpConsumer { | |||
| type Folder = NoOpConsumer; | |||
| type Reducer = NoOpReducer; | |||
| @@ -6,7 +6,7 @@ use std::thread::panicking; | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* PanicFuse */ | |||
| @@ -163,6 +163,15 @@ struct PanicFuseProducer<P> { | |||
| fuse: Fuse, | |||
| } | |||
| impl<P> WithSetup for PanicFuseProducer<P> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<P> Producer for PanicFuseProducer<P> | |||
| where | |||
| P: Producer, | |||
| @@ -190,10 +199,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, base: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -240,18 +245,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn fold_with<F>(self, base: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -313,6 +306,15 @@ struct PanicFuseConsumer<C> { | |||
| fuse: Fuse, | |||
| } | |||
| impl<C> WithSetup for PanicFuseConsumer<C> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<C, T> Consumer<T> for PanicFuseConsumer<C> | |||
| where | |||
| C: Consumer<T>, | |||
| @@ -1,4 +1,7 @@ | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelExtend, ParallelIterator, Reducer}; | |||
| use crate::{ | |||
| core::Driver, Consumer, Executor, Folder, ParallelExtend, ParallelIterator, Reducer, Setup, | |||
| WithSetup, | |||
| }; | |||
| /* Partition */ | |||
| @@ -164,6 +167,21 @@ macro_rules! parallel_extend_tuple { | |||
| } | |||
| } | |||
| #[allow(non_snake_case)] | |||
| impl<O, $($C,)+> WithSetup for PartitionConsumer<($($C,)+), O> | |||
| where | |||
| $($C: WithSetup,)+ | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| let ($($C,)+) = &self.base; | |||
| let mut ret = Setup::default(); | |||
| $(ret = ret.merge($C.setup());)+ | |||
| ret | |||
| } | |||
| } | |||
| #[allow(non_snake_case)] | |||
| impl<O, I, $($I,)+ $($C,)+> Consumer<I> for PartitionConsumer<($($C,)+), O> | |||
| where | |||
| @@ -1,7 +1,7 @@ | |||
| use std::iter::{empty, once}; | |||
| use std::marker::PhantomData; | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer}; | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer, WithSetup}; | |||
| /* Product */ | |||
| @@ -39,6 +39,8 @@ where | |||
| pub struct ProductConsumer<P>(PhantomData<P>); | |||
| impl<P> WithSetup for ProductConsumer<P> {} | |||
| impl<P, I> Consumer<I> for ProductConsumer<P> | |||
| where | |||
| P: std::iter::Product<I> + std::iter::Product + Send, | |||
| @@ -1,4 +1,4 @@ | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer}; | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer, WithSetup}; | |||
| /* Reduce */ | |||
| @@ -91,6 +91,8 @@ struct ReduceConsumer<S, O> { | |||
| operation: O, | |||
| } | |||
| impl<S, O> WithSetup for ReduceConsumer<S, O> {} | |||
| impl<S, O> Clone for ReduceConsumer<S, O> | |||
| where | |||
| S: Clone, | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, ExecutorCallback, Folder, IndexedParallelIterator, IndexedProducer, | |||
| IndexedProducerCallback, ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| pub struct Splits<X> { | |||
| @@ -20,14 +20,17 @@ where | |||
| { | |||
| type Item = X::Item; | |||
| fn drive<E, C, D, R>(self, executor: E, consumer: C) -> E::Result | |||
| fn drive<E, C, D, R>(self, executor: E, base: C) -> E::Result | |||
| where | |||
| E: Executor<'a, D>, | |||
| C: Consumer<Self::Item, Result = D, Reducer = R> + 'a, | |||
| D: Send + 'a, | |||
| R: Reducer<D> + Send + 'a, | |||
| { | |||
| self.with_producer(ExecutorCallback::new(executor, consumer)) | |||
| let splits = self.splits; | |||
| let consumer = SplitsConsumer { base, splits }; | |||
| self.base.drive(executor, consumer) | |||
| } | |||
| fn with_producer<CB>(self, base: CB) -> CB::Output | |||
| @@ -48,14 +51,17 @@ impl<'a, X> IndexedParallelIterator<'a> for Splits<X> | |||
| where | |||
| X: IndexedParallelIterator<'a>, | |||
| { | |||
| fn drive_indexed<E, C, D, R>(self, executor: E, consumer: C) -> E::Result | |||
| fn drive_indexed<E, C, D, R>(self, executor: E, base: C) -> E::Result | |||
| where | |||
| E: Executor<'a, D>, | |||
| C: Consumer<Self::Item, Result = D, Reducer = R> + 'a, | |||
| D: Send + 'a, | |||
| R: Reducer<D> + Send + 'a, | |||
| { | |||
| self.with_producer_indexed(ExecutorCallback::new(executor, consumer)) | |||
| let splits = self.splits; | |||
| let consumer = SplitsConsumer { base, splits }; | |||
| self.base.drive_indexed(executor, consumer) | |||
| } | |||
| fn with_producer_indexed<CB>(self, base: CB) -> CB::Output | |||
| @@ -119,6 +125,18 @@ struct SplitsProducer<P> { | |||
| splits: usize, | |||
| } | |||
| impl<P> WithSetup for SplitsProducer<P> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup().merge(Setup { | |||
| splits: Some(self.splits), | |||
| ..Default::default() | |||
| }) | |||
| } | |||
| } | |||
| impl<P> Producer for SplitsProducer<P> | |||
| where | |||
| P: Producer, | |||
| @@ -140,10 +158,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| Some(self.splits) | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -180,22 +194,72 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| Some(self.splits) | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| { | |||
| self.base.fold_with(folder) | |||
| } | |||
| } | |||
| /* SplitsConsumer */ | |||
| struct SplitsConsumer<C> { | |||
| base: C, | |||
| splits: usize, | |||
| } | |||
| impl<C> WithSetup for SplitsConsumer<C> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup().merge(Setup { | |||
| splits: Some(self.splits), | |||
| ..Default::default() | |||
| }) | |||
| } | |||
| } | |||
| impl<C, I> Consumer<I> for SplitsConsumer<C> | |||
| where | |||
| C: Consumer<I>, | |||
| { | |||
| type Folder = C::Folder; | |||
| type Reducer = C::Reducer; | |||
| type Result = C::Result; | |||
| fn split(self) -> (Self, Self, Self::Reducer) { | |||
| let splits = self.splits; | |||
| let (left, right, reducer) = self.base.split(); | |||
| let left = Self { base: left, splits }; | |||
| let right = Self { | |||
| base: right, | |||
| splits, | |||
| }; | |||
| (left, right, reducer) | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { | |||
| let splits = self.splits; | |||
| let (left, right, reducer) = self.base.split_at(index); | |||
| let left = Self { base: left, splits }; | |||
| let right = Self { | |||
| base: right, | |||
| splits, | |||
| }; | |||
| (left, right, reducer) | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| fn into_folder(self) -> Self::Folder { | |||
| self.base.into_folder() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| { | |||
| self.base.fold_with(folder) | |||
| fn is_full(&self) -> bool { | |||
| self.base.is_full() | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| use std::iter::{empty, once}; | |||
| use std::marker::PhantomData; | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer}; | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer, WithSetup}; | |||
| /* Sum */ | |||
| @@ -39,6 +39,8 @@ where | |||
| pub struct SumConsumer<S>(PhantomData<S>); | |||
| impl<S> WithSetup for SumConsumer<S> {} | |||
| impl<S, I> Consumer<I> for SumConsumer<S> | |||
| where | |||
| S: std::iter::Sum<I> + std::iter::Sum + Send, | |||
| @@ -2,6 +2,7 @@ use std::marker::PhantomData; | |||
| use crate::{ | |||
| misc::Try, Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| Setup, WithSetup, | |||
| }; | |||
| /* TryFold */ | |||
| @@ -148,6 +149,15 @@ struct TryFoldConsumer<C, S, O, T> { | |||
| marker: PhantomData<T>, | |||
| } | |||
| impl<C, S, O, T> WithSetup for TryFoldConsumer<C, S, O, T> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, S, O, T, I> Consumer<I> for TryFoldConsumer<C, S, O, T> | |||
| where | |||
| C: Consumer<T>, | |||
| @@ -250,6 +260,15 @@ struct TryFoldProducer<P, S, O, T> { | |||
| marker: PhantomData<T>, | |||
| } | |||
| impl<P, S, O, T> WithSetup for TryFoldProducer<P, S, O, T> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, S, O, T> Producer for TryFoldProducer<P, S, O, T> | |||
| where | |||
| P: Producer, | |||
| @@ -294,10 +313,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -3,7 +3,9 @@ use std::sync::{ | |||
| Arc, | |||
| }; | |||
| use crate::{core::Driver, misc::Try, Consumer, Executor, Folder, ParallelIterator, Reducer}; | |||
| use crate::{ | |||
| core::Driver, misc::Try, Consumer, Executor, Folder, ParallelIterator, Reducer, WithSetup, | |||
| }; | |||
| /* TryReduce */ | |||
| @@ -111,6 +113,8 @@ struct TryReduceConsumer<S, O> { | |||
| is_full: Arc<AtomicBool>, | |||
| } | |||
| impl<S, O> WithSetup for TryReduceConsumer<S, O> {} | |||
| impl<S, O> Clone for TryReduceConsumer<S, O> | |||
| where | |||
| S: Clone, | |||
| @@ -1,4 +1,7 @@ | |||
| use crate::{core::Driver, Consumer, Executor, Folder, ParallelExtend, ParallelIterator, Reducer}; | |||
| use crate::{ | |||
| core::Driver, Consumer, Executor, Folder, ParallelExtend, ParallelIterator, Reducer, Setup, | |||
| WithSetup, | |||
| }; | |||
| /* Unzip */ | |||
| @@ -70,6 +73,21 @@ macro_rules! parallel_extend_tuple { | |||
| } | |||
| } | |||
| #[allow(non_snake_case)] | |||
| impl<$($C,)+> WithSetup for UnzipConsumer<($($C,)+)> | |||
| where | |||
| $($C: WithSetup,)+ | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| let ($($C,)+) = &self.0; | |||
| let mut ret = Setup::default(); | |||
| $(ret = ret.merge($C.setup());)+ | |||
| ret | |||
| } | |||
| } | |||
| #[allow(non_snake_case)] | |||
| impl<$($C,)+ $($I,)+> Consumer<($($I,)+)> for UnzipConsumer<($($C,)+)> | |||
| where | |||
| @@ -1,6 +1,6 @@ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* Update */ | |||
| @@ -97,6 +97,15 @@ struct UpdateConsumer<C, O> { | |||
| operation: O, | |||
| } | |||
| impl<C, O> WithSetup for UpdateConsumer<C, O> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, C, O, T> Consumer<T> for UpdateConsumer<C, O> | |||
| where | |||
| C: Consumer<T>, | |||
| @@ -240,6 +249,15 @@ struct UpdateProducer<P, O> { | |||
| operation: O, | |||
| } | |||
| impl<P, O> WithSetup for UpdateProducer<P, O> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<'a, P, O, T> Producer for UpdateProducer<P, O> | |||
| where | |||
| P: Producer<Item = T>, | |||
| @@ -271,10 +289,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -322,18 +336,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| fn fold_with<F>(self, folder: F) -> F | |||
| where | |||
| F: Folder<Self::Item>, | |||
| @@ -6,7 +6,7 @@ use std::sync::{ | |||
| use crate::{ | |||
| Consumer, Executor, Folder, IndexedParallelIterator, IndexedProducer, IndexedProducerCallback, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| /* WhileSome */ | |||
| @@ -134,6 +134,15 @@ struct WhileSomeProducer<P> { | |||
| is_full: Arc<AtomicBool>, | |||
| } | |||
| impl<P> WithSetup for WhileSomeProducer<P> | |||
| where | |||
| P: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<P, T> Producer for WhileSomeProducer<P> | |||
| where | |||
| P: Producer<Item = Option<T>>, | |||
| @@ -160,10 +169,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| } | |||
| impl<P, T> IndexedProducer for WhileSomeProducer<P> | |||
| @@ -198,18 +203,6 @@ where | |||
| (left, right) | |||
| } | |||
| fn splits(&self) -> Option<usize> { | |||
| self.base.splits() | |||
| } | |||
| fn min_len(&self) -> Option<usize> { | |||
| self.base.min_len() | |||
| } | |||
| fn max_len(&self) -> Option<usize> { | |||
| self.base.max_len() | |||
| } | |||
| } | |||
| /* WhileSomeIter */ | |||
| @@ -280,6 +273,15 @@ struct WhileSomeConsumer<C> { | |||
| is_full: Arc<AtomicBool>, | |||
| } | |||
| impl<C> WithSetup for WhileSomeConsumer<C> | |||
| where | |||
| C: WithSetup, | |||
| { | |||
| fn setup(&self) -> Setup { | |||
| self.base.setup() | |||
| } | |||
| } | |||
| impl<C, T> Consumer<Option<T>> for WhileSomeConsumer<C> | |||
| where | |||
| C: Consumer<T>, | |||
| @@ -8,6 +8,6 @@ pub use self::core::{ | |||
| Consumer, Driver, Executor, ExecutorCallback, Folder, IndexedParallelIterator, IndexedProducer, | |||
| IndexedProducerCallback, IntoParallelIterator, IntoParallelRefIterator, | |||
| IntoParallelRefMutIterator, ParallelDrainFull, ParallelDrainRange, ParallelExtend, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelIterator, Producer, ProducerCallback, Reducer, Setup, WithSetup, | |||
| }; | |||
| pub use self::executor::{DefaultExecutor, SequentialExecutor}; | |||
| @@ -3,7 +3,7 @@ use std::ops::Range; | |||
| use crate::{ | |||
| Consumer, Executor, ExecutorCallback, IndexedParallelIterator, IndexedProducer, | |||
| IndexedProducerCallback, IntoParallelIterator, ParallelIterator, Producer, ProducerCallback, | |||
| Reducer, | |||
| Reducer, WithSetup, | |||
| }; | |||
| /// Parallel iterator over a range, implemented for all integer types. | |||
| @@ -94,7 +94,15 @@ macro_rules! unindexed_parallel_iterator_impl { | |||
| D: Send + 'a, | |||
| R: Reducer<D> + Send + 'a, | |||
| { | |||
| self.with_producer(ExecutorCallback::new(executor, consumer)) | |||
| if let Some(len) = self.len_hint_opt() { | |||
| let start = self.range.start; | |||
| (0..len) | |||
| .into_par_iter() | |||
| .map(move |i| start.wrapping_add(i as $t)) | |||
| .drive_indexed(executor, consumer) | |||
| } else { | |||
| self.with_producer(ExecutorCallback::new(executor, consumer)) | |||
| } | |||
| } | |||
| fn with_producer<CB>(self, callback: CB) -> CB::Output | |||
| @@ -105,10 +113,18 @@ macro_rules! unindexed_parallel_iterator_impl { | |||
| } | |||
| fn len_hint_opt(&self) -> Option<usize> { | |||
| Some(self.range.length() as usize) | |||
| let len = self.range.length(); | |||
| if len <= usize::MAX as $len_t { | |||
| Some(len as usize) | |||
| } else { | |||
| None | |||
| } | |||
| } | |||
| } | |||
| impl WithSetup for IterProducer<$t> {} | |||
| impl Producer for IterProducer<$t> { | |||
| type Item = $t; | |||
| type IntoIter = Range<$t>; | |||
| @@ -1,7 +1,7 @@ | |||
| use crate::{ | |||
| Consumer, Executor, ExecutorCallback, IndexedParallelIterator, IndexedProducer, | |||
| IndexedProducerCallback, IntoParallelIterator, ParallelIterator, Producer, ProducerCallback, | |||
| Reducer, | |||
| Reducer, WithSetup, | |||
| }; | |||
| impl<'a, T> IntoParallelIterator<'a> for &'a [T] | |||
| @@ -118,6 +118,8 @@ struct IterProducer<'a, T> { | |||
| slice: &'a [T], | |||
| } | |||
| impl<'a, T> WithSetup for IterProducer<'a, T> {} | |||
| impl<'a, T> Producer for IterProducer<'a, T> | |||
| where | |||
| T: Send + Sync, | |||
| @@ -232,6 +234,8 @@ struct IterMutProducer<'a, T> { | |||
| slice: &'a mut [T], | |||
| } | |||
| impl<'a, T> WithSetup for IterMutProducer<'a, T> {} | |||
| impl<'a, T> Producer for IterMutProducer<'a, T> | |||
| where | |||
| T: Send + Sync, | |||
| @@ -9,7 +9,7 @@ use std::sync::Arc; | |||
| use crate::{ | |||
| misc::simplify_range, Consumer, Executor, ExecutorCallback, Folder, IndexedParallelIterator, | |||
| IndexedProducer, IndexedProducerCallback, IntoParallelIterator, ParallelDrainRange, | |||
| ParallelExtend, ParallelIterator, Producer, ProducerCallback, Reducer, | |||
| ParallelExtend, ParallelIterator, Producer, ProducerCallback, Reducer, WithSetup, | |||
| }; | |||
| /// Parallel iterator that moves out of a vector. | |||
| @@ -136,6 +136,8 @@ impl<'a, T> VecProducer<'a, T> { | |||
| } | |||
| } | |||
| impl<'a, T> WithSetup for VecProducer<'a, T> {} | |||
| impl<'a, T> Drop for VecProducer<'a, T> { | |||
| fn drop(&mut self) { | |||
| unsafe { | |||
| @@ -331,6 +333,8 @@ struct DrainProducer<'a, T> { | |||
| slice: &'a mut [T], | |||
| } | |||
| impl<'a, T> WithSetup for DrainProducer<'a, T> {} | |||
| impl<'a, T> Drop for DrainProducer<'a, T> { | |||
| fn drop(&mut self) { | |||
| unsafe { | |||
| @@ -486,6 +490,8 @@ pub struct VecConsumer<T> { | |||
| vec: Option<Vec<T>>, | |||
| } | |||
| impl<T> WithSetup for VecConsumer<T> {} | |||
| impl<T> Consumer<T> for VecConsumer<T> | |||
| where | |||
| T: Send, | |||