| //! Native threads. |
| //! |
| //! ## The threading model |
| //! |
| //! An executing Rust program consists of a collection of native OS threads, |
| //! each with their own stack and local state. Threads can be named, and |
| //! provide some built-in support for low-level synchronization. |
| //! |
| //! Communication between threads can be done through |
| //! [channels], Rust's message-passing types, along with [other forms of thread |
| //! synchronization](../../std/sync/index.html) and shared-memory data |
| //! structures. In particular, types that are guaranteed to be |
| //! threadsafe are easily shared between threads using the |
| //! atomically-reference-counted container, [`Arc`]. |
| //! |
| //! Fatal logic errors in Rust cause *thread panic*, during which |
| //! a thread will unwind the stack, running destructors and freeing |
| //! owned resources. While not meant as a 'try/catch' mechanism, panics |
| //! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with |
| //! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered |
| //! from, or alternatively be resumed with |
| //! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic |
| //! is not caught the thread will exit, but the panic may optionally be |
| //! detected from a different thread with [`join`]. If the main thread panics |
| //! without the panic being caught, the application will exit with a |
| //! non-zero exit code. |
| //! |
| //! When the main thread of a Rust program terminates, the entire program shuts |
| //! down, even if other threads are still running. However, this module provides |
| //! convenient facilities for automatically waiting for the termination of a |
| //! thread (i.e., join). |
| //! |
| //! ## Spawning a thread |
| //! |
| //! A new thread can be spawned using the [`thread::spawn`][`spawn`] function: |
| //! |
| //! ```rust |
| //! use std::thread; |
| //! |
| //! thread::spawn(move || { |
| //! // some work here |
| //! }); |
| //! ``` |
| //! |
| //! In this example, the spawned thread is "detached," which means that there is |
| //! no way for the program to learn when the spawned thread completes or otherwise |
| //! terminates. |
| //! |
| //! To learn when a thread completes, it is necessary to capture the [`JoinHandle`] |
| //! object that is returned by the call to [`spawn`], which provides |
| //! a `join` method that allows the caller to wait for the completion of the |
| //! spawned thread: |
| //! |
| //! ```rust |
| //! use std::thread; |
| //! |
| //! let thread_join_handle = thread::spawn(move || { |
| //! // some work here |
| //! }); |
| //! // some work here |
| //! let res = thread_join_handle.join(); |
| //! ``` |
| //! |
| //! The [`join`] method returns a [`thread::Result`] containing [`Ok`] of the final |
| //! value produced by the spawned thread, or [`Err`] of the value given to |
| //! a call to [`panic!`] if the thread panicked. |
| //! |
| //! Note that there is no parent/child relationship between a thread that spawns a |
| //! new thread and the thread being spawned. In particular, the spawned thread may or |
| //! may not outlive the spawning thread, unless the spawning thread is the main thread. |
| //! |
| //! ## Configuring threads |
| //! |
| //! A new thread can be configured before it is spawned via the [`Builder`] type, |
| //! which currently allows you to set the name and stack size for the thread: |
| //! |
| //! ```rust |
| //! # #![allow(unused_must_use)] |
| //! use std::thread; |
| //! |
| //! thread::Builder::new().name("thread1".to_string()).spawn(move || { |
| //! println!("Hello, world!"); |
| //! }); |
| //! ``` |
| //! |
| //! ## The `Thread` type |
| //! |
| //! Threads are represented via the [`Thread`] type, which you can get in one of |
| //! two ways: |
| //! |
| //! * By spawning a new thread, e.g., using the [`thread::spawn`][`spawn`] |
| //! function, and calling [`thread`][`JoinHandle::thread`] on the [`JoinHandle`]. |
| //! * By requesting the current thread, using the [`thread::current`] function. |
| //! |
| //! The [`thread::current`] function is available even for threads not spawned |
| //! by the APIs of this module. |
| //! |
| //! ## Thread-local storage |
| //! |
| //! This module also provides an implementation of thread-local storage for Rust |
| //! programs. Thread-local storage is a method of storing data into a global |
| //! variable that each thread in the program will have its own copy of. |
| //! Threads do not share this data, so accesses do not need to be synchronized. |
| //! |
| //! A thread-local key owns the value it contains and will destroy the value when the |
| //! thread exits. It is created with the [`thread_local!`] macro and can contain any |
| //! value that is `'static` (no borrowed pointers). It provides an accessor function, |
| //! [`with`], that yields a shared reference to the value to the specified |
| //! closure. Thread-local keys allow only shared access to values, as there would be no |
| //! way to guarantee uniqueness if mutable borrows were allowed. Most values |
| //! will want to make use of some form of **interior mutability** through the |
| //! [`Cell`] or [`RefCell`] types. |
| //! |
| //! ## Naming threads |
| //! |
| //! Threads are able to have associated names for identification purposes. By default, spawned |
| //! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass |
| //! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the |
| //! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used: |
| //! |
| //! * If a panic occurs in a named thread, the thread name will be printed in the panic message. |
| //! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in |
| //! unix-like platforms). |
| //! |
| //! ## Stack size |
| //! |
| //! The default stack size is platform-dependent and subject to change. |
| //! Currently, it is 2 MiB on all Tier-1 platforms. |
| //! |
| //! There are two ways to manually specify the stack size for spawned threads: |
| //! |
| //! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`]. |
| //! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack |
| //! size (in bytes). Note that setting [`Builder::stack_size`] will override this. Be aware that |
| //! changes to `RUST_MIN_STACK` may be ignored after program start. |
| //! |
| //! Note that the stack size of the main thread is *not* determined by Rust. |
| //! |
| //! [channels]: crate::sync::mpsc |
| //! [`Arc`]: crate::sync::Arc |
| //! [`join`]: JoinHandle::join |
| //! [`Result`]: crate::result::Result |
| //! [`Ok`]: crate::result::Result::Ok |
| //! [`Err`]: crate::result::Result::Err |
| //! [`thread::current`]: current::current |
| //! [`thread::Result`]: Result |
| //! [`unpark`]: Thread::unpark |
| //! [`thread::park_timeout`]: park_timeout |
| //! [`Cell`]: crate::cell::Cell |
| //! [`RefCell`]: crate::cell::RefCell |
| //! [`with`]: LocalKey::with |
| //! [`thread_local!`]: crate::thread_local |
| |
| #![stable(feature = "rust1", since = "1.0.0")] |
| #![deny(unsafe_op_in_unsafe_fn)] |
| // Under `test`, `__FastLocalKeyInner` seems unused. |
| #![cfg_attr(test, allow(dead_code))] |
| |
| use crate::any::Any; |
| |
| #[macro_use] |
| mod local; |
| mod builder; |
| mod current; |
| mod functions; |
| mod id; |
| mod join_handle; |
| mod lifecycle; |
| mod scoped; |
| mod spawnhook; |
| mod thread; |
| |
| pub(crate) mod main_thread; |
| |
| #[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] |
| mod tests; |
| |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub use builder::Builder; |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub use current::current; |
| #[unstable(feature = "current_thread_id", issue = "147194")] |
| pub use current::current_id; |
| pub(crate) use current::{current_or_unnamed, current_os_id, drop_current, with_current_name}; |
| #[stable(feature = "available_parallelism", since = "1.59.0")] |
| pub use functions::available_parallelism; |
| #[stable(feature = "park_timeout", since = "1.4.0")] |
| pub use functions::park_timeout; |
| #[stable(feature = "thread_sleep", since = "1.4.0")] |
| pub use functions::sleep; |
| #[unstable(feature = "thread_sleep_until", issue = "113752")] |
| pub use functions::sleep_until; |
| #[expect(deprecated)] |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub use functions::{panicking, park, park_timeout_ms, sleep_ms, spawn, yield_now}; |
| #[stable(feature = "thread_id", since = "1.19.0")] |
| pub use id::ThreadId; |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub use join_handle::JoinHandle; |
| pub(crate) use lifecycle::ThreadInit; |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub use local::{AccessError, LocalKey}; |
| #[stable(feature = "scoped_threads", since = "1.63.0")] |
| pub use scoped::{Scope, ScopedJoinHandle, scope}; |
| #[unstable(feature = "thread_spawn_hook", issue = "132951")] |
| pub use spawnhook::add_spawn_hook; |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub use thread::Thread; |
| |
| // Implementation details used by the thread_local!{} macro. |
| #[doc(hidden)] |
| #[unstable(feature = "thread_local_internals", issue = "none")] |
| pub mod local_impl { |
| pub use super::local::thread_local_process_attrs; |
| pub use crate::sys::thread_local::*; |
| } |
| |
| /// A specialized [`Result`] type for threads. |
| /// |
| /// Indicates the manner in which a thread exited. |
| /// |
| /// The value contained in the `Result::Err` variant |
| /// is the value the thread panicked with; |
| /// that is, the argument the `panic!` macro was called with. |
| /// Unlike with normal errors, this value doesn't implement |
| /// the [`Error`](crate::error::Error) trait. |
| /// |
| /// Thus, a sensible way to handle a thread panic is to either: |
| /// |
| /// 1. propagate the panic with [`std::panic::resume_unwind`] |
| /// 2. or in case the thread is intended to be a subsystem boundary |
| /// that is supposed to isolate system-level failures, |
| /// match on the `Err` variant and handle the panic in an appropriate way |
| /// |
| /// A thread that completes without panicking is considered to exit successfully. |
| /// |
| /// # Examples |
| /// |
| /// Matching on the result of a joined thread: |
| /// |
| /// ```no_run |
| /// use std::{fs, thread, panic}; |
| /// |
| /// fn copy_in_thread() -> thread::Result<()> { |
| /// thread::spawn(|| { |
| /// fs::copy("foo.txt", "bar.txt").unwrap(); |
| /// }).join() |
| /// } |
| /// |
| /// fn main() { |
| /// match copy_in_thread() { |
| /// Ok(_) => println!("copy succeeded"), |
| /// Err(e) => panic::resume_unwind(e), |
| /// } |
| /// } |
| /// ``` |
| /// |
| /// [`Result`]: crate::result::Result |
| /// [`std::panic::resume_unwind`]: crate::panic::resume_unwind |
| #[stable(feature = "rust1", since = "1.0.0")] |
| #[doc(search_unbox)] |
| pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>; |
| |
| fn _assert_sync_and_send() { |
| fn _assert_both<T: Send + Sync>() {} |
| _assert_both::<JoinHandle<()>>(); |
| _assert_both::<Thread>(); |
| } |