Skip to main content

p3_maybe_rayon/
serial.rs

1use core::iter::{FlatMap, IntoIterator, Iterator};
2use core::marker::{Send, Sized, Sync};
3use core::ops::{Fn, FnOnce};
4use core::slice::{
5    Chunks, ChunksExact, ChunksExactMut, ChunksMut, RChunks, RChunksExact, RChunksExactMut,
6    RChunksMut, Split, SplitMut, Windows,
7};
8
9pub trait IntoParallelIterator {
10    type Iter: Iterator<Item = Self::Item>;
11    type Item: Send;
12
13    fn into_par_iter(self) -> Self::Iter;
14}
15impl<T: IntoIterator> IntoParallelIterator for T
16where
17    T::Item: Send,
18{
19    type Iter = T::IntoIter;
20    type Item = T::Item;
21
22    fn into_par_iter(self) -> Self::Iter {
23        self.into_iter()
24    }
25}
26
27pub trait IntoParallelRefIterator<'data> {
28    type Iter: Iterator<Item = Self::Item>;
29    type Item: Send + 'data;
30
31    fn par_iter(&'data self) -> Self::Iter;
32}
33
34impl<'data, I: 'data + ?Sized> IntoParallelRefIterator<'data> for I
35where
36    &'data I: IntoParallelIterator,
37{
38    type Iter = <&'data I as IntoParallelIterator>::Iter;
39    type Item = <&'data I as IntoParallelIterator>::Item;
40
41    fn par_iter(&'data self) -> Self::Iter {
42        self.into_par_iter()
43    }
44}
45
46pub trait IntoParallelRefMutIterator<'data> {
47    type Iter: Iterator<Item = Self::Item>;
48    type Item: Send + 'data;
49
50    fn par_iter_mut(&'data mut self) -> Self::Iter;
51}
52
53impl<'data, I: 'data + ?Sized> IntoParallelRefMutIterator<'data> for I
54where
55    &'data mut I: IntoParallelIterator,
56{
57    type Iter = <&'data mut I as IntoParallelIterator>::Iter;
58    type Item = <&'data mut I as IntoParallelIterator>::Item;
59
60    fn par_iter_mut(&'data mut self) -> Self::Iter {
61        self.into_par_iter()
62    }
63}
64
65pub trait ParallelSlice<T: Sync> {
66    /// Returns a plain slice, which is used to implement the rest of the
67    /// parallel methods.
68    fn as_parallel_slice(&self) -> &[T];
69
70    fn par_split<P>(&self, separator: P) -> Split<'_, T, P>
71    where
72        P: Fn(&T) -> bool + Sync + Send,
73    {
74        self.as_parallel_slice().split(separator)
75    }
76
77    fn par_windows(&self, window_size: usize) -> Windows<'_, T> {
78        self.as_parallel_slice().windows(window_size)
79    }
80
81    fn par_chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
82        self.as_parallel_slice().chunks(chunk_size)
83    }
84
85    fn par_chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
86        self.as_parallel_slice().chunks_exact(chunk_size)
87    }
88
89    fn par_rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
90        self.as_parallel_slice().rchunks(chunk_size)
91    }
92
93    fn par_rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
94        self.as_parallel_slice().rchunks_exact(chunk_size)
95    }
96}
97
98impl<T: Sync> ParallelSlice<T> for [T] {
99    #[inline]
100    fn as_parallel_slice(&self) -> &[T] {
101        self
102    }
103}
104
105pub trait ParallelSliceMut<T: Send> {
106    /// Returns a plain mutable slice, which is used to implement the rest of
107    /// the parallel methods.
108    fn as_parallel_slice_mut(&mut self) -> &mut [T];
109
110    fn par_split_mut<P>(&mut self, separator: P) -> SplitMut<'_, T, P>
111    where
112        P: Fn(&T) -> bool + Sync + Send,
113    {
114        self.as_parallel_slice_mut().split_mut(separator)
115    }
116
117    fn par_chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {
118        self.as_parallel_slice_mut().chunks_mut(chunk_size)
119    }
120
121    fn par_chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
122        self.as_parallel_slice_mut().chunks_exact_mut(chunk_size)
123    }
124
125    fn par_rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {
126        self.as_parallel_slice_mut().rchunks_mut(chunk_size)
127    }
128
129    fn par_rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
130        self.as_parallel_slice_mut().rchunks_exact_mut(chunk_size)
131    }
132}
133
134impl<T: Send> ParallelSliceMut<T> for [T] {
135    #[inline]
136    fn as_parallel_slice_mut(&mut self) -> &mut [T] {
137        self
138    }
139}
140
141pub trait ParIterExt: Iterator {
142    /// Serially, this returns the first matching item, unlike rayon's `find_any`, which may
143    /// return any matching item found by any thread.
144    fn find_any<P>(self, predicate: P) -> Option<Self::Item>
145    where
146        P: Fn(&Self::Item) -> bool + Sync + Send;
147
148    fn find_map_any<P, R>(self, predicate: P) -> Option<R>
149    where
150        P: Fn(Self::Item) -> Option<R> + Sync + Send;
151
152    fn flat_map_iter<U, F>(self, map_op: F) -> FlatMap<Self, U, F>
153    where
154        Self: Sized,
155        U: IntoIterator,
156        F: Fn(Self::Item) -> U;
157
158    /// Serially, `init` is called once and the single state is reused across every item,
159    /// unlike rayon's `for_each_init`, which calls `init` once per split.
160    fn for_each_init<OP, INIT, T>(self, init: INIT, op: OP)
161    where
162        Self: Sized,
163        OP: Fn(&mut T, Self::Item) + Sync + Send,
164        INIT: Fn() -> T + Sync + Send;
165}
166
167impl<I: Iterator> ParIterExt for I {
168    fn find_any<P>(mut self, predicate: P) -> Option<Self::Item>
169    where
170        P: Fn(&Self::Item) -> bool + Sync + Send,
171    {
172        self.find(predicate)
173    }
174
175    fn find_map_any<P, R>(mut self, predicate: P) -> Option<R>
176    where
177        P: Fn(Self::Item) -> Option<R> + Sync + Send,
178    {
179        self.find_map(predicate)
180    }
181
182    fn flat_map_iter<U, F>(self, map_op: F) -> FlatMap<Self, U, F>
183    where
184        Self: Sized,
185        U: IntoIterator,
186        F: Fn(Self::Item) -> U,
187    {
188        self.flat_map(map_op)
189    }
190
191    fn for_each_init<OP, INIT, T>(self, init: INIT, op: OP)
192    where
193        Self: Sized,
194        OP: Fn(&mut T, Self::Item) + Sync + Send,
195        INIT: Fn() -> T + Sync + Send,
196    {
197        let mut state = init();
198        self.for_each(|item| op(&mut state, item));
199    }
200}
201
202/// Runs `oper_a` then `oper_b` in sequence, unlike rayon's `join`, which may run them
203/// concurrently on separate threads.
204pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
205where
206    A: FnOnce() -> RA,
207    B: FnOnce() -> RB,
208{
209    let result_a = oper_a();
210    let result_b = oper_b();
211    (result_a, result_b)
212}
213
214/// Always 1: there is only one thread of execution in a serial build.
215pub const fn current_num_threads() -> usize {
216    1
217}