par_iter/
lib.rs

1#![deny(missing_debug_implementations)]
2#![deny(missing_docs)]
3#![deny(unreachable_pub)]
4#![warn(rust_2018_idioms)]
5#![allow(clippy::all)]
6
7//! Fork of `rayon` to use parallel iterators with chili. See [`par-core`](https://docs.rs/par-core) for
8//! more details.
9//!
10//! ---
11//!
12//! Rayon is a data-parallelism library that makes it easy to convert sequential
13//! computations into parallel.
14//!
15//! It is lightweight and convenient for introducing parallelism into existing
16//! code. It guarantees data-race free executions and takes advantage of
17//! parallelism when sensible, based on work-load at runtime.
18//!
19//! # How to use Rayon
20//!
21//! There are two ways to use Rayon:
22//!
23//! - **High-level parallel constructs** are the simplest way to use Rayon and
24//!   also typically the most efficient.
25//!   - [Parallel iterators][iter module] make it easy to convert a sequential
26//!     iterator to execute in parallel.
27//!     - The [`ParallelIterator`] trait defines general methods for all
28//!       parallel iterators.
29//!     - The [`IndexedParallelIterator`] trait adds methods for iterators that
30//!       support random access.
31//!   - The [`par_sort`] method sorts `&mut [T]` slices (or vectors) in
32//!     parallel.
33//!   - [`par_extend`] can be used to efficiently grow collections with items
34//!     produced by a parallel iterator.
35//! - **Custom tasks** let you divide your work into parallel tasks yourself.
36//!   - [`join`] is used to subdivide a task into two pieces.
37//!   - [`scope`] creates a scope within which you can create any number of
38//!     parallel tasks.
39//!   - [`ThreadPoolBuilder`] can be used to create your own thread pools or
40//!     customize the global one.
41//!
42//! [iter module]: iter/index.html
43//! [`join`]: fn.join.html
44//! [`scope`]: fn.scope.html
45//! [`par_sort`]: slice/trait.ParallelSliceMut.html#method.par_sort
46//! [`par_extend`]: iter/trait.ParallelExtend.html#tymethod.par_extend
47//! [`ThreadPoolBuilder`]: struct.ThreadPoolBuilder.html
48//!
49//! # Basic usage and the Rayon prelude
50//!
51//! First, you will need to add `rayon` to your `Cargo.toml`.
52//!
53//! Next, to use parallel iterators or the other high-level methods,
54//! you need to import several traits. Those traits are bundled into
55//! the module [`par_iter::prelude`]. It is recommended that you import
56//! all of these traits at once by adding `use par_iter::prelude::*` at
57//! the top of each module that uses Rayon methods.
58//!
59//! These traits give you access to the `par_iter` method which provides
60//! parallel implementations of many iterative functions such as [`map`],
61//! [`for_each`], [`filter`], [`fold`], and [more].
62//!
63//! [`par_iter::prelude`]: prelude/index.html
64//! [`map`]: iter/trait.ParallelIterator.html#method.map
65//! [`for_each`]: iter/trait.ParallelIterator.html#method.for_each
66//! [`filter`]: iter/trait.ParallelIterator.html#method.filter
67//! [`fold`]: iter/trait.ParallelIterator.html#method.fold
68//! [more]: iter/trait.ParallelIterator.html#provided-methods
69//! [`ParallelIterator`]: iter/trait.ParallelIterator.html
70//! [`IndexedParallelIterator`]: iter/trait.IndexedParallelIterator.html
71//!
72//! # Crate Layout
73//!
74//! Rayon extends many of the types found in the standard library with
75//! parallel iterator implementations. The modules in the `rayon`
76//! crate mirror [`std`] itself: so, e.g., the `option` module in
77//! Rayon contains parallel iterators for the `Option` type, which is
78//! found in [the `option` module of `std`]. Similarly, the
79//! `collections` module in Rayon offers parallel iterator types for
80//! [the `collections` from `std`]. You will rarely need to access
81//! these submodules unless you need to name iterator types
82//! explicitly.
83//!
84//! [the `option` module of `std`]: https://doc.rust-lang.org/std/option/index.html
85//! [the `collections` from `std`]: https://doc.rust-lang.org/std/collections/index.html
86//! [`std`]: https://doc.rust-lang.org/std/
87//!
88//! # Targets without threading
89//!
90//! Rayon has limited support for targets without `std` threading
91//! implementations. See the [`rayon_core`] documentation for more information
92//! about its global fallback.
93//!
94//! # Other questions?
95//!
96//! See [the Rayon FAQ][faq].
97//!
98//! [faq]: https://github.com/rayon-rs/rayon/blob/main/FAQ.md
99
100use std::{num::NonZero, sync::LazyLock};
101
102#[macro_use]
103mod delegate;
104
105#[macro_use]
106mod private;
107
108mod split_producer;
109
110pub mod array;
111pub mod collections;
112pub mod iter;
113pub mod option;
114pub mod prelude;
115pub mod range;
116pub mod range_inclusive;
117pub mod result;
118pub mod slice;
119pub mod str;
120pub mod string;
121pub mod vec;
122
123mod math;
124mod par_either;
125
126mod compile_fail;
127
128/// We need to transmit raw pointers across threads. It is possible to do this
129/// without any unsafe code by converting pointers to usize or to AtomicPtr<T>
130/// then back to a raw pointer for use. We prefer this approach because code
131/// that uses this type is more explicit.
132///
133/// Unsafe code is still required to dereference the pointer, so this type is
134/// not unsound on its own, although it does partly lift the unconditional
135/// !Send and !Sync on raw pointers. As always, dereference with care.
136struct SendPtr<T>(*mut T);
137
138// SAFETY: !Send for raw pointers is not for safety, just as a lint
139unsafe impl<T: Send> Send for SendPtr<T> {}
140
141// SAFETY: !Sync for raw pointers is not for safety, just as a lint
142unsafe impl<T: Send> Sync for SendPtr<T> {}
143
144impl<T> SendPtr<T> {
145    // Helper to avoid disjoint captures of `send_ptr.0`
146    fn get(self) -> *mut T {
147        self.0
148    }
149}
150
151// Implement Clone without the T: Clone bound from the derive
152impl<T> Clone for SendPtr<T> {
153    fn clone(&self) -> Self {
154        *self
155    }
156}
157
158// Implement Copy without the T: Copy bound from the derive
159impl<T> Copy for SendPtr<T> {}
160
161fn current_num_threads() -> usize {
162    static CACHE: LazyLock<usize> = LazyLock::new(|| {
163        std::thread::available_parallelism()
164            .unwrap_or(NonZero::new(1).unwrap())
165            .into()
166    });
167
168    *CACHE
169}