/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 | | } |