Skip to main content

orx_parallel/infallible/
par_iter.rs

1use crate::infallible::Xap;
2use crate::infallible::XapIter;
3use crate::infallible::par_core::ParCore;
4use crate::infallible::par_runner::ParRunnerInfallible;
5use crate::infallible::xap::{FilMapOf, FilOf, FlatMapOf, FlattenOf, InsOf, MapOf};
6use crate::parameters::{ChunkSize, IterationOrder, NumThreads, Params};
7use crate::runner::{DefaultRunner, ParRunner};
8use crate::sizes::Size;
9use crate::{Par, ParExtend};
10use orx_concurrent_iter::ConcurrentIter;
11
12/// Parallel iterator.
13pub struct ParIter<I, X, R = DefaultRunner>
14where
15    I: ConcurrentIter,
16    X: Xap<I = I::Item>,
17    R: ParRunner,
18{
19    iter: I,
20    xap: X,
21    exe: R,
22    params: Params,
23}
24
25impl<I, X, R> ParIter<I, X, R>
26where
27    I: ConcurrentIter,
28    X: Xap<I = I::Item>,
29    R: ParRunner,
30{
31    pub(crate) fn new(iter: I, xap: X, exe: R, params: Params) -> Self {
32        Self {
33            iter,
34            xap,
35            exe,
36            params,
37        }
38    }
39
40    pub(super) fn with_xap<Y: Xap<I = I::Item>>(self, xap: Y) -> ParIter<I, Y, R> {
41        ParIter::new(self.iter, xap, self.exe, self.params)
42    }
43}
44
45impl<I, X, R> IntoIterator for ParIter<I, X, R>
46where
47    I: ConcurrentIter,
48    X: Xap<I = I::Item>,
49    R: ParRunner,
50{
51    type Item = X::O;
52
53    type IntoIter = XapIter<I::SequentialIter, X>;
54
55    fn into_iter(self) -> Self::IntoIter {
56        XapIter::new(self.iter.into_seq_iter(), self.xap)
57    }
58}
59
60impl<I, X, R> ParCore for ParIter<I, X, R>
61where
62    I: ConcurrentIter,
63    X: Xap<I = I::Item>,
64    R: ParRunner,
65{
66    type Runner = R;
67
68    type Input = I;
69
70    type Xap = X;
71
72    fn destruct(self) -> (Self::Input, Self::Xap, Self::Runner, Params) {
73        (self.iter, self.xap, self.exe, self.params)
74    }
75}
76
77impl<I, X, R> Par for ParIter<I, X, R>
78where
79    I: ConcurrentIter,
80    X: Xap<I = I::Item>,
81    R: ParRunner,
82{
83    // configuration
84
85    fn runner<Q: ParRunner>(
86        self,
87        runner: Q,
88    ) -> impl Par<Item = Self::Item, Xap = Self::Xap, Input = Self::Input> {
89        let (iter, xap, _, params) = self.destruct();
90        ParIter::new(iter, xap, runner, params)
91    }
92
93    #[cfg(feature = "std")]
94    fn runner_with_diagnostics(
95        self,
96    ) -> impl Par<Item = Self::Item, Xap = Self::Xap, Input = Self::Input> {
97        let (iter, xap, exe, params) = self.destruct();
98        ParIter::new(iter, xap, exe.with_diagnostics(), params)
99    }
100
101    fn num_threads(mut self, num_threads: impl Into<NumThreads>) -> Self {
102        self.params = self.params.with_num_threads(num_threads);
103        self
104    }
105
106    fn chunk_size(mut self, chunk_size: impl Into<ChunkSize>) -> Self {
107        self.params = self.params.with_chunk_size(chunk_size);
108        self
109    }
110
111    fn iteration_order(mut self, collect: IterationOrder) -> Self {
112        self.params = self.params.with_collect_ordering(collect);
113        self
114    }
115
116    // transformations
117
118    fn map<Q, H>(
119        self,
120        h: H,
121    ) -> impl Par<Item = Q, Xap = MapOf<Self::Xap, Q, H>, Input = Self::Input>
122    where
123        H: Fn(X::O) -> Q + Copy + Send,
124    {
125        let xap = self.xap.map(h);
126        self.with_xap(xap)
127    }
128
129    fn inspect<H>(
130        self,
131        h: H,
132    ) -> impl Par<Item = Self::Item, Xap = InsOf<Self::Xap, H>, Input = Self::Input>
133    where
134        H: Fn(&Self::Item) + Copy + Send,
135    {
136        let xap = self.xap.inspect(h);
137        self.with_xap(xap)
138    }
139
140    fn filter<H>(
141        self,
142        h: H,
143    ) -> impl Par<Item = Self::Item, Xap = FilOf<Self::Xap, H>, Input = Self::Input>
144    where
145        H: Fn(&Self::Item) -> bool + Copy + Send,
146    {
147        let xap = self.xap.filter(h);
148        self.with_xap(xap)
149    }
150
151    fn filter_map<Q, H>(
152        self,
153        h: H,
154    ) -> impl Par<Item = Q, Xap = FilMapOf<Self::Xap, Q, H>, Input = Self::Input>
155    where
156        H: Fn(Self::Item) -> Option<Q> + Copy + Send,
157    {
158        let xap = self.xap.filter_map(h);
159        self.with_xap(xap)
160    }
161
162    fn flat_map<V, H>(
163        self,
164        h: H,
165    ) -> impl Par<Item = V::Item, Xap = FlatMapOf<Self::Xap, V, H>, Input = Self::Input>
166    where
167        V: IntoIterator,
168        H: Fn(Self::Item) -> V + Copy + Send,
169    {
170        let xap = self.xap.flat_map(h);
171        self.with_xap(xap)
172    }
173
174    fn flatten(
175        self,
176    ) -> impl Par<
177        Item = <Self::Item as IntoIterator>::Item,
178        Xap = FlattenOf<Self::Xap>,
179        Input = Self::Input,
180    >
181    where
182        Self::Item: IntoIterator,
183    {
184        let xap = self.xap.flatten();
185        self.with_xap(xap)
186    }
187
188    // get
189
190    fn size_hint(&self) -> (usize, Option<usize>) {
191        <X::Size as Size>::transformed_size_hint(self.iter.size_hint())
192    }
193
194    // compute
195
196    fn first(self) -> Option<X::O>
197    where
198        X::O: Send,
199    {
200        let (iter, x, mut exe, params) = self.destruct();
201        match params.iteration_order {
202            IterationOrder::Ordered => exe.next(params, iter, x).map(|x| x.val),
203            IterationOrder::Arbitrary => exe.next_any(params, iter, x),
204        }
205    }
206
207    fn reduce<F>(self, f: F) -> Option<X::O>
208    where
209        F: Fn(X::O, X::O) -> X::O + Send + Copy,
210        X::O: Send,
211    {
212        let (iter, x, mut exe, params) = self.destruct();
213        exe.reduce(params, iter, x, f)
214    }
215
216    fn collect_into<P>(self, dst: &mut P)
217    where
218        P: ParExtend<X::O>,
219        X::O: Send,
220    {
221        let (iter, x, mut exe, params) = self.destruct();
222        match params.iteration_order {
223            IterationOrder::Ordered => exe.collect(params, iter, x, dst),
224            IterationOrder::Arbitrary => exe.collect_arb(params, iter, x, dst),
225        }
226    }
227}