Coverage Report

Created: 2025-10-28 08:03

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/find.rs
Line
Count
Source
1
use super::plumbing::*;
2
use super::*;
3
use std::sync::atomic::{AtomicBool, Ordering};
4
5
0
pub(super) fn find<I, P>(pi: I, find_op: P) -> Option<I::Item>
6
0
where
7
0
    I: ParallelIterator,
8
0
    P: Fn(&I::Item) -> bool + Sync,
9
{
10
0
    let found = AtomicBool::new(false);
11
0
    let consumer = FindConsumer::new(&find_op, &found);
12
0
    pi.drive_unindexed(consumer)
13
0
}
14
15
struct FindConsumer<'p, P> {
16
    find_op: &'p P,
17
    found: &'p AtomicBool,
18
}
19
20
impl<'p, P> FindConsumer<'p, P> {
21
0
    fn new(find_op: &'p P, found: &'p AtomicBool) -> Self {
22
0
        FindConsumer { find_op, found }
23
0
    }
24
}
25
26
impl<'p, T, P: 'p> Consumer<T> for FindConsumer<'p, P>
27
where
28
    T: Send,
29
    P: Fn(&T) -> bool + Sync,
30
{
31
    type Folder = FindFolder<'p, T, P>;
32
    type Reducer = FindReducer;
33
    type Result = Option<T>;
34
35
0
    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
36
0
        (self.split_off_left(), self, FindReducer)
37
0
    }
38
39
0
    fn into_folder(self) -> Self::Folder {
40
0
        FindFolder {
41
0
            find_op: self.find_op,
42
0
            found: self.found,
43
0
            item: None,
44
0
        }
45
0
    }
46
47
0
    fn full(&self) -> bool {
48
0
        self.found.load(Ordering::Relaxed)
49
0
    }
50
}
51
52
impl<'p, T, P: 'p> UnindexedConsumer<T> for FindConsumer<'p, P>
53
where
54
    T: Send,
55
    P: Fn(&T) -> bool + Sync,
56
{
57
0
    fn split_off_left(&self) -> Self {
58
0
        FindConsumer::new(self.find_op, self.found)
59
0
    }
60
61
0
    fn to_reducer(&self) -> Self::Reducer {
62
0
        FindReducer
63
0
    }
64
}
65
66
struct FindFolder<'p, T, P> {
67
    find_op: &'p P,
68
    found: &'p AtomicBool,
69
    item: Option<T>,
70
}
71
72
impl<'p, T, P> Folder<T> for FindFolder<'p, T, P>
73
where
74
    P: Fn(&T) -> bool + 'p,
75
{
76
    type Result = Option<T>;
77
78
0
    fn consume(mut self, item: T) -> Self {
79
0
        if (self.find_op)(&item) {
80
0
            self.found.store(true, Ordering::Relaxed);
81
0
            self.item = Some(item);
82
0
        }
83
0
        self
84
0
    }
85
86
0
    fn consume_iter<I>(mut self, iter: I) -> Self
87
0
    where
88
0
        I: IntoIterator<Item = T>,
89
    {
90
0
        fn not_full<T>(found: &AtomicBool) -> impl Fn(&T) -> bool + '_ {
91
0
            move |_| !found.load(Ordering::Relaxed)
92
0
        }
93
94
0
        self.item = iter
95
0
            .into_iter()
96
0
            // stop iterating if another thread has found something
97
0
            .take_while(not_full(self.found))
98
0
            .find(self.find_op);
99
0
        if self.item.is_some() {
100
0
            self.found.store(true, Ordering::Relaxed)
101
0
        }
102
0
        self
103
0
    }
104
105
0
    fn complete(self) -> Self::Result {
106
0
        self.item
107
0
    }
108
109
0
    fn full(&self) -> bool {
110
0
        self.found.load(Ordering::Relaxed)
111
0
    }
112
}
113
114
struct FindReducer;
115
116
impl<T> Reducer<Option<T>> for FindReducer {
117
0
    fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {
118
0
        left.or(right)
119
0
    }
120
}