binius_utils/rayon/
mod.rs

1// Copyright 2024-2025 Irreducible Inc.
2//
3// The code is initially based on `maybe-rayon` crate, https://github.com/shssoichiro/maybe-rayon
4// Original: Copyright (c) 2021 Joshua Holmer
5// Licensed under MIT License
6
7//! This crate provides a subset of the `rayon` API to allow conditional
8//! compilation without `rayon`.
9//! This is useful for profiling single-threaded code, as it simplifies call stacks significantly.
10//! The initial code was taken from the `maybe-rayon` crate, but many changes were made to
11//! support the usage of `ParallelIterator` and `IndexedParallelIterator` methods, which have
12//! different signatures from `std::iter::Iterator`. Some of these changes may be potentially
13//! backward-incompatible, and given the absence of tests in the original crate, it is very unlikely
14//! that it is possible to commit the changes back to the original crate.
15
16cfg_if::cfg_if! {
17	if #[cfg(any(not(feature = "rayon"), all(target_arch="wasm32", not(target_feature = "atomics"))))] {
18		use std::marker::PhantomData;
19
20		pub mod iter;
21		pub mod slice;
22
23		pub mod prelude {
24			pub use super::{iter::*, slice::*};
25		}
26
27		#[derive(Default)]
28		pub struct ThreadPoolBuilder();
29		impl ThreadPoolBuilder {
30			#[inline(always)]
31			pub const fn new() -> Self {
32				Self()
33			}
34
35			#[inline(always)]
36			pub const fn build(self) -> Result<ThreadPool, ::core::convert::Infallible> {
37				Ok(ThreadPool())
38			}
39
40			#[inline(always)]
41			pub const fn num_threads(self, _num_threads: usize) -> Self {
42				Self()
43			}
44
45			#[inline(always)]
46			pub const fn use_current_thread(self) -> Self {
47				Self()
48			}
49
50			#[inline(always)]
51			pub const fn build_global(self) -> Result<(), ThreadPoolBuildError> {
52				Ok(())
53			}
54		}
55
56		#[derive(Debug)]
57		pub struct ThreadPool();
58		impl ThreadPool {
59			#[inline(always)]
60			pub fn install<OP, R>(&self, op: OP) -> R
61			where
62				OP: FnOnce() -> R + Send,
63				R: Send,
64			{
65				op()
66			}
67		}
68
69		#[derive(Debug, Default)]
70		pub struct ThreadPoolBuildError;
71		impl std::fmt::Display for ThreadPoolBuildError {
72			fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73				write!(f, "ThreadPoolBuildError")
74			}
75		}
76		impl std::error::Error for ThreadPoolBuildError {
77			fn description(&self) -> &str {
78				"Error building thread pool"
79			}
80		}
81
82		#[inline(always)]
83		pub const fn current_num_threads() -> usize {
84			1
85		}
86
87		#[inline(always)]
88		pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
89		where
90			A: FnOnce() -> RA + Send,
91			B: FnOnce() -> RB + Send,
92			RA: Send,
93			RB: Send,
94		{
95			(oper_a(), oper_b())
96		}
97
98		pub struct Scope<'scope> {
99			#[allow(clippy::type_complexity)]
100			marker: PhantomData<Box<dyn FnOnce(&Scope<'scope>) + Send + Sync + 'scope>>,
101		}
102
103		impl<'scope> Scope<'scope> {
104			#[inline(always)]
105			pub fn spawn<BODY>(&self, body: BODY)
106			where
107				BODY: FnOnce(&Self) + Send + 'scope,
108			{
109				body(self)
110			}
111		}
112
113		#[inline(always)]
114		pub fn scope<'scope, OP, R>(op: OP) -> R
115		where
116			OP: for<'s> FnOnce(&'s Scope<'scope>) -> R + 'scope + Send,
117			R: Send,
118		{
119			op(&Scope {
120				marker: PhantomData,
121			})
122		}
123	} else {
124		pub use rayon::*;
125	}
126}
127
128pub mod config;