| use super::join_handle::JoinHandle; | |
| use super::lifecycle::spawn_unchecked; | |
| use crate::io; | |
| /// Thread factory, which can be used in order to configure the properties of | |
| /// a new thread. | |
| /// | |
| /// Methods can be chained on it in order to configure it. | |
| /// | |
| /// The two configurations available are: | |
| /// | |
| /// - [`name`]: specifies an [associated name for the thread][naming-threads] | |
| /// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size] | |
| /// | |
| /// The [`spawn`] method will take ownership of the builder and create an | |
| /// [`io::Result`] to the thread handle with the given configuration. | |
| /// | |
| /// The [`thread::spawn`] free function uses a `Builder` with default | |
| /// configuration and [`unwrap`]s its return value. | |
| /// | |
| /// You may want to use [`spawn`] instead of [`thread::spawn`], when you want | |
| /// to recover from a failure to launch a thread, indeed the free function will | |
| /// panic where the `Builder` method will return a [`io::Result`]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new(); | |
| /// | |
| /// let handler = builder.spawn(|| { | |
| /// // thread code | |
| /// }).unwrap(); | |
| /// | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// [`stack_size`]: Builder::stack_size | |
| /// [`name`]: Builder::name | |
| /// [`spawn`]: Builder::spawn | |
| /// [`thread::spawn`]: super::spawn | |
| /// [`unwrap`]: crate::result::Result::unwrap | |
| /// [naming-threads]: ./index.html#naming-threads | |
| /// [stack-size]: ./index.html#stack-size | |
| #[must_use = "must eventually spawn the thread"] | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[derive(Debug)] | |
| pub struct Builder { | |
| /// A name for the thread-to-be, for identification in panic messages | |
| pub(super) name: Option<String>, | |
| /// The size of the stack for the spawned thread in bytes | |
| pub(super) stack_size: Option<usize>, | |
| /// Skip running and inheriting the thread spawn hooks | |
| pub(super) no_hooks: bool, | |
| } | |
| impl Builder { | |
| /// Generates the base configuration for spawning a thread, from which | |
| /// configuration methods can be chained. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new() | |
| /// .name("foo".into()) | |
| /// .stack_size(32 * 1024); | |
| /// | |
| /// let handler = builder.spawn(|| { | |
| /// // thread code | |
| /// }).unwrap(); | |
| /// | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn new() -> Builder { | |
| Builder { name: None, stack_size: None, no_hooks: false } | |
| } | |
| /// Names the thread-to-be. Currently the name is used for identification | |
| /// only in panic messages. | |
| /// | |
| /// The name must not contain null bytes (`\0`). | |
| /// | |
| /// For more information about named threads, see | |
| /// [this module-level documentation][naming-threads]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new() | |
| /// .name("foo".into()); | |
| /// | |
| /// let handler = builder.spawn(|| { | |
| /// assert_eq!(thread::current().name(), Some("foo")) | |
| /// }).unwrap(); | |
| /// | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// [naming-threads]: ./index.html#naming-threads | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn name(mut self, name: String) -> Builder { | |
| self.name = Some(name); | |
| self | |
| } | |
| /// Sets the size of the stack (in bytes) for the new thread. | |
| /// | |
| /// The actual stack size may be greater than this value if | |
| /// the platform specifies a minimal stack size. | |
| /// | |
| /// For more information about the stack size for threads, see | |
| /// [this module-level documentation][stack-size]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new().stack_size(32 * 1024); | |
| /// ``` | |
| /// | |
| /// [stack-size]: ./index.html#stack-size | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| pub fn stack_size(mut self, size: usize) -> Builder { | |
| self.stack_size = Some(size); | |
| self | |
| } | |
| /// Disables running and inheriting [spawn hooks]. | |
| /// | |
| /// Use this if the parent thread is in no way relevant for the child thread. | |
| /// For example, when lazily spawning threads for a thread pool. | |
| /// | |
| /// [spawn hooks]: super::add_spawn_hook | |
| #[unstable(feature = "thread_spawn_hook", issue = "132951")] | |
| pub fn no_hooks(mut self) -> Builder { | |
| self.no_hooks = true; | |
| self | |
| } | |
| /// Spawns a new thread by taking ownership of the `Builder`, and returns an | |
| /// [`io::Result`] to its [`JoinHandle`]. | |
| /// | |
| /// The spawned thread may outlive the caller (unless the caller thread | |
| /// is the main thread; the whole process is terminated when the main | |
| /// thread finishes). The join handle can be used to block on | |
| /// termination of the spawned thread, including recovering its panics. | |
| /// | |
| /// For a more complete documentation see [`thread::spawn`]. | |
| /// | |
| /// # Errors | |
| /// | |
| /// Unlike the [`spawn`] free function, this method yields an | |
| /// [`io::Result`] to capture any failure to create the thread at | |
| /// the OS level. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if a thread name was set and it contained null bytes. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new(); | |
| /// | |
| /// let handler = builder.spawn(|| { | |
| /// // thread code | |
| /// }).unwrap(); | |
| /// | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// [`thread::spawn`]: super::spawn | |
| /// [`spawn`]: super::spawn | |
| #[stable(feature = "rust1", since = "1.0.0")] | |
| #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | |
| pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> | |
| where | |
| F: FnOnce() -> T, | |
| F: Send + 'static, | |
| T: Send + 'static, | |
| { | |
| unsafe { self.spawn_unchecked(f) } | |
| } | |
| /// Spawns a new thread without any lifetime restrictions by taking ownership | |
| /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`]. | |
| /// | |
| /// The spawned thread may outlive the caller (unless the caller thread | |
| /// is the main thread; the whole process is terminated when the main | |
| /// thread finishes). The join handle can be used to block on | |
| /// termination of the spawned thread, including recovering its panics. | |
| /// | |
| /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`], | |
| /// except for the relaxed lifetime bounds, which render it unsafe. | |
| /// For a more complete documentation see [`thread::spawn`]. | |
| /// | |
| /// # Errors | |
| /// | |
| /// Unlike the [`spawn`] free function, this method yields an | |
| /// [`io::Result`] to capture any failure to create the thread at | |
| /// the OS level. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if a thread name was set and it contained null bytes. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The caller has to ensure that the spawned thread does not outlive any | |
| /// references in the supplied thread closure and its return type. | |
| /// This can be guaranteed in two ways: | |
| /// | |
| /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced | |
| /// data is dropped | |
| /// - use only types with `'static` lifetime bounds, i.e., those with no or only | |
| /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`] | |
| /// and [`thread::spawn`] enforce this property statically) | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::thread; | |
| /// | |
| /// let builder = thread::Builder::new(); | |
| /// | |
| /// let x = 1; | |
| /// let thread_x = &x; | |
| /// | |
| /// let handler = unsafe { | |
| /// builder.spawn_unchecked(move || { | |
| /// println!("x = {}", *thread_x); | |
| /// }).unwrap() | |
| /// }; | |
| /// | |
| /// // caller has to ensure `join()` is called, otherwise | |
| /// // it is possible to access freed memory if `x` gets | |
| /// // dropped before the thread closure is executed! | |
| /// handler.join().unwrap(); | |
| /// ``` | |
| /// | |
| /// [`thread::spawn`]: super::spawn | |
| /// [`spawn`]: super::spawn | |
| #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] | |
| #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces | |
| pub unsafe fn spawn_unchecked<F, T>(self, f: F) -> io::Result<JoinHandle<T>> | |
| where | |
| F: FnOnce() -> T, | |
| F: Send, | |
| T: Send, | |
| { | |
| let Builder { name, stack_size, no_hooks } = self; | |
| Ok(JoinHandle(unsafe { spawn_unchecked(name, stack_size, no_hooks, None, f) }?)) | |
| } | |
| } |