/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rayon-1.11.0/src/iter/blocks.rs
Line | Count | Source |
1 | | use super::plumbing::*; |
2 | | use super::*; |
3 | | |
4 | | struct BlocksCallback<S, C> { |
5 | | sizes: S, |
6 | | consumer: C, |
7 | | len: usize, |
8 | | } |
9 | | |
10 | | impl<T, S, C> ProducerCallback<T> for BlocksCallback<S, C> |
11 | | where |
12 | | C: UnindexedConsumer<T>, |
13 | | S: Iterator<Item = usize>, |
14 | | { |
15 | | type Output = C::Result; |
16 | | |
17 | 0 | fn callback<P: Producer<Item = T>>(mut self, mut producer: P) -> Self::Output { |
18 | 0 | let mut remaining_len = self.len; |
19 | 0 | let mut consumer = self.consumer; |
20 | | |
21 | | // we need a local variable for the accumulated results |
22 | | // we call the reducer's identity by splitting at 0 |
23 | 0 | let (left_consumer, right_consumer, _) = consumer.split_at(0); |
24 | 0 | let mut leftmost_res = left_consumer.into_folder().complete(); |
25 | 0 | consumer = right_consumer; |
26 | | |
27 | | // now we loop on each block size |
28 | 0 | while remaining_len > 0 && !consumer.full() { |
29 | 0 | // we compute the next block's size |
30 | 0 | let size = self.sizes.next().unwrap_or(usize::MAX); |
31 | 0 | let capped_size = remaining_len.min(size); |
32 | 0 | remaining_len -= capped_size; |
33 | 0 |
|
34 | 0 | // split the producer |
35 | 0 | let (left_producer, right_producer) = producer.split_at(capped_size); |
36 | 0 | producer = right_producer; |
37 | 0 |
|
38 | 0 | // split the consumer |
39 | 0 | let (left_consumer, right_consumer, _) = consumer.split_at(capped_size); |
40 | 0 | consumer = right_consumer; |
41 | 0 |
|
42 | 0 | leftmost_res = consumer.to_reducer().reduce( |
43 | 0 | leftmost_res, |
44 | 0 | bridge_producer_consumer(capped_size, left_producer, left_consumer), |
45 | 0 | ); |
46 | 0 | } |
47 | 0 | leftmost_res |
48 | 0 | } |
49 | | } |
50 | | |
51 | | /// `ExponentialBlocks` is a parallel iterator that consumes itself as a sequence |
52 | | /// of parallel blocks of increasing sizes (exponentially). |
53 | | /// |
54 | | /// This struct is created by the [`by_exponential_blocks()`] method on [`IndexedParallelIterator`] |
55 | | /// |
56 | | /// [`by_exponential_blocks()`]: IndexedParallelIterator::by_exponential_blocks() |
57 | | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] |
58 | | #[derive(Debug, Clone)] |
59 | | pub struct ExponentialBlocks<I> { |
60 | | base: I, |
61 | | } |
62 | | |
63 | | impl<I> ExponentialBlocks<I> { |
64 | 0 | pub(super) fn new(base: I) -> Self { |
65 | 0 | Self { base } |
66 | 0 | } |
67 | | } |
68 | | |
69 | | impl<I> ParallelIterator for ExponentialBlocks<I> |
70 | | where |
71 | | I: IndexedParallelIterator, |
72 | | { |
73 | | type Item = I::Item; |
74 | | |
75 | 0 | fn drive_unindexed<C>(self, consumer: C) -> C::Result |
76 | 0 | where |
77 | 0 | C: UnindexedConsumer<Self::Item>, |
78 | | { |
79 | 0 | let first = crate::current_num_threads(); |
80 | 0 | let callback = BlocksCallback { |
81 | 0 | consumer, |
82 | 0 | sizes: std::iter::successors(Some(first), exponential_size), |
83 | 0 | len: self.base.len(), |
84 | 0 | }; |
85 | 0 | self.base.with_producer(callback) |
86 | 0 | } |
87 | | } |
88 | | |
89 | 0 | fn exponential_size(size: &usize) -> Option<usize> { |
90 | 0 | Some(size.saturating_mul(2)) |
91 | 0 | } |
92 | | |
93 | | /// `UniformBlocks` is a parallel iterator that consumes itself as a sequence |
94 | | /// of parallel blocks of constant sizes. |
95 | | /// |
96 | | /// This struct is created by the [`by_uniform_blocks()`] method on [`IndexedParallelIterator`] |
97 | | /// |
98 | | /// [`by_uniform_blocks()`]: IndexedParallelIterator::by_uniform_blocks() |
99 | | #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] |
100 | | #[derive(Debug, Clone)] |
101 | | pub struct UniformBlocks<I> { |
102 | | base: I, |
103 | | block_size: usize, |
104 | | } |
105 | | |
106 | | impl<I> UniformBlocks<I> { |
107 | 0 | pub(super) fn new(base: I, block_size: usize) -> Self { |
108 | 0 | Self { base, block_size } |
109 | 0 | } |
110 | | } |
111 | | |
112 | | impl<I> ParallelIterator for UniformBlocks<I> |
113 | | where |
114 | | I: IndexedParallelIterator, |
115 | | { |
116 | | type Item = I::Item; |
117 | | |
118 | 0 | fn drive_unindexed<C>(self, consumer: C) -> C::Result |
119 | 0 | where |
120 | 0 | C: UnindexedConsumer<Self::Item>, |
121 | | { |
122 | 0 | let callback = BlocksCallback { |
123 | 0 | consumer, |
124 | 0 | sizes: std::iter::repeat(self.block_size), |
125 | 0 | len: self.base.len(), |
126 | 0 | }; |
127 | 0 | self.base.with_producer(callback) |
128 | 0 | } |
129 | | } |