builder.rs - source
Description: Source of the Rust file `library/std/src/thread/builder.rs`.

#
std/thread/
builder.rs

    1use super::join_handle::JoinHandle;
    2use super::lifecycle::spawn_unchecked;
    3use crate::io;
    4
    5/// Thread factory, which can be used in order to configure the properties of
    6/// a new thread.
    7///
    8/// Methods can be chained on it in order to configure it.
    9///
    10/// The two configurations available are:
    11///
    12/// - [`name`]: specifies an [associated name for the thread][naming-threads]
    13/// - [`stack_size`]: specifies the [desired stack size for the thread][stack-size]
    14///
    15/// The [`spawn`] method will take ownership of the builder and create an
    16/// [`io::Result`] to the thread handle with the given configuration.
    17///
    18/// The [`thread::spawn`] free function uses a `Builder` with default
    19/// configuration and [`unwrap`]s its return value.
    20///
    21/// You may want to use [`spawn`] instead of [`thread::spawn`], when you want
    22/// to recover from a failure to launch a thread, indeed the free function will
    23/// panic where the `Builder` method will return a [`io::Result`].
    24///
    25/// # Examples
    26///
    27/// ```
    28/// use std::thread;
    29///
    30/// let builder = thread::Builder::new();
    31///
    32/// let handler = builder.spawn(|| {
    33///     // thread code
    34/// }).unwrap();
    35///
    36/// handler.join().unwrap();
    37/// ```
    38///
    39/// [`stack_size`]: Builder::stack_size
    40/// [`name`]: Builder::name
    41/// [`spawn`]: Builder::spawn
    42/// [`thread::spawn`]: super::spawn
    43/// [`unwrap`]: crate::result::Result::unwrap
    44/// [naming-threads]: ./index.html#naming-threads
    45/// [stack-size]: ./index.html#stack-size
    46#[must_use = "must eventually spawn the thread"]
    47#[stable(feature = "rust1", since = "1.0.0")]
    48#[derive(Debug)]
    49pub struct Builder {
    50    /// A name for the thread-to-be, for identification in panic messages
    51    pub(super) name: Option<String>,
    52    /// The size of the stack for the spawned thread in bytes
    53    pub(super) stack_size: Option<usize>,
    54    /// Skip running and inheriting the thread spawn hooks
    55    pub(super) no_hooks: bool,
    56}
    57
    58impl Builder {
    59    /// Generates the base configuration for spawning a thread, from which
    60    /// configuration methods can be chained.
    61    ///
    62    /// # Examples
    63    ///
    64    /// ```
    65    /// use std::thread;
    66    ///
    67    /// let builder = thread::Builder::new()
    68    ///                               .name("foo".into())
    69    ///                               .stack_size(32 * 1024);
    70    ///
    71    /// let handler = builder.spawn(|| {
    72    ///     // thread code
    73    /// }).unwrap();
    74    ///
    75    /// handler.join().unwrap();
    76    /// ```
    77    #[stable(feature = "rust1", since = "1.0.0")]
    78    pub fn new() -> Builder {
    79        Builder { name: None, stack_size: None, no_hooks: false }
    80    }
    81
    82    /// Names the thread-to-be. Currently the name is used for identification
    83    /// only in panic messages.
    84    ///
    85    /// The name must not contain null bytes (`\0`).
    86    ///
    87    /// For more information about named threads, see
    88    /// [this module-level documentation][naming-threads].
    89    ///
    90    /// # Examples
    91    ///
    92    /// ```
    93    /// use std::thread;
    94    ///
    95    /// let builder = thread::Builder::new()
    96    ///     .name("foo".into());
    97    ///
    98    /// let handler = builder.spawn(|| {
    99    ///     assert_eq!(thread::current().name(), Some("foo"))
    100    /// }).unwrap();
    101    ///
    102    /// handler.join().unwrap();
    103    /// ```
    104    ///
    105    /// [naming-threads]: ./index.html#naming-threads
    106    #[stable(feature = "rust1", since = "1.0.0")]
    107    pub fn name(mut self, name: String) -> Builder {
    108        self.name = Some(name);
    109        self
    110    }
    111
    112    /// Sets the size of the stack (in bytes) for the new thread.
    113    ///
    114    /// The actual stack size may be greater than this value if
    115    /// the platform specifies a minimal stack size.
    116    ///
    117    /// For more information about the stack size for threads, see
    118    /// [this module-level documentation][stack-size].
    119    ///
    120    /// # Examples
    121    ///
    122    /// ```
    123    /// use std::thread;
    124    ///
    125    /// let builder = thread::Builder::new().stack_size(32 * 1024);
    126    /// ```
    127    ///
    128    /// [stack-size]: ./index.html#stack-size
    129    #[stable(feature = "rust1", since = "1.0.0")]
    130    pub fn stack_size(mut self, size: usize) -> Builder {
    131        self.stack_size = Some(size);
    132        self
    133    }
    134
    135    /// Disables running and inheriting [spawn hooks].
    136    ///
    137    /// Use this if the parent thread is in no way relevant for the child thread.
    138    /// For example, when lazily spawning threads for a thread pool.
    139    ///
    140    /// [spawn hooks]: super::add_spawn_hook
    141    #[unstable(feature = "thread_spawn_hook", issue = "132951")]
    142    pub fn no_hooks(mut self) -> Builder {
    143        self.no_hooks = true;
    144        self
    145    }
    146
    147    /// Spawns a new thread by taking ownership of the `Builder`, and returns an
    148    /// [`io::Result`] to its [`JoinHandle`].
    149    ///
    150    /// The spawned thread may outlive the caller (unless the caller thread
    151    /// is the main thread; the whole process is terminated when the main
    152    /// thread finishes). The join handle can be used to block on
    153    /// termination of the spawned thread, including recovering its panics.
    154    ///
    155    /// For a more complete documentation see [`thread::spawn`].
    156    ///
    157    /// # Errors
    158    ///
    159    /// Unlike the [`spawn`] free function, this method yields an
    160    /// [`io::Result`] to capture any failure to create the thread at
    161    /// the OS level.
    162    ///
    163    /// # Panics
    164    ///
    165    /// Panics if a thread name was set and it contained null bytes.
    166    ///
    167    /// # Examples
    168    ///
    169    /// ```
    170    /// use std::thread;
    171    ///
    172    /// let builder = thread::Builder::new();
    173    ///
    174    /// let handler = builder.spawn(|| {
    175    ///     // thread code
    176    /// }).unwrap();
    177    ///
    178    /// handler.join().unwrap();
    179    /// ```
    180    ///
    181    /// [`thread::spawn`]: super::spawn
    182    /// [`spawn`]: super::spawn
    183    #[stable(feature = "rust1", since = "1.0.0")]
    184    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    185    pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
    186    where
    187        F: FnOnce() -> T,
    188        F: Send + 'static,
    189        T: Send + 'static,
    190    {
    191        unsafe { self.spawn_unchecked(f) }
    192    }
    193
    194    /// Spawns a new thread without any lifetime restrictions by taking ownership
    195    /// of the `Builder`, and returns an [`io::Result`] to its [`JoinHandle`].
    196    ///
    197    /// The spawned thread may outlive the caller (unless the caller thread
    198    /// is the main thread; the whole process is terminated when the main
    199    /// thread finishes). The join handle can be used to block on
    200    /// termination of the spawned thread, including recovering its panics.
    201    ///
    202    /// This method is identical to [`thread::Builder::spawn`][`Builder::spawn`],
    203    /// except for the relaxed lifetime bounds, which render it unsafe.
    204    /// For a more complete documentation see [`thread::spawn`].
    205    ///
    206    /// # Errors
    207    ///
    208    /// Unlike the [`spawn`] free function, this method yields an
    209    /// [`io::Result`] to capture any failure to create the thread at
    210    /// the OS level.
    211    ///
    212    /// # Panics
    213    ///
    214    /// Panics if a thread name was set and it contained null bytes.
    215    ///
    216    /// # Safety
    217    ///
    218    /// The caller has to ensure that the spawned thread does not outlive any
    219    /// references in the supplied thread closure and its return type.
    220    /// This can be guaranteed in two ways:
    221    ///
    222    /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced
    223    /// data is dropped
    224    /// - use only types with `'static` lifetime bounds, i.e., those with no or only
    225    /// `'static` references (both [`thread::Builder::spawn`][`Builder::spawn`]
    226    /// and [`thread::spawn`] enforce this property statically)
    227    ///
    228    /// # Examples
    229    ///
    230    /// ```
    231    /// use std::thread;
    232    ///
    233    /// let builder = thread::Builder::new();
    234    ///
    235    /// let x = 1;
    236    /// let thread_x = &x;
    237    ///
    238    /// let handler = unsafe {
    239    ///     builder.spawn_unchecked(move || {
    240    ///         println!("x = {}", *thread_x);
    241    ///     }).unwrap()
    242    /// };
    243    ///
    244    /// // caller has to ensure `join()` is called, otherwise
    245    /// // it is possible to access freed memory if `x` gets
    246    /// // dropped before the thread closure is executed!
    247    /// handler.join().unwrap();
    248    /// ```
    249    ///
    250    /// [`thread::spawn`]: super::spawn
    251    /// [`spawn`]: super::spawn
    252    #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")]
    253    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    254    pub unsafe fn spawn_unchecked<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
    255    where
    256        F: FnOnce() -> T,
    257        F: Send,
    258        T: Send,
    259    {
    260        let Builder { name, stack_size, no_hooks } = self;
    261        Ok(JoinHandle(unsafe { spawn_unchecked(name, stack_size, no_hooks, None, f) }?))
    262    }
    263}