forked from rayon-rs/rayon
-
Notifications
You must be signed in to change notification settings - Fork 6
/
find.rs
107 lines (87 loc) · 2.57 KB
/
find.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::sync::atomic::{AtomicBool, Ordering};
use super::*;
use super::len::*;
use super::internal::*;
pub fn find<PAR_ITER, FIND_OP>(pi: PAR_ITER, find_op: FIND_OP) -> Option<PAR_ITER::Item>
where PAR_ITER: ParallelIterator,
FIND_OP: Fn(&PAR_ITER::Item) -> bool + Sync,
{
let found = AtomicBool::new(false);
let consumer = FindConsumer::new(&find_op, &found);
pi.drive_unindexed(consumer)
}
struct FindConsumer<'f, FIND_OP: 'f> {
find_op: &'f FIND_OP,
found: &'f AtomicBool,
}
impl<'f, FIND_OP> FindConsumer<'f, FIND_OP> {
fn new(find_op: &'f FIND_OP, found: &'f AtomicBool) -> Self {
FindConsumer {
find_op: find_op,
found: found,
}
}
}
impl<'f, ITEM, FIND_OP: 'f> Consumer<ITEM> for FindConsumer<'f, FIND_OP>
where ITEM: Send, FIND_OP: Fn(&ITEM) -> bool + Sync,
{
type Folder = FindFolder<'f, ITEM, FIND_OP>;
type Reducer = FindReducer;
type Result = Option<ITEM>;
fn cost(&mut self, cost: f64) -> f64 {
// This isn't quite right, as we will do more than O(n) reductions, but whatever.
cost * FUNC_ADJUSTMENT
}
fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
(self.split_off(), self, FindReducer)
}
fn into_folder(self) -> Self::Folder {
FindFolder {
find_op: self.find_op,
found: self.found,
item: None,
}
}
fn full(&self) -> bool {
self.found.load(Ordering::Relaxed)
}
}
impl<'f, ITEM, FIND_OP: 'f> UnindexedConsumer<ITEM> for FindConsumer<'f, FIND_OP>
where ITEM: Send, FIND_OP: Fn(&ITEM) -> bool + Sync,
{
fn split_off(&self) -> Self {
FindConsumer::new(self.find_op, self.found)
}
fn to_reducer(&self) -> Self::Reducer {
FindReducer
}
}
struct FindFolder<'f, ITEM, FIND_OP: 'f> {
find_op: &'f FIND_OP,
found: &'f AtomicBool,
item: Option<ITEM>,
}
impl<'f, ITEM, FIND_OP> Folder<ITEM> for FindFolder<'f, ITEM, FIND_OP>
where FIND_OP: Fn(&ITEM) -> bool + 'f
{
type Result = Option<ITEM>;
fn consume(mut self, item: ITEM) -> Self {
if (self.find_op)(&item) {
self.found.store(true, Ordering::Relaxed);
self.item = Some(item);
}
self
}
fn complete(self) -> Self::Result {
self.item
}
fn full(&self) -> bool {
self.found.load(Ordering::Relaxed)
}
}
struct FindReducer;
impl<ITEM> Reducer<Option<ITEM>> for FindReducer {
fn reduce(self, left: Option<ITEM>, right: Option<ITEM>) -> Option<ITEM> {
left.or(right)
}
}