| 1 | //! Native threads. |
| 2 | //! |
| 3 | //! ## The threading model |
| 4 | //! |
| 5 | //! An executing Rust program consists of a collection of native OS threads, |
| 6 | //! each with their own stack and local state. Threads can be named, and |
| 7 | //! provide some built-in support for low-level synchronization. |
| 8 | //! |
| 9 | //! Communication between threads can be done through |
| 10 | //! [channels], Rust's message-passing types, along with [other forms of thread |
| 11 | //! synchronization](../../std/sync/index.html) and shared-memory data |
| 12 | //! structures. In particular, types that are guaranteed to be |
| 13 | //! threadsafe are easily shared between threads using the |
| 14 | //! atomically-reference-counted container, [`Arc`]. |
| 15 | //! |
| 16 | //! Fatal logic errors in Rust cause *thread panic*, during which |
| 17 | //! a thread will unwind the stack, running destructors and freeing |
| 18 | //! owned resources. While not meant as a 'try/catch' mechanism, panics |
| 19 | //! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with |
| 20 | //! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered |
| 21 | //! from, or alternatively be resumed with |
| 22 | //! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic |
| 23 | //! is not caught the thread will exit, but the panic may optionally be |
| 24 | //! detected from a different thread with [`join`]. If the main thread panics |
| 25 | //! without the panic being caught, the application will exit with a |
| 26 | //! non-zero exit code. |
| 27 | //! |
| 28 | //! When the main thread of a Rust program terminates, the entire program shuts |
| 29 | //! down, even if other threads are still running. However, this module provides |
| 30 | //! convenient facilities for automatically waiting for the termination of a |
| 31 | //! thread (i.e., join). |
| 32 | //! |
| 33 | //! ## Spawning a thread |
| 34 | //! |
| 35 | //! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: |
| 36 | //! |
| 37 | //! ```rust |
| 38 | //! use std::thread; |
| 39 | //! |
| 40 | //! thread::spawn(move || { |
| 41 | //! // some work here |
| 42 | //! }); |
| 43 | //! ``` |
| 44 | //! |
| 45 | //! In this example, the spawned thread is "detached," which means that there is |
| 46 | //! no way for the program to learn when the spawned thread completes or otherwise |
| 47 | //! terminates. |
| 48 | //! |
| 49 | //! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] |
| 50 | //! object that is returned by the call to [`spawn`], which provides |
| 51 | //! a `join` method that allows the caller to wait for the completion of the |
| 52 | //! spawned thread: |
| 53 | //! |
| 54 | //! ```rust |
| 55 | //! use std::thread; |
| 56 | //! |
| 57 | //! let thread_join_handle = thread::spawn(move || { |
| 58 | //! // some work here |
| 59 | //! }); |
| 60 | //! // some work here |
| 61 | //! let res = thread_join_handle.join(); |
| 62 | //! ``` |
| 63 | //! |
| 64 | //! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final |
| 65 | //! value produced by the spawned thread, or [`Err`] of the value given to |
| 66 | //! a call to [`panic!`] if the thread panicked. |
| 67 | //! |
| 68 | //! Note that there is no parent/child relationship between a thread that spawns a |
| 69 | //! new thread and the thread being spawned. In particular, the spawned thread may or |
| 70 | //! may not outlive the spawning thread, unless the spawning thread is the main thread. |
| 71 | //! |
| 72 | //! ## Configuring threads |
| 73 | //! |
| 74 | //! A new thread can be configured before it is spawned via the [`Builder`] type, |
| 75 | //! which currently allows you to set the name and stack size for the thread: |
| 76 | //! |
| 77 | //! ```rust |
| 78 | //! # #![allow(unused_must_use)] |
| 79 | //! use std::thread; |
| 80 | //! |
| 81 | //! thread::Builder::new().name("thread1" .to_string()).spawn(move || { |
| 82 | //! println!("Hello, world!" ); |
| 83 | //! }); |
| 84 | //! ``` |
| 85 | //! |
| 86 | //! ## The `Thread` type |
| 87 | //! |
| 88 | //! Threads are represented via the [`Thread`] type, which you can get in one of |
| 89 | //! two ways: |
| 90 | //! |
| 91 | //! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] |
| 92 | //! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. |
| 93 | //! * By requesting the current thread, using the [`thread::current`] function. |
| 94 | //! |
| 95 | //! The [`thread::current`] function is available even for threads not spawned |
| 96 | //! by the APIs of this module. |
| 97 | //! |
| 98 | //! ## Thread-local storage |
| 99 | //! |
| 100 | //! This module also provides an implementation of thread-local storage for Rust |
| 101 | //! programs. Thread-local storage is a method of storing data into a global |
| 102 | //! variable that each thread in the program will have its own copy of. |
| 103 | //! Threads do not share this data, so accesses do not need to be synchronized. |
| 104 | //! |
| 105 | //! A thread-local key owns the value it contains and will destroy the value when the |
| 106 | //! thread exits. It is created with the [`thread_local!`] macro and can contain any |
| 107 | //! value that is `'static` (no borrowed pointers). It provides an accessor function, |
| 108 | //! [`with`], that yields a shared reference to the value to the specified |
| 109 | //! closure. Thread-local keys allow only shared access to values, as there would be no |
| 110 | //! way to guarantee uniqueness if mutable borrows were allowed. Most values |
| 111 | //! will want to make use of some form of **interior mutability** through the |
| 112 | //! [`Cell`] or [`RefCell`] types. |
| 113 | //! |
| 114 | //! ## Naming threads |
| 115 | //! |
| 116 | //! Threads are able to have associated names for identification purposes. By default, spawned |
| 117 | //! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass |
| 118 | //! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the |
| 119 | //! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: |
| 120 | //! |
| 121 | //! * If a panic occurs in a named thread, the thread name will be printed in the panic message. |
| 122 | //! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in |
| 123 | //! unix-like platforms). |
| 124 | //! |
| 125 | //! ## Stack size |
| 126 | //! |
| 127 | //! The default stack size is platform-dependent and subject to change. |
| 128 | //! Currently, it is 2 MiB on all Tier-1 platforms. |
| 129 | //! |
| 130 | //! There are two ways to manually specify the stack size for spawned threads: |
| 131 | //! |
| 132 | //! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. |
| 133 | //! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack |
| 134 | //! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that |
| 135 | //! changes to `RUST_MIN_STACK` may be ignored after program start. |
| 136 | //! |
| 137 | //! Note that the stack size of the main thread is *not* determined by Rust. |
| 138 | //! |
| 139 | //! [channels]: crate::sync::mpsc |
| 140 | //! [`Arc`]: crate::sync::Arc |
| 141 | //! [`join`]: JoinHandle::join |
| 142 | //! [`Result`]: crate::result::Result |
| 143 | //! [`Ok`]: crate::result::Result::Ok |
| 144 | //! [`Err`]: crate::result::Result::Err |
| 145 | //! [`thread::current`]: current::current |
| 146 | //! [`thread::Result`]: Result |
| 147 | //! [`unpark`]: Thread::unpark |
| 148 | //! [`thread::park_timeout`]: park_timeout |
| 149 | //! [`Cell`]: crate::cell::Cell |
| 150 | //! [`RefCell`]: crate::cell::RefCell |
| 151 | //! [`with`]: LocalKey::with |
| 152 | //! [`thread_local!`]: crate::thread_local |
| 153 | |
| 154 | #![stable (feature = "rust1" , since = "1.0.0" )] |
| 155 | #![deny (unsafe_op_in_unsafe_fn)] |
| 156 | // Under `test`, `__FastLocalKeyInner` seems unused. |
| 157 | #![cfg_attr (test, allow(dead_code))] |
| 158 | |
| 159 | use crate::any::Any; |
| 160 | |
| 161 | #[macro_use ] |
| 162 | mod local; |
| 163 | mod builder; |
| 164 | mod current; |
| 165 | mod functions; |
| 166 | mod id; |
| 167 | mod join_handle; |
| 168 | mod lifecycle; |
| 169 | mod scoped; |
| 170 | mod spawnhook; |
| 171 | mod thread; |
| 172 | |
| 173 | pub(crate) mod main_thread; |
| 174 | |
| 175 | #[cfg (all(test, not(any(target_os = "emscripten" , target_os = "wasi" ))))] |
| 176 | mod tests; |
| 177 | |
| 178 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 179 | pub use builder::Builder; |
| 180 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 181 | pub use current::current; |
| 182 | #[unstable (feature = "current_thread_id" , issue = "147194" )] |
| 183 | pub use current::current_id; |
| 184 | pub(crate) use current::{current_or_unnamed, current_os_id, drop_current, with_current_name}; |
| 185 | #[stable (feature = "available_parallelism" , since = "1.59.0" )] |
| 186 | pub use functions::available_parallelism; |
| 187 | #[stable (feature = "park_timeout" , since = "1.4.0" )] |
| 188 | pub use functions::park_timeout; |
| 189 | #[stable (feature = "thread_sleep" , since = "1.4.0" )] |
| 190 | pub use functions::sleep; |
| 191 | #[unstable (feature = "thread_sleep_until" , issue = "113752" )] |
| 192 | pub use functions::sleep_until; |
| 193 | #[expect (deprecated)] |
| 194 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 195 | pub use functions::{panicking, park, park_timeout_ms, sleep_ms, spawn, yield_now}; |
| 196 | #[stable (feature = "thread_id" , since = "1.19.0" )] |
| 197 | pub use id::ThreadId; |
| 198 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 199 | pub use join_handle::JoinHandle; |
| 200 | pub(crate) use lifecycle::ThreadInit; |
| 201 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 202 | pub use local::{AccessError, LocalKey}; |
| 203 | #[stable (feature = "scoped_threads" , since = "1.63.0" )] |
| 204 | pub use scoped::{Scope, ScopedJoinHandle, scope}; |
| 205 | #[unstable (feature = "thread_spawn_hook" , issue = "132951" )] |
| 206 | pub use spawnhook::add_spawn_hook; |
| 207 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 208 | pub use thread::Thread; |
| 209 | |
| 210 | // Implementation details used by the thread_local!{} macro. |
| 211 | #[doc (hidden)] |
| 212 | #[unstable (feature = "thread_local_internals" , issue = "none" )] |
| 213 | pub mod local_impl { |
| 214 | pub use super::local::thread_local_process_attrs; |
| 215 | pub use crate::sys::thread_local::*; |
| 216 | } |
| 217 | |
| 218 | /// A specialized [`Result`] type for threads. |
| 219 | /// |
| 220 | /// Indicates the manner in which a thread exited. |
| 221 | /// |
| 222 | /// The value contained in the `Result::Err` variant |
| 223 | /// is the value the thread panicked with; |
| 224 | /// that is, the argument the `panic!` macro was called with. |
| 225 | /// Unlike with normal errors, this value doesn't implement |
| 226 | /// the [`Error`](crate::error::Error) trait. |
| 227 | /// |
| 228 | /// Thus, a sensible way to handle a thread panic is to either: |
| 229 | /// |
| 230 | /// 1. propagate the panic with [`std::panic::resume_unwind`] |
| 231 | /// 2. or in case the thread is intended to be a subsystem boundary |
| 232 | /// that is supposed to isolate system-level failures, |
| 233 | /// match on the `Err` variant and handle the panic in an appropriate way |
| 234 | /// |
| 235 | /// A thread that completes without panicking is considered to exit successfully. |
| 236 | /// |
| 237 | /// # Examples |
| 238 | /// |
| 239 | /// Matching on the result of a joined thread: |
| 240 | /// |
| 241 | /// ```no_run |
| 242 | /// use std::{fs, thread, panic}; |
| 243 | /// |
| 244 | /// fn copy_in_thread() -> thread::Result<()> { |
| 245 | /// thread::spawn(|| { |
| 246 | /// fs::copy("foo.txt" , "bar.txt" ).unwrap(); |
| 247 | /// }).join() |
| 248 | /// } |
| 249 | /// |
| 250 | /// fn main() { |
| 251 | /// match copy_in_thread() { |
| 252 | /// Ok(_) => println!("copy succeeded" ), |
| 253 | /// Err(e) => panic::resume_unwind(e), |
| 254 | /// } |
| 255 | /// } |
| 256 | /// ``` |
| 257 | /// |
| 258 | /// [`Result`]: crate::result::Result |
| 259 | /// [`std::panic::resume_unwind`]: crate::panic::resume_unwind |
| 260 | #[stable (feature = "rust1" , since = "1.0.0" )] |
| 261 | #[doc (search_unbox)] |
| 262 | pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>; |
| 263 | |
| 264 | fn _assert_sync_and_send() { |
| 265 | fn _assert_both<T: Send + Sync>() {} |
| 266 | _assert_both::<JoinHandle<()>>(); |
| 267 | _assert_both::<Thread>(); |
| 268 | } |
| 269 | |