Skip to main content

orx_parallel/pools/pool_impl/
once.rs

1use crate::NumThreads;
2use crate::pools::scope::Scope;
3use crate::pools::{ThreadPool, env::max_num_threads_by_env_and_resource};
4use core::num::NonZeroUsize;
5
6/// A _one-time-use_ thread pool.
7///
8/// This is not an actual thread pool, rather a configuration on number of threads to be spawned.
9/// Desired threads will be spawned just before the computation starts and will be released right after.
10/// Therefore, it may be considered as a _one-time-use_ thread pool.
11///
12/// `OncePool` is used when the `transient-pool` feature is enabled.
13/// In this configuration, "orx-parallel" does not create and hold on to a persistent thread pool.
14#[derive(Clone, Copy, Debug)]
15pub struct OncePool {
16    num_threads: NonZeroUsize,
17}
18
19impl Default for OncePool {
20    fn default() -> Self {
21        Self::new(NumThreads::Auto)
22    }
23}
24
25unsafe impl Sync for OncePool {}
26
27impl OncePool {
28    /// Assumes (*) a thread pool of `num_threads` threads.
29    ///
30    /// Note that, this desired number of threads can be overwritten by the following:
31    /// - if the system has `n < num_threads` available threads, computation will use `n` threads.
32    /// - if ORX_NUM_THREADS environment variable exists with value `m < num_threads`,
33    ///   computation will use `m` threads.
34    ///
35    /// (*) This is not an actual thread pool, rather a configuration on number of threads to be spawned.
36    /// Desired threads will be spawned just before the computation starts and will be released right after.
37    /// Therefore, it may be considered as a _one-time-use_ thread pool.
38    pub fn new(num_threads: impl Into<NumThreads>) -> Self {
39        let num_threads = match num_threads.into() {
40            NumThreads::Auto => max_num_threads_by_env_and_resource(),
41            NumThreads::Max(n) => max_num_threads_by_env_and_resource().min(n),
42        };
43        Self { num_threads }
44    }
45}
46
47impl<'s, 'env, 'scope> Scope<'s, 'env, 'scope> for &'s std::thread::Scope<'s, 'env> {
48    fn run<W>(self, work: W)
49    where
50        'scope: 's,
51        'env: 'scope + 's,
52        W: FnOnce() + Send + 'scope + 'env,
53    {
54        self.spawn(work);
55    }
56}
57
58impl ThreadPool for OncePool {
59    type ScopeRef<'s, 'env, 'scope>
60        = &'s std::thread::Scope<'s, 'env>
61    where
62        'scope: 's,
63        'env: 'scope + 's;
64
65    fn max_num_threads(&self) -> NonZeroUsize {
66        self.num_threads
67    }
68
69    fn scope<'env, 'scope, F>(&'env self, f: F)
70    where
71        'env: 'scope,
72        for<'s> F: FnOnce(&'s std::thread::Scope<'s, 'env>) + Send,
73    {
74        std::thread::scope(f)
75    }
76}
77
78impl ThreadPool for &OncePool {
79    type ScopeRef<'s, 'env, 'scope>
80        = &'s std::thread::Scope<'s, 'env>
81    where
82        'scope: 's,
83        'env: 'scope + 's;
84
85    fn max_num_threads(&self) -> NonZeroUsize {
86        self.num_threads
87    }
88
89    fn scope<'env, 'scope, F>(&'env self, f: F)
90    where
91        'env: 'scope,
92        for<'s> F: FnOnce(&'s std::thread::Scope<'s, 'env>) + Send,
93    {
94        std::thread::scope(f)
95    }
96}
97
98impl ThreadPool for &mut OncePool {
99    type ScopeRef<'s, 'env, 'scope>
100        = &'s std::thread::Scope<'s, 'env>
101    where
102        'scope: 's,
103        'env: 'scope + 's;
104
105    fn max_num_threads(&self) -> NonZeroUsize {
106        self.num_threads
107    }
108
109    fn scope<'env, 'scope, F>(&'env self, f: F)
110    where
111        'env: 'scope,
112        for<'s> F: FnOnce(&'s std::thread::Scope<'s, 'env>) + Send,
113    {
114        std::thread::scope(f)
115    }
116}