| 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 |
| /// [`io::Result`]: crate::io::Result |
| /// [`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. |
| /// |
| /// [`io::Result`]: crate::io::Result |
| /// |
| /// # 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(); |
| /// ``` |
| /// |
| /// [`io::Result`]: crate::io::Result |
| /// [`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) }?)) |
| } |
| } |