strided_basic/
exec_context.rs1use core::num::NonZeroUsize;
8
9use crate::{with_execution_policy, ExecutionPolicy, Result, StridedError};
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17pub struct ExecContext {
18 kind: ExecContextKind,
19}
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22enum ExecContextKind {
23 Serial,
24 MaxThreads(NonZeroUsize),
25 Ambient,
26}
27
28impl ExecContext {
29 #[inline]
31 pub const fn serial() -> Self {
32 Self {
33 kind: ExecContextKind::Serial,
34 }
35 }
36
37 #[inline]
39 pub fn max_threads(max_threads: usize) -> Result<Self> {
40 match NonZeroUsize::new(max_threads) {
41 Some(max_threads) => Ok(Self {
42 kind: ExecContextKind::MaxThreads(max_threads),
43 }),
44 None => Err(StridedError::InvalidThreadBudget { max_threads }),
45 }
46 }
47
48 #[inline]
54 pub const fn ambient() -> Self {
55 Self {
56 kind: ExecContextKind::Ambient,
57 }
58 }
59
60 #[inline]
62 pub fn is_serial(&self) -> bool {
63 matches!(self.kind, ExecContextKind::Serial)
64 }
65
66 #[inline]
68 pub fn is_ambient(&self) -> bool {
69 matches!(self.kind, ExecContextKind::Ambient)
70 }
71
72 #[inline]
74 pub fn max_threads_limit(&self) -> Option<NonZeroUsize> {
75 match self.kind {
76 ExecContextKind::MaxThreads(max_threads) => Some(max_threads),
77 ExecContextKind::Serial | ExecContextKind::Ambient => None,
78 }
79 }
80
81 #[inline]
82 pub fn run<R>(&self, operation: impl FnOnce() -> R) -> R {
91 match self.kind {
92 ExecContextKind::Serial => {
93 with_execution_policy(ExecutionPolicy::Sequential, operation)
94 }
95 ExecContextKind::MaxThreads(max_threads) => {
96 with_execution_policy(ExecutionPolicy::Rayon { max_threads }, operation)
97 }
98 ExecContextKind::Ambient => operation(),
99 }
100 }
101}
102
103impl Default for ExecContext {
104 #[inline]
105 fn default() -> Self {
106 Self::serial()
107 }
108}
109
110#[cfg(test)]
111#[path = "exec_context/tests/tests.rs"]
112mod tests;