Coverage Report

Created: 2026-01-13 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}