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