1 //! Rayon-core houses the core stable APIs of Rayon.
2 //!
3 //! These APIs have been mirrored in the Rayon crate and it is recommended to use these from there.
4 //!
5 //! [`join`] is used to take two closures and potentially run them in parallel.
6 //!   - It will run in parallel if task B gets stolen before task A can finish.
7 //!   - It will run sequentially if task A finishes before task B is stolen and can continue on task B.
8 //!
9 //! [`scope`] creates a scope in which you can run any number of parallel tasks.
10 //! These tasks can spawn nested tasks and scopes, but given the nature of work stealing, the order of execution can not be guaranteed.
11 //! The scope will exist until all tasks spawned within the scope have been completed.
12 //!
13 //! [`spawn`] add a task into the 'static' or 'global' scope, or a local scope created by the [`scope()`] function.
14 //!
15 //! [`ThreadPool`] can be used to create your own thread pools (using [`ThreadPoolBuilder`]) or to customize the global one.
16 //! Tasks spawned within the pool (using [`install()`], [`join()`], etc.) will be added to a deque,
17 //! where it becomes available for work stealing from other threads in the local threadpool.
18 //!
19 //! [`join`]: fn.join.html
20 //! [`scope`]: fn.scope.html
21 //! [`scope()`]: fn.scope.html
22 //! [`spawn`]: fn.spawn.html
23 //! [`ThreadPool`]: struct.threadpool.html
24 //! [`install()`]: struct.ThreadPool.html#method.install
25 //! [`spawn()`]: struct.ThreadPool.html#method.spawn
26 //! [`join()`]: struct.ThreadPool.html#method.join
27 //! [`ThreadPoolBuilder`]: struct.ThreadPoolBuilder.html
28 //!
29 //! ## Restricting multiple versions
30 //!
31 //! In order to ensure proper coordination between threadpools, and especially
32 //! to make sure there's only one global threadpool, `rayon-core` is actively
33 //! restricted from building multiple versions of itself into a single target.
34 //! You may see a build error like this in violation:
35 //!
36 //! ```text
37 //! error: native library `rayon-core` is being linked to by more
38 //! than one package, and can only be linked to by one package
39 //! ```
40 //!
41 //! While we strive to keep `rayon-core` semver-compatible, it's still
42 //! possible to arrive at this situation if different crates have overly
43 //! restrictive tilde or inequality requirements for `rayon-core`.  The
44 //! conflicting requirements will need to be resolved before the build will
45 //! succeed.
46 
47 #![doc(html_root_url = "https://docs.rs/rayon-core/1.9")]
48 #![deny(missing_debug_implementations)]
49 #![deny(missing_docs)]
50 #![deny(unreachable_pub)]
51 #![warn(rust_2018_idioms)]
52 
53 use std::any::Any;
54 use std::env;
55 use std::error::Error;
56 use std::fmt;
57 use std::io;
58 use std::marker::PhantomData;
59 use std::str::FromStr;
60 
61 #[macro_use]
62 mod log;
63 #[macro_use]
64 mod private;
65 
66 mod job;
67 mod join;
68 mod latch;
69 mod registry;
70 mod scope;
71 mod sleep;
72 mod spawn;
73 mod thread_pool;
74 mod unwind;
75 
76 mod compile_fail;
77 mod test;
78 
79 pub use self::join::{join, join_context};
80 pub use self::registry::ThreadBuilder;
81 pub use self::scope::{in_place_scope, scope, Scope};
82 pub use self::scope::{in_place_scope_fifo, scope_fifo, ScopeFifo};
83 pub use self::spawn::{spawn, spawn_fifo};
84 pub use self::thread_pool::current_thread_has_pending_tasks;
85 pub use self::thread_pool::current_thread_index;
86 pub use self::thread_pool::ThreadPool;
87 
88 use self::registry::{CustomSpawn, DefaultSpawn, ThreadSpawn};
89 
90 /// Returns the number of threads in the current registry. If this
91 /// code is executing within a Rayon thread-pool, then this will be
92 /// the number of threads for the thread-pool of the current
93 /// thread. Otherwise, it will be the number of threads for the global
94 /// thread-pool.
95 ///
96 /// This can be useful when trying to judge how many times to split
97 /// parallel work (the parallel iterator traits use this value
98 /// internally for this purpose).
99 ///
100 /// # Future compatibility note
101 ///
102 /// Note that unless this thread-pool was created with a
103 /// builder that specifies the number of threads, then this
104 /// number may vary over time in future versions (see [the
105 /// `num_threads()` method for details][snt]).
106 ///
107 /// [snt]: struct.ThreadPoolBuilder.html#method.num_threads
current_num_threads() -> usize108 pub fn current_num_threads() -> usize {
109     crate::registry::Registry::current_num_threads()
110 }
111 
112 /// Error when initializing a thread pool.
113 #[derive(Debug)]
114 pub struct ThreadPoolBuildError {
115     kind: ErrorKind,
116 }
117 
118 #[derive(Debug)]
119 enum ErrorKind {
120     GlobalPoolAlreadyInitialized,
121     IOError(io::Error),
122 }
123 
124 /// Used to create a new [`ThreadPool`] or to configure the global rayon thread pool.
125 /// ## Creating a ThreadPool
126 /// The following creates a thread pool with 22 threads.
127 ///
128 /// ```rust
129 /// # use rayon_core as rayon;
130 /// let pool = rayon::ThreadPoolBuilder::new().num_threads(22).build().unwrap();
131 /// ```
132 ///
133 /// To instead configure the global thread pool, use [`build_global()`]:
134 ///
135 /// ```rust
136 /// # use rayon_core as rayon;
137 /// rayon::ThreadPoolBuilder::new().num_threads(22).build_global().unwrap();
138 /// ```
139 ///
140 /// [`ThreadPool`]: struct.ThreadPool.html
141 /// [`build_global()`]: struct.ThreadPoolBuilder.html#method.build_global
142 pub struct ThreadPoolBuilder<S = DefaultSpawn> {
143     /// The number of threads in the rayon thread pool.
144     /// If zero will use the RAYON_NUM_THREADS environment variable.
145     /// If RAYON_NUM_THREADS is invalid or zero will use the default.
146     num_threads: usize,
147 
148     /// Custom closure, if any, to handle a panic that we cannot propagate
149     /// anywhere else.
150     panic_handler: Option<Box<PanicHandler>>,
151 
152     /// Closure to compute the name of a thread.
153     get_thread_name: Option<Box<dyn FnMut(usize) -> String>>,
154 
155     /// The stack size for the created worker threads
156     stack_size: Option<usize>,
157 
158     /// Closure invoked on worker thread start.
159     start_handler: Option<Box<StartHandler>>,
160 
161     /// Closure invoked on worker thread exit.
162     exit_handler: Option<Box<ExitHandler>>,
163 
164     /// Closure invoked to spawn threads.
165     spawn_handler: S,
166 
167     /// If false, worker threads will execute spawned jobs in a
168     /// "depth-first" fashion. If true, they will do a "breadth-first"
169     /// fashion. Depth-first is the default.
170     breadth_first: bool,
171 }
172 
173 /// Contains the rayon thread pool configuration. Use [`ThreadPoolBuilder`] instead.
174 ///
175 /// [`ThreadPoolBuilder`]: struct.ThreadPoolBuilder.html
176 #[deprecated(note = "Use `ThreadPoolBuilder`")]
177 pub struct Configuration {
178     builder: ThreadPoolBuilder,
179 }
180 
181 /// The type for a panic handling closure. Note that this same closure
182 /// may be invoked multiple times in parallel.
183 type PanicHandler = dyn Fn(Box<dyn Any + Send>) + Send + Sync;
184 
185 /// The type for a closure that gets invoked when a thread starts. The
186 /// closure is passed the index of the thread on which it is invoked.
187 /// Note that this same closure may be invoked multiple times in parallel.
188 type StartHandler = dyn Fn(usize) + Send + Sync;
189 
190 /// The type for a closure that gets invoked when a thread exits. The
191 /// closure is passed the index of the thread on which is is invoked.
192 /// Note that this same closure may be invoked multiple times in parallel.
193 type ExitHandler = dyn Fn(usize) + Send + Sync;
194 
195 // NB: We can't `#[derive(Default)]` because `S` is left ambiguous.
196 impl Default for ThreadPoolBuilder {
default() -> Self197     fn default() -> Self {
198         ThreadPoolBuilder {
199             num_threads: 0,
200             panic_handler: None,
201             get_thread_name: None,
202             stack_size: None,
203             start_handler: None,
204             exit_handler: None,
205             spawn_handler: DefaultSpawn,
206             breadth_first: false,
207         }
208     }
209 }
210 
211 impl ThreadPoolBuilder {
212     /// Creates and returns a valid rayon thread pool builder, but does not initialize it.
new() -> Self213     pub fn new() -> Self {
214         Self::default()
215     }
216 }
217 
218 /// Note: the `S: ThreadSpawn` constraint is an internal implementation detail for the
219 /// default spawn and those set by [`spawn_handler`](#method.spawn_handler).
220 impl<S> ThreadPoolBuilder<S>
221 where
222     S: ThreadSpawn,
223 {
224     /// Creates a new `ThreadPool` initialized using this configuration.
build(self) -> Result<ThreadPool, ThreadPoolBuildError>225     pub fn build(self) -> Result<ThreadPool, ThreadPoolBuildError> {
226         ThreadPool::build(self)
227     }
228 
229     /// Initializes the global thread pool. This initialization is
230     /// **optional**.  If you do not call this function, the thread pool
231     /// will be automatically initialized with the default
232     /// configuration. Calling `build_global` is not recommended, except
233     /// in two scenarios:
234     ///
235     /// - You wish to change the default configuration.
236     /// - You are running a benchmark, in which case initializing may
237     ///   yield slightly more consistent results, since the worker threads
238     ///   will already be ready to go even in the first iteration.  But
239     ///   this cost is minimal.
240     ///
241     /// Initialization of the global thread pool happens exactly
242     /// once. Once started, the configuration cannot be
243     /// changed. Therefore, if you call `build_global` a second time, it
244     /// will return an error. An `Ok` result indicates that this
245     /// is the first initialization of the thread pool.
build_global(self) -> Result<(), ThreadPoolBuildError>246     pub fn build_global(self) -> Result<(), ThreadPoolBuildError> {
247         let registry = registry::init_global_registry(self)?;
248         registry.wait_until_primed();
249         Ok(())
250     }
251 }
252 
253 impl ThreadPoolBuilder {
254     /// Creates a scoped `ThreadPool` initialized using this configuration.
255     ///
256     /// This is a convenience function for building a pool using [`crossbeam::scope`]
257     /// to spawn threads in a [`spawn_handler`](#method.spawn_handler).
258     /// The threads in this pool will start by calling `wrapper`, which should
259     /// do initialization and continue by calling `ThreadBuilder::run()`.
260     ///
261     /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.7/crossbeam/fn.scope.html
262     ///
263     /// # Examples
264     ///
265     /// A scoped pool may be useful in combination with scoped thread-local variables.
266     ///
267     /// ```
268     /// # use rayon_core as rayon;
269     ///
270     /// scoped_tls::scoped_thread_local!(static POOL_DATA: Vec<i32>);
271     ///
272     /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
273     ///     let pool_data = vec![1, 2, 3];
274     ///
275     ///     // We haven't assigned any TLS data yet.
276     ///     assert!(!POOL_DATA.is_set());
277     ///
278     ///     rayon::ThreadPoolBuilder::new()
279     ///         .build_scoped(
280     ///             // Borrow `pool_data` in TLS for each thread.
281     ///             |thread| POOL_DATA.set(&pool_data, || thread.run()),
282     ///             // Do some work that needs the TLS data.
283     ///             |pool| pool.install(|| assert!(POOL_DATA.is_set())),
284     ///         )?;
285     ///
286     ///     // Once we've returned, `pool_data` is no longer borrowed.
287     ///     drop(pool_data);
288     ///     Ok(())
289     /// }
290     /// ```
build_scoped<W, F, R>(self, wrapper: W, with_pool: F) -> Result<R, ThreadPoolBuildError> where W: Fn(ThreadBuilder) + Sync, F: FnOnce(&ThreadPool) -> R,291     pub fn build_scoped<W, F, R>(self, wrapper: W, with_pool: F) -> Result<R, ThreadPoolBuildError>
292     where
293         W: Fn(ThreadBuilder) + Sync, // expected to call `run()`
294         F: FnOnce(&ThreadPool) -> R,
295     {
296         let result = crossbeam_utils::thread::scope(|scope| {
297             let wrapper = &wrapper;
298             let pool = self
299                 .spawn_handler(|thread| {
300                     let mut builder = scope.builder();
301                     if let Some(name) = thread.name() {
302                         builder = builder.name(name.to_string());
303                     }
304                     if let Some(size) = thread.stack_size() {
305                         builder = builder.stack_size(size);
306                     }
307                     builder.spawn(move |_| wrapper(thread))?;
308                     Ok(())
309                 })
310                 .build()?;
311             Ok(with_pool(&pool))
312         });
313 
314         match result {
315             Ok(result) => result,
316             Err(err) => unwind::resume_unwinding(err),
317         }
318     }
319 }
320 
321 impl<S> ThreadPoolBuilder<S> {
322     /// Sets a custom function for spawning threads.
323     ///
324     /// Note that the threads will not exit until after the pool is dropped. It
325     /// is up to the caller to wait for thread termination if that is important
326     /// for any invariants. For instance, threads created in [`crossbeam::scope`]
327     /// will be joined before that scope returns, and this will block indefinitely
328     /// if the pool is leaked. Furthermore, the global thread pool doesn't terminate
329     /// until the entire process exits!
330     ///
331     /// [`crossbeam::scope`]: https://docs.rs/crossbeam/0.7/crossbeam/fn.scope.html
332     ///
333     /// # Examples
334     ///
335     /// A minimal spawn handler just needs to call `run()` from an independent thread.
336     ///
337     /// ```
338     /// # use rayon_core as rayon;
339     /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
340     ///     let pool = rayon::ThreadPoolBuilder::new()
341     ///         .spawn_handler(|thread| {
342     ///             std::thread::spawn(|| thread.run());
343     ///             Ok(())
344     ///         })
345     ///         .build()?;
346     ///
347     ///     pool.install(|| println!("Hello from my custom thread!"));
348     ///     Ok(())
349     /// }
350     /// ```
351     ///
352     /// The default spawn handler sets the name and stack size if given, and propagates
353     /// any errors from the thread builder.
354     ///
355     /// ```
356     /// # use rayon_core as rayon;
357     /// fn main() -> Result<(), rayon::ThreadPoolBuildError> {
358     ///     let pool = rayon::ThreadPoolBuilder::new()
359     ///         .spawn_handler(|thread| {
360     ///             let mut b = std::thread::Builder::new();
361     ///             if let Some(name) = thread.name() {
362     ///                 b = b.name(name.to_owned());
363     ///             }
364     ///             if let Some(stack_size) = thread.stack_size() {
365     ///                 b = b.stack_size(stack_size);
366     ///             }
367     ///             b.spawn(|| thread.run())?;
368     ///             Ok(())
369     ///         })
370     ///         .build()?;
371     ///
372     ///     pool.install(|| println!("Hello from my fully custom thread!"));
373     ///     Ok(())
374     /// }
375     /// ```
spawn_handler<F>(self, spawn: F) -> ThreadPoolBuilder<CustomSpawn<F>> where F: FnMut(ThreadBuilder) -> io::Result<()>,376     pub fn spawn_handler<F>(self, spawn: F) -> ThreadPoolBuilder<CustomSpawn<F>>
377     where
378         F: FnMut(ThreadBuilder) -> io::Result<()>,
379     {
380         ThreadPoolBuilder {
381             spawn_handler: CustomSpawn::new(spawn),
382             // ..self
383             num_threads: self.num_threads,
384             panic_handler: self.panic_handler,
385             get_thread_name: self.get_thread_name,
386             stack_size: self.stack_size,
387             start_handler: self.start_handler,
388             exit_handler: self.exit_handler,
389             breadth_first: self.breadth_first,
390         }
391     }
392 
393     /// Returns a reference to the current spawn handler.
get_spawn_handler(&mut self) -> &mut S394     fn get_spawn_handler(&mut self) -> &mut S {
395         &mut self.spawn_handler
396     }
397 
398     /// Get the number of threads that will be used for the thread
399     /// pool. See `num_threads()` for more information.
get_num_threads(&self) -> usize400     fn get_num_threads(&self) -> usize {
401         if self.num_threads > 0 {
402             self.num_threads
403         } else {
404             match env::var("RAYON_NUM_THREADS")
405                 .ok()
406                 .and_then(|s| usize::from_str(&s).ok())
407             {
408                 Some(x) if x > 0 => return x,
409                 Some(x) if x == 0 => return num_cpus::get(),
410                 _ => {}
411             }
412 
413             // Support for deprecated `RAYON_RS_NUM_CPUS`.
414             match env::var("RAYON_RS_NUM_CPUS")
415                 .ok()
416                 .and_then(|s| usize::from_str(&s).ok())
417             {
418                 Some(x) if x > 0 => x,
419                 _ => num_cpus::get(),
420             }
421         }
422     }
423 
424     /// Get the thread name for the thread with the given index.
get_thread_name(&mut self, index: usize) -> Option<String>425     fn get_thread_name(&mut self, index: usize) -> Option<String> {
426         let f = self.get_thread_name.as_mut()?;
427         Some(f(index))
428     }
429 
430     /// Sets a closure which takes a thread index and returns
431     /// the thread's name.
thread_name<F>(mut self, closure: F) -> Self where F: FnMut(usize) -> String + 'static,432     pub fn thread_name<F>(mut self, closure: F) -> Self
433     where
434         F: FnMut(usize) -> String + 'static,
435     {
436         self.get_thread_name = Some(Box::new(closure));
437         self
438     }
439 
440     /// Sets the number of threads to be used in the rayon threadpool.
441     ///
442     /// If you specify a non-zero number of threads using this
443     /// function, then the resulting thread-pools are guaranteed to
444     /// start at most this number of threads.
445     ///
446     /// If `num_threads` is 0, or you do not call this function, then
447     /// the Rayon runtime will select the number of threads
448     /// automatically. At present, this is based on the
449     /// `RAYON_NUM_THREADS` environment variable (if set),
450     /// or the number of logical CPUs (otherwise).
451     /// In the future, however, the default behavior may
452     /// change to dynamically add or remove threads as needed.
453     ///
454     /// **Future compatibility warning:** Given the default behavior
455     /// may change in the future, if you wish to rely on a fixed
456     /// number of threads, you should use this function to specify
457     /// that number. To reproduce the current default behavior, you
458     /// may wish to use the [`num_cpus`
459     /// crate](https://crates.io/crates/num_cpus) to query the number
460     /// of CPUs dynamically.
461     ///
462     /// **Old environment variable:** `RAYON_NUM_THREADS` is a one-to-one
463     /// replacement of the now deprecated `RAYON_RS_NUM_CPUS` environment
464     /// variable. If both variables are specified, `RAYON_NUM_THREADS` will
465     /// be prefered.
num_threads(mut self, num_threads: usize) -> Self466     pub fn num_threads(mut self, num_threads: usize) -> Self {
467         self.num_threads = num_threads;
468         self
469     }
470 
471     /// Returns a copy of the current panic handler.
take_panic_handler(&mut self) -> Option<Box<PanicHandler>>472     fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
473         self.panic_handler.take()
474     }
475 
476     /// Normally, whenever Rayon catches a panic, it tries to
477     /// propagate it to someplace sensible, to try and reflect the
478     /// semantics of sequential execution. But in some cases,
479     /// particularly with the `spawn()` APIs, there is no
480     /// obvious place where we should propagate the panic to.
481     /// In that case, this panic handler is invoked.
482     ///
483     /// If no panic handler is set, the default is to abort the
484     /// process, under the principle that panics should not go
485     /// unobserved.
486     ///
487     /// If the panic handler itself panics, this will abort the
488     /// process. To prevent this, wrap the body of your panic handler
489     /// in a call to `std::panic::catch_unwind()`.
panic_handler<H>(mut self, panic_handler: H) -> Self where H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,490     pub fn panic_handler<H>(mut self, panic_handler: H) -> Self
491     where
492         H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,
493     {
494         self.panic_handler = Some(Box::new(panic_handler));
495         self
496     }
497 
498     /// Get the stack size of the worker threads
get_stack_size(&self) -> Option<usize>499     fn get_stack_size(&self) -> Option<usize> {
500         self.stack_size
501     }
502 
503     /// Sets the stack size of the worker threads
stack_size(mut self, stack_size: usize) -> Self504     pub fn stack_size(mut self, stack_size: usize) -> Self {
505         self.stack_size = Some(stack_size);
506         self
507     }
508 
509     /// **(DEPRECATED)** Suggest to worker threads that they execute
510     /// spawned jobs in a "breadth-first" fashion.
511     ///
512     /// Typically, when a worker thread is idle or blocked, it will
513     /// attempt to execute the job from the *top* of its local deque of
514     /// work (i.e., the job most recently spawned). If this flag is set
515     /// to true, however, workers will prefer to execute in a
516     /// *breadth-first* fashion -- that is, they will search for jobs at
517     /// the *bottom* of their local deque. (At present, workers *always*
518     /// steal from the bottom of other worker's deques, regardless of
519     /// the setting of this flag.)
520     ///
521     /// If you think of the tasks as a tree, where a parent task
522     /// spawns its children in the tree, then this flag loosely
523     /// corresponds to doing a breadth-first traversal of the tree,
524     /// whereas the default would be to do a depth-first traversal.
525     ///
526     /// **Note that this is an "execution hint".** Rayon's task
527     /// execution is highly dynamic and the precise order in which
528     /// independent tasks are executed is not intended to be
529     /// guaranteed.
530     ///
531     /// This `breadth_first()` method is now deprecated per [RFC #1],
532     /// and in the future its effect may be removed. Consider using
533     /// [`scope_fifo()`] for a similar effect.
534     ///
535     /// [RFC #1]: https://github.com/rayon-rs/rfcs/blob/master/accepted/rfc0001-scope-scheduling.md
536     /// [`scope_fifo()`]: fn.scope_fifo.html
537     #[deprecated(note = "use `scope_fifo` and `spawn_fifo` for similar effect")]
breadth_first(mut self) -> Self538     pub fn breadth_first(mut self) -> Self {
539         self.breadth_first = true;
540         self
541     }
542 
get_breadth_first(&self) -> bool543     fn get_breadth_first(&self) -> bool {
544         self.breadth_first
545     }
546 
547     /// Takes the current thread start callback, leaving `None`.
take_start_handler(&mut self) -> Option<Box<StartHandler>>548     fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
549         self.start_handler.take()
550     }
551 
552     /// Sets a callback to be invoked on thread start.
553     ///
554     /// The closure is passed the index of the thread on which it is invoked.
555     /// Note that this same closure may be invoked multiple times in parallel.
556     /// If this closure panics, the panic will be passed to the panic handler.
557     /// If that handler returns, then startup will continue normally.
start_handler<H>(mut self, start_handler: H) -> Self where H: Fn(usize) + Send + Sync + 'static,558     pub fn start_handler<H>(mut self, start_handler: H) -> Self
559     where
560         H: Fn(usize) + Send + Sync + 'static,
561     {
562         self.start_handler = Some(Box::new(start_handler));
563         self
564     }
565 
566     /// Returns a current thread exit callback, leaving `None`.
take_exit_handler(&mut self) -> Option<Box<ExitHandler>>567     fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
568         self.exit_handler.take()
569     }
570 
571     /// Sets a callback to be invoked on thread exit.
572     ///
573     /// The closure is passed the index of the thread on which it is invoked.
574     /// Note that this same closure may be invoked multiple times in parallel.
575     /// If this closure panics, the panic will be passed to the panic handler.
576     /// If that handler returns, then the thread will exit normally.
exit_handler<H>(mut self, exit_handler: H) -> Self where H: Fn(usize) + Send + Sync + 'static,577     pub fn exit_handler<H>(mut self, exit_handler: H) -> Self
578     where
579         H: Fn(usize) + Send + Sync + 'static,
580     {
581         self.exit_handler = Some(Box::new(exit_handler));
582         self
583     }
584 }
585 
586 #[allow(deprecated)]
587 impl Configuration {
588     /// Creates and return a valid rayon thread pool configuration, but does not initialize it.
new() -> Configuration589     pub fn new() -> Configuration {
590         Configuration {
591             builder: ThreadPoolBuilder::new(),
592         }
593     }
594 
595     /// Deprecated in favor of `ThreadPoolBuilder::build`.
build(self) -> Result<ThreadPool, Box<dyn Error + 'static>>596     pub fn build(self) -> Result<ThreadPool, Box<dyn Error + 'static>> {
597         self.builder.build().map_err(Box::from)
598     }
599 
600     /// Deprecated in favor of `ThreadPoolBuilder::thread_name`.
thread_name<F>(mut self, closure: F) -> Self where F: FnMut(usize) -> String + 'static,601     pub fn thread_name<F>(mut self, closure: F) -> Self
602     where
603         F: FnMut(usize) -> String + 'static,
604     {
605         self.builder = self.builder.thread_name(closure);
606         self
607     }
608 
609     /// Deprecated in favor of `ThreadPoolBuilder::num_threads`.
num_threads(mut self, num_threads: usize) -> Configuration610     pub fn num_threads(mut self, num_threads: usize) -> Configuration {
611         self.builder = self.builder.num_threads(num_threads);
612         self
613     }
614 
615     /// Deprecated in favor of `ThreadPoolBuilder::panic_handler`.
panic_handler<H>(mut self, panic_handler: H) -> Configuration where H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,616     pub fn panic_handler<H>(mut self, panic_handler: H) -> Configuration
617     where
618         H: Fn(Box<dyn Any + Send>) + Send + Sync + 'static,
619     {
620         self.builder = self.builder.panic_handler(panic_handler);
621         self
622     }
623 
624     /// Deprecated in favor of `ThreadPoolBuilder::stack_size`.
stack_size(mut self, stack_size: usize) -> Self625     pub fn stack_size(mut self, stack_size: usize) -> Self {
626         self.builder = self.builder.stack_size(stack_size);
627         self
628     }
629 
630     /// Deprecated in favor of `ThreadPoolBuilder::breadth_first`.
breadth_first(mut self) -> Self631     pub fn breadth_first(mut self) -> Self {
632         self.builder = self.builder.breadth_first();
633         self
634     }
635 
636     /// Deprecated in favor of `ThreadPoolBuilder::start_handler`.
start_handler<H>(mut self, start_handler: H) -> Configuration where H: Fn(usize) + Send + Sync + 'static,637     pub fn start_handler<H>(mut self, start_handler: H) -> Configuration
638     where
639         H: Fn(usize) + Send + Sync + 'static,
640     {
641         self.builder = self.builder.start_handler(start_handler);
642         self
643     }
644 
645     /// Deprecated in favor of `ThreadPoolBuilder::exit_handler`.
exit_handler<H>(mut self, exit_handler: H) -> Configuration where H: Fn(usize) + Send + Sync + 'static,646     pub fn exit_handler<H>(mut self, exit_handler: H) -> Configuration
647     where
648         H: Fn(usize) + Send + Sync + 'static,
649     {
650         self.builder = self.builder.exit_handler(exit_handler);
651         self
652     }
653 
654     /// Returns a ThreadPoolBuilder with identical parameters.
into_builder(self) -> ThreadPoolBuilder655     fn into_builder(self) -> ThreadPoolBuilder {
656         self.builder
657     }
658 }
659 
660 impl ThreadPoolBuildError {
new(kind: ErrorKind) -> ThreadPoolBuildError661     fn new(kind: ErrorKind) -> ThreadPoolBuildError {
662         ThreadPoolBuildError { kind }
663     }
664 }
665 
666 const GLOBAL_POOL_ALREADY_INITIALIZED: &str =
667     "The global thread pool has already been initialized.";
668 
669 impl Error for ThreadPoolBuildError {
670     #[allow(deprecated)]
description(&self) -> &str671     fn description(&self) -> &str {
672         match self.kind {
673             ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED,
674             ErrorKind::IOError(ref e) => e.description(),
675         }
676     }
677 
source(&self) -> Option<&(dyn Error + 'static)>678     fn source(&self) -> Option<&(dyn Error + 'static)> {
679         match &self.kind {
680             ErrorKind::GlobalPoolAlreadyInitialized => None,
681             ErrorKind::IOError(e) => Some(e),
682         }
683     }
684 }
685 
686 impl fmt::Display for ThreadPoolBuildError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result687     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
688         match &self.kind {
689             ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED.fmt(f),
690             ErrorKind::IOError(e) => e.fmt(f),
691         }
692     }
693 }
694 
695 /// Deprecated in favor of `ThreadPoolBuilder::build_global`.
696 #[deprecated(note = "use `ThreadPoolBuilder::build_global`")]
697 #[allow(deprecated)]
initialize(config: Configuration) -> Result<(), Box<dyn Error>>698 pub fn initialize(config: Configuration) -> Result<(), Box<dyn Error>> {
699     config.into_builder().build_global().map_err(Box::from)
700 }
701 
702 impl<S> fmt::Debug for ThreadPoolBuilder<S> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result703     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
704         let ThreadPoolBuilder {
705             ref num_threads,
706             ref get_thread_name,
707             ref panic_handler,
708             ref stack_size,
709             ref start_handler,
710             ref exit_handler,
711             spawn_handler: _,
712             ref breadth_first,
713         } = *self;
714 
715         // Just print `Some(<closure>)` or `None` to the debug
716         // output.
717         struct ClosurePlaceholder;
718         impl fmt::Debug for ClosurePlaceholder {
719             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
720                 f.write_str("<closure>")
721             }
722         }
723         let get_thread_name = get_thread_name.as_ref().map(|_| ClosurePlaceholder);
724         let panic_handler = panic_handler.as_ref().map(|_| ClosurePlaceholder);
725         let start_handler = start_handler.as_ref().map(|_| ClosurePlaceholder);
726         let exit_handler = exit_handler.as_ref().map(|_| ClosurePlaceholder);
727 
728         f.debug_struct("ThreadPoolBuilder")
729             .field("num_threads", num_threads)
730             .field("get_thread_name", &get_thread_name)
731             .field("panic_handler", &panic_handler)
732             .field("stack_size", &stack_size)
733             .field("start_handler", &start_handler)
734             .field("exit_handler", &exit_handler)
735             .field("breadth_first", &breadth_first)
736             .finish()
737     }
738 }
739 
740 #[allow(deprecated)]
741 impl Default for Configuration {
default() -> Self742     fn default() -> Self {
743         Configuration {
744             builder: Default::default(),
745         }
746     }
747 }
748 
749 #[allow(deprecated)]
750 impl fmt::Debug for Configuration {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result751     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
752         self.builder.fmt(f)
753     }
754 }
755 
756 /// Provides the calling context to a closure called by `join_context`.
757 #[derive(Debug)]
758 pub struct FnContext {
759     migrated: bool,
760 
761     /// disable `Send` and `Sync`, just for a little future-proofing.
762     _marker: PhantomData<*mut ()>,
763 }
764 
765 impl FnContext {
766     #[inline]
new(migrated: bool) -> Self767     fn new(migrated: bool) -> Self {
768         FnContext {
769             migrated,
770             _marker: PhantomData,
771         }
772     }
773 }
774 
775 impl FnContext {
776     /// Returns `true` if the closure was called from a different thread
777     /// than it was provided from.
778     #[inline]
migrated(&self) -> bool779     pub fn migrated(&self) -> bool {
780         self.migrated
781     }
782 }
783