binius_maybe_rayon/
lib.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
108
109
110
111
112
113
// Copyright 2025 Irreducible Inc.
// The code is initially based on `maybe-rayon` crate, https://github.com/shssoichiro/maybe-rayon

//! This crate provides a subset of the `rayon` API to allow conditional
//! compilation without `rayon`.
//! This is useful for profiling single-threaded code, as it simplifies call stacks significantly.
//! The initial code was taken from the `maybe-rayon` crate, but many changes were made to
//! support the usage of `ParallelIterator` and `IndexedParallelIterator` methods, which have different
//! signatures from `std::iter::Iterator`. Some of these changes may be potentially backward-incompatible,
//! and given the absence of tests in the original crate, it is very unlikely that it is possible to
//! commit the changes back to the original crate.

cfg_if::cfg_if! {
	if #[cfg(any(not(feature = "rayon"), all(target_arch="wasm32", not(target_feature = "atomics"))))] {
		use std::marker::PhantomData;

		pub mod iter;
		pub mod slice;

		pub mod prelude {
			pub use super::{iter::*, slice::*};
		}

		#[derive(Default)]
		pub struct ThreadPoolBuilder();
		impl ThreadPoolBuilder {
			#[inline(always)]
			pub const fn new() -> Self {
				Self()
			}

			#[inline(always)]
			pub const fn build(self) -> Result<ThreadPool, ::core::convert::Infallible> {
				Ok(ThreadPool())
			}

			#[inline(always)]
			pub const fn num_threads(self, _num_threads: usize) -> Self {
				Self()
			}
		}

		#[derive(Debug)]
		pub struct ThreadPool();
		impl ThreadPool {
			#[inline(always)]
			pub fn install<OP, R>(&self, op: OP) -> R
			where
				OP: FnOnce() -> R + Send,
				R: Send,
			{
				op()
			}
		}

		#[derive(Debug, Default)]
		pub struct ThreadPoolBuildError;
		impl std::fmt::Display for ThreadPoolBuildError {
			fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
				write!(f, "ThreadPoolBuildError")
			}
		}
		impl std::error::Error for ThreadPoolBuildError {
			fn description(&self) -> &str {
				"Error building thread pool"
			}
		}

		#[inline(always)]
		pub const fn current_num_threads() -> usize {
			1
		}

		#[inline(always)]
		pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
		where
			A: FnOnce() -> RA + Send,
			B: FnOnce() -> RB + Send,
			RA: Send,
			RB: Send,
		{
			(oper_a(), oper_b())
		}

		pub struct Scope<'scope> {
			#[allow(clippy::type_complexity)]
			marker: PhantomData<Box<dyn FnOnce(&Scope<'scope>) + Send + Sync + 'scope>>,
		}

		impl<'scope> Scope<'scope> {
			#[inline(always)]
			pub fn spawn<BODY>(&self, body: BODY)
			where
				BODY: FnOnce(&Self) + Send + 'scope,
			{
				body(self)
			}
		}

		#[inline(always)]
		pub fn scope<'scope, OP, R>(op: OP) -> R
		where
			OP: for<'s> FnOnce(&'s Scope<'scope>) -> R + 'scope + Send,
			R: Send,
		{
			op(&Scope {
				marker: PhantomData,
			})
		}
	} else {
		pub use rayon::*;
	}
}