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

#
std/thread/
functions.rs

    1//! Free functions.
    2
    3use super::builder::Builder;
    4use super::current::current;
    5use super::join_handle::JoinHandle;
    6use crate::mem::forget;
    7use crate::num::NonZero;
    8use crate::sys::thread as imp;
    9use crate::time::{Duration, Instant};
    10use crate::{io, panicking};
    11
    12/// Spawns a new thread, returning a [`JoinHandle`] for it.
    13///
    14/// The join handle provides a [`join`] method that can be used to join the spawned
    15/// thread. If the spawned thread panics, [`join`] will return an [`Err`] containing
    16/// the argument given to [`panic!`].
    17///
    18/// If the join handle is dropped, the spawned thread will implicitly be *detached*.
    19/// In this case, the spawned thread may no longer be joined.
    20/// (It is the responsibility of the program to either eventually join threads it
    21/// creates or detach them; otherwise, a resource leak will result.)
    22///
    23/// This function creates a thread with the default parameters of [`Builder`].
    24/// To specify the new thread's stack size or the name, use [`Builder::spawn`].
    25///
    26/// As you can see in the signature of `spawn` there are two constraints on
    27/// both the closure given to `spawn` and its return value, let's explain them:
    28///
    29/// - The `'static` constraint means that the closure and its return value
    30///   must have a lifetime of the whole program execution. The reason for this
    31///   is that threads can outlive the lifetime they have been created in.
    32///
    33///   Indeed if the thread, and by extension its return value, can outlive their
    34///   caller, we need to make sure that they will be valid afterwards, and since
    35///   we *can't* know when it will return we need to have them valid as long as
    36///   possible, that is until the end of the program, hence the `'static`
    37///   lifetime.
    38/// - The [`Send`] constraint is because the closure will need to be passed
    39///   *by value* from the thread where it is spawned to the new thread. Its
    40///   return value will need to be passed from the new thread to the thread
    41///   where it is `join`ed.
    42///   As a reminder, the [`Send`] marker trait expresses that it is safe to be
    43///   passed from thread to thread. [`Sync`] expresses that it is safe to have a
    44///   reference be passed from thread to thread.
    45///
    46/// # Panics
    47///
    48/// Panics if the OS fails to create a thread; use [`Builder::spawn`]
    49/// to recover from such errors.
    50///
    51/// # Examples
    52///
    53/// Creating a thread.
    54///
    55/// ```
    56/// use std::thread;
    57///
    58/// let handler = thread::spawn(|| {
    59///     // thread code
    60/// });
    61///
    62/// handler.join().unwrap();
    63/// ```
    64///
    65/// As mentioned in the module documentation, threads are usually made to
    66/// communicate using [`channels`], here is how it usually looks.
    67///
    68/// This example also shows how to use `move`, in order to give ownership
    69/// of values to a thread.
    70///
    71/// ```
    72/// use std::thread;
    73/// use std::sync::mpsc::channel;
    74///
    75/// let (tx, rx) = channel();
    76///
    77/// let sender = thread::spawn(move || {
    78///     tx.send("Hello, thread".to_owned())
    79///         .expect("Unable to send on channel");
    80/// });
    81///
    82/// let receiver = thread::spawn(move || {
    83///     let value = rx.recv().expect("Unable to receive from channel");
    84///     println!("{value}");
    85/// });
    86///
    87/// sender.join().expect("The sender thread has panicked");
    88/// receiver.join().expect("The receiver thread has panicked");
    89/// ```
    90///
    91/// A thread can also return a value through its [`JoinHandle`], you can use
    92/// this to make asynchronous computations (futures might be more appropriate
    93/// though).
    94///
    95/// ```
    96/// use std::thread;
    97///
    98/// let computation = thread::spawn(|| {
    99///     // Some expensive computation.
    100///     42
    101/// });
    102///
    103/// let result = computation.join().unwrap();
    104/// println!("{result}");
    105/// ```
    106///
    107/// # Notes
    108///
    109/// This function has the same minimal guarantee regarding "foreign" unwinding operations (e.g.
    110/// an exception thrown from C++ code, or a `panic!` in Rust code compiled or linked with a
    111/// different runtime) as [`catch_unwind`]; namely, if the thread created with `thread::spawn`
    112/// unwinds all the way to the root with such an exception, one of two behaviors are possible,
    113/// and it is unspecified which will occur:
    114///
    115/// * The process aborts.
    116/// * The process does not abort, and [`join`] will return a `Result::Err`
    117///   containing an opaque type.
    118///
    119/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
    120/// [`channels`]: crate::sync::mpsc
    121/// [`join`]: JoinHandle::join
    122/// [`Err`]: crate::result::Result::Err
    123#[stable(feature = "rust1", since = "1.0.0")]
    124#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
    125pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    126where
    127    F: FnOnce() -> T,
    128    F: Send + 'static,
    129    T: Send + 'static,
    130{
    131    Builder::new().spawn(f).expect("failed to spawn thread")
    132}
    133
    134/// Cooperatively gives up a timeslice to the OS scheduler.
    135///
    136/// This calls the underlying OS scheduler's yield primitive, signaling
    137/// that the calling thread is willing to give up its remaining timeslice
    138/// so that the OS may schedule other threads on the CPU.
    139///
    140/// A drawback of yielding in a loop is that if the OS does not have any
    141/// other ready threads to run on the current CPU, the thread will effectively
    142/// busy-wait, which wastes CPU time and energy.
    143///
    144/// Therefore, when waiting for events of interest, a programmer's first
    145/// choice should be to use synchronization devices such as [`channel`]s,
    146/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are
    147/// implemented in a blocking manner, giving up the CPU until the event
    148/// of interest has occurred which avoids repeated yielding.
    149///
    150/// `yield_now` should thus be used only rarely, mostly in situations where
    151/// repeated polling is required because there is no other suitable way to
    152/// learn when an event of interest has occurred.
    153///
    154/// # Examples
    155///
    156/// ```
    157/// use std::thread;
    158///
    159/// thread::yield_now();
    160/// ```
    161///
    162/// [`channel`]: crate::sync::mpsc
    163/// [`join`]: JoinHandle::join
    164/// [`Condvar`]: crate::sync::Condvar
    165/// [`Mutex`]: crate::sync::Mutex
    166#[stable(feature = "rust1", since = "1.0.0")]
    167pub fn yield_now() {
    168    imp::yield_now()
    169}
    170
    171/// Determines whether the current thread is unwinding because of panic.
    172///
    173/// A common use of this feature is to poison shared resources when writing
    174/// unsafe code, by checking `panicking` when the `drop` is called.
    175///
    176/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex]
    177/// already poison themselves when a thread panics while holding the lock.
    178///
    179/// This can also be used in multithreaded applications, in order to send a
    180/// message to other threads warning that a thread has panicked (e.g., for
    181/// monitoring purposes).
    182///
    183/// # Examples
    184///
    185/// ```should_panic
    186/// use std::thread;
    187///
    188/// struct SomeStruct;
    189///
    190/// impl Drop for SomeStruct {
    191///     fn drop(&mut self) {
    192///         if thread::panicking() {
    193///             println!("dropped while unwinding");
    194///         } else {
    195///             println!("dropped while not unwinding");
    196///         }
    197///     }
    198/// }
    199///
    200/// {
    201///     print!("a: ");
    202///     let a = SomeStruct;
    203/// }
    204///
    205/// {
    206///     print!("b: ");
    207///     let b = SomeStruct;
    208///     panic!()
    209/// }
    210/// ```
    211///
    212/// [Mutex]: crate::sync::Mutex
    213#[inline]
    214#[must_use]
    215#[stable(feature = "rust1", since = "1.0.0")]
    216pub fn panicking() -> bool {
    217    panicking::panicking()
    218}
    219
    220/// Uses [`sleep`].
    221///
    222/// Puts the current thread to sleep for at least the specified amount of time.
    223///
    224/// The thread may sleep longer than the duration specified due to scheduling
    225/// specifics or platform-dependent functionality. It will never sleep less.
    226///
    227/// This function is blocking, and should not be used in `async` functions.
    228///
    229/// # Platform-specific behavior
    230///
    231/// On Unix platforms, the underlying syscall may be interrupted by a
    232/// spurious wakeup or signal handler. To ensure the sleep occurs for at least
    233/// the specified duration, this function may invoke that system call multiple
    234/// times.
    235///
    236/// # Examples
    237///
    238/// ```no_run
    239/// use std::thread;
    240///
    241/// // Let's sleep for 2 seconds:
    242/// thread::sleep_ms(2000);
    243/// ```
    244#[stable(feature = "rust1", since = "1.0.0")]
    245#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")]
    246pub fn sleep_ms(ms: u32) {
    247    sleep(Duration::from_millis(ms as u64))
    248}
    249
    250/// Puts the current thread to sleep for at least the specified amount of time.
    251///
    252/// The thread may sleep longer than the duration specified due to scheduling
    253/// specifics or platform-dependent functionality. It will never sleep less.
    254///
    255/// This function is blocking, and should not be used in `async` functions.
    256///
    257/// # Platform-specific behavior
    258///
    259/// On Unix platforms, the underlying syscall may be interrupted by a
    260/// spurious wakeup or signal handler. To ensure the sleep occurs for at least
    261/// the specified duration, this function may invoke that system call multiple
    262/// times.
    263/// Platforms which do not support nanosecond precision for sleeping will
    264/// have `dur` rounded up to the nearest granularity of time they can sleep for.
    265///
    266/// Currently, specifying a zero duration on Unix platforms returns immediately
    267/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows
    268/// platforms the underlying [`Sleep`] syscall is always invoked.
    269/// If the intention is to yield the current time-slice you may want to use
    270/// [`yield_now`] instead.
    271///
    272/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep
    273/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
    274///
    275/// # Examples
    276///
    277/// ```no_run
    278/// use std::{thread, time};
    279///
    280/// let ten_millis = time::Duration::from_millis(10);
    281/// let now = time::Instant::now();
    282///
    283/// thread::sleep(ten_millis);
    284///
    285/// assert!(now.elapsed() >= ten_millis);
    286/// ```
    287#[stable(feature = "thread_sleep", since = "1.4.0")]
    288pub fn sleep(dur: Duration) {
    289    imp::sleep(dur)
    290}
    291
    292/// Puts the current thread to sleep until the specified deadline has passed.
    293///
    294/// The thread may still be asleep after the deadline specified due to
    295/// scheduling specifics or platform-dependent functionality. It will never
    296/// wake before.
    297///
    298/// This function is blocking, and should not be used in `async` functions.
    299///
    300/// # Platform-specific behavior
    301///
    302/// In most cases this function will call an OS specific function. Where that
    303/// is not supported [`sleep`] is used. Those platforms are referred to as other
    304/// in the table below.
    305///
    306/// # Underlying System calls
    307///
    308/// The following system calls are [currently] being used:
    309///
    310/// |  Platform |               System call                                            |
    311/// |-----------|----------------------------------------------------------------------|
    312/// | Linux     | [clock_nanosleep] (Monotonic clock)                                  |
    313/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)]                        |
    314/// | Android   | [clock_nanosleep] (Monotonic Clock)]                                 |
    315/// | Solaris   | [clock_nanosleep] (Monotonic Clock)]                                 |
    316/// | Illumos   | [clock_nanosleep] (Monotonic Clock)]                                 |
    317/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)]                                 |
    318/// | Hurd      | [clock_nanosleep] (Monotonic Clock)]                                 |
    319/// | Fuchsia   | [clock_nanosleep] (Monotonic Clock)]                                 |
    320/// | Vxworks   | [clock_nanosleep] (Monotonic Clock)]                                 |
    321/// | Other     | `sleep_until` uses [`sleep`] and does not issue a syscall itself     |
    322///
    323/// [currently]: crate::io#platform-specific-behavior
    324/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep
    325///
    326/// **Disclaimer:** These system calls might change over time.
    327///
    328/// # Examples
    329///
    330/// A simple game loop that limits the game to 60 frames per second.
    331///
    332/// ```no_run
    333/// #![feature(thread_sleep_until)]
    334/// # use std::time::{Duration, Instant};
    335/// # use std::thread;
    336/// #
    337/// # fn update() {}
    338/// # fn render() {}
    339/// #
    340/// let max_fps = 60.0;
    341/// let frame_time = Duration::from_secs_f32(1.0/max_fps);
    342/// let mut next_frame = Instant::now();
    343/// loop {
    344///     thread::sleep_until(next_frame);
    345///     next_frame += frame_time;
    346///     update();
    347///     render();
    348/// }
    349/// ```
    350///
    351/// A slow API we must not call too fast and which takes a few
    352/// tries before succeeding. By using `sleep_until` the time the
    353/// API call takes does not influence when we retry or when we give up
    354///
    355/// ```no_run
    356/// #![feature(thread_sleep_until)]
    357/// # use std::time::{Duration, Instant};
    358/// # use std::thread;
    359/// #
    360/// # enum Status {
    361/// #     Ready(usize),
    362/// #     Waiting,
    363/// # }
    364/// # fn slow_web_api_call() -> Status { Status::Ready(42) }
    365/// #
    366/// # const MAX_DURATION: Duration = Duration::from_secs(10);
    367/// #
    368/// # fn try_api_call() -> Result<usize, ()> {
    369/// let deadline = Instant::now() + MAX_DURATION;
    370/// let delay = Duration::from_millis(250);
    371/// let mut next_attempt = Instant::now();
    372/// loop {
    373///     if Instant::now() > deadline {
    374///         break Err(());
    375///     }
    376///     if let Status::Ready(data) = slow_web_api_call() {
    377///         break Ok(data);
    378///     }
    379///
    380///     next_attempt = deadline.min(next_attempt + delay);
    381///     thread::sleep_until(next_attempt);
    382/// }
    383/// # }
    384/// # let _data = try_api_call();
    385/// ```
    386#[unstable(feature = "thread_sleep_until", issue = "113752")]
    387pub fn sleep_until(deadline: Instant) {
    388    imp::sleep_until(deadline)
    389}
    390
    391/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
    392/// cause undefined behavior if not handled correctly (see #102398 for context).
    393struct PanicGuard;
    394
    395impl Drop for PanicGuard {
    396    fn drop(&mut self) {
    397        rtabort!("an irrecoverable error occurred while synchronizing threads")
    398    }
    399}
    400
    401/// Blocks unless or until the current thread's token is made available.
    402///
    403/// A call to `park` does not guarantee that the thread will remain parked
    404/// forever, and callers should be prepared for this possibility. However,
    405/// it is guaranteed that this function will not panic (it may abort the
    406/// process if the implementation encounters some rare errors).
    407///
    408/// # `park` and `unpark`
    409///
    410/// Every thread is equipped with some basic low-level blocking support, via the
    411/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
    412/// method. [`park`] blocks the current thread, which can then be resumed from
    413/// another thread by calling the [`unpark`] method on the blocked thread's
    414/// handle.
    415///
    416/// Conceptually, each [`Thread`] handle has an associated token, which is
    417/// initially not present:
    418///
    419/// * The [`thread::park`][`park`] function blocks the current thread unless or
    420///   until the token is available for its thread handle, at which point it
    421///   atomically consumes the token. It may also return *spuriously*, without
    422///   consuming the token. [`thread::park_timeout`] does the same, but allows
    423///   specifying a maximum time to block the thread for.
    424///
    425/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
    426///   if it wasn't already. Because the token can be held by a thread even if it is currently not
    427///   parked, [`unpark`] followed by [`park`] will result in the second call returning immediately.
    428///   However, note that to rely on this guarantee, you need to make sure that your `unpark` happens
    429///   after all `park` that may be done by other data structures!
    430///
    431/// The API is typically used by acquiring a handle to the current thread, placing that handle in a
    432/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some
    433/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point
    434/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it
    435/// will be woken up properly.
    436///
    437/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread
    438/// without first establishing that it is about to be `park`ing within your code, that `unpark` may
    439/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means
    440/// you must not call unknown code between setting up for parking and calling `park`; for instance,
    441/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a
    442/// deadlock.
    443///
    444/// The motivation for this design is twofold:
    445///
    446/// * It avoids the need to allocate mutexes and condvars when building new
    447///   synchronization primitives; the threads already provide basic
    448///   blocking/signaling.
    449///
    450/// * It can be implemented very efficiently on many platforms.
    451///
    452/// # Memory Ordering
    453///
    454/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory
    455/// operations performed before a call to `unpark` are made visible to the thread that
    456/// consumes the token and returns from `park`. Note that all `park` and `unpark`
    457/// operations for a given thread form a total order and _all_ prior `unpark` operations
    458/// synchronize-with `park`.
    459///
    460/// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
    461/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
    462/// thread form a [release sequence].
    463///
    464/// Note that being unblocked does not imply a call was made to `unpark`, because
    465/// wakeups can also be spurious. For example, a valid, but inefficient,
    466/// implementation could have `park` and `unpark` return immediately without doing anything,
    467/// making *all* wakeups spurious.
    468///
    469/// # Examples
    470///
    471/// ```
    472/// use std::thread;
    473/// use std::sync::atomic::{Ordering, AtomicBool};
    474/// use std::time::Duration;
    475///
    476/// static QUEUED: AtomicBool = AtomicBool::new(false);
    477/// static FLAG: AtomicBool = AtomicBool::new(false);
    478///
    479/// let parked_thread = thread::spawn(move || {
    480///     println!("Thread spawned");
    481///     // Signal that we are going to `park`. Between this store and our `park`, there may
    482///     // be no other `park`, or else that `park` could consume our `unpark` token!
    483///     QUEUED.store(true, Ordering::Release);
    484///     // We want to wait until the flag is set. We *could* just spin, but using
    485///     // park/unpark is more efficient.
    486///     while !FLAG.load(Ordering::Acquire) {
    487///         // We can *not* use `println!` here since that could use thread parking internally.
    488///         thread::park();
    489///         // We *could* get here spuriously, i.e., way before the 10ms below are over!
    490///         // But that is no problem, we are in a loop until the flag is set anyway.
    491///     }
    492///     println!("Flag received");
    493/// });
    494///
    495/// // Let some time pass for the thread to be spawned.
    496/// thread::sleep(Duration::from_millis(10));
    497///
    498/// // Ensure the thread is about to park.
    499/// // This is crucial! It guarantees that the `unpark` below is not consumed
    500/// // by some other code in the parked thread (e.g. inside `println!`).
    501/// while !QUEUED.load(Ordering::Acquire) {
    502///     // Spinning is of course inefficient; in practice, this would more likely be
    503///     // a dequeue where we have no work to do if there's nobody queued.
    504///     std::hint::spin_loop();
    505/// }
    506///
    507/// // Set the flag, and let the thread wake up.
    508/// // There is no race condition here: if `unpark`
    509/// // happens first, `park` will return immediately.
    510/// // There is also no other `park` that could consume this token,
    511/// // since we waited until the other thread got queued.
    512/// // Hence there is no risk of a deadlock.
    513/// FLAG.store(true, Ordering::Release);
    514/// println!("Unpark the thread");
    515/// parked_thread.thread().unpark();
    516///
    517/// parked_thread.join().unwrap();
    518/// ```
    519///
    520/// [`Thread`]: super::Thread
    521/// [`unpark`]: super::Thread::unpark
    522/// [`thread::park_timeout`]: park_timeout
    523/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
    524#[stable(feature = "rust1", since = "1.0.0")]
    525pub fn park() {
    526    let guard = PanicGuard;
    527    // SAFETY: park_timeout is called on the parker owned by this thread.
    528    unsafe {
    529        current().park();
    530    }
    531    // No panic occurred, do not abort.
    532    forget(guard);
    533}
    534
    535/// Uses [`park_timeout`].
    536///
    537/// Blocks unless or until the current thread's token is made available or
    538/// the specified duration has been reached (may wake spuriously).
    539///
    540/// The semantics of this function are equivalent to [`park`] except
    541/// that the thread will be blocked for roughly no longer than `dur`. This
    542/// method should not be used for precise timing due to anomalies such as
    543/// preemption or platform differences that might not cause the maximum
    544/// amount of time waited to be precisely `ms` long.
    545///
    546/// See the [park documentation][`park`] for more detail.
    547#[stable(feature = "rust1", since = "1.0.0")]
    548#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")]
    549pub fn park_timeout_ms(ms: u32) {
    550    park_timeout(Duration::from_millis(ms as u64))
    551}
    552
    553/// Blocks unless or until the current thread's token is made available or
    554/// the specified duration has been reached (may wake spuriously).
    555///
    556/// The semantics of this function are equivalent to [`park`][park] except
    557/// that the thread will be blocked for roughly no longer than `dur`. This
    558/// method should not be used for precise timing due to anomalies such as
    559/// preemption or platform differences that might not cause the maximum
    560/// amount of time waited to be precisely `dur` long.
    561///
    562/// See the [park documentation][park] for more details.
    563///
    564/// # Platform-specific behavior
    565///
    566/// Platforms which do not support nanosecond precision for sleeping will have
    567/// `dur` rounded up to the nearest granularity of time they can sleep for.
    568///
    569/// # Examples
    570///
    571/// Waiting for the complete expiration of the timeout:
    572///
    573/// ```rust,no_run
    574/// use std::thread::park_timeout;
    575/// use std::time::{Instant, Duration};
    576///
    577/// let timeout = Duration::from_secs(2);
    578/// let beginning_park = Instant::now();
    579///
    580/// let mut timeout_remaining = timeout;
    581/// loop {
    582///     park_timeout(timeout_remaining);
    583///     let elapsed = beginning_park.elapsed();
    584///     if elapsed >= timeout {
    585///         break;
    586///     }
    587///     println!("restarting park_timeout after {elapsed:?}");
    588///     timeout_remaining = timeout - elapsed;
    589/// }
    590/// ```
    591#[stable(feature = "park_timeout", since = "1.4.0")]
    592pub fn park_timeout(dur: Duration) {
    593    let guard = PanicGuard;
    594    // SAFETY: park_timeout is called on a handle owned by this thread.
    595    unsafe {
    596        current().park_timeout(dur);
    597    }
    598    // No panic occurred, do not abort.
    599    forget(guard);
    600}
    601
    602/// Returns an estimate of the default amount of parallelism a program should use.
    603///
    604/// Parallelism is a resource. A given machine provides a certain capacity for
    605/// parallelism, i.e., a bound on the number of computations it can perform
    606/// simultaneously. This number often corresponds to the amount of CPUs a
    607/// computer has, but it may diverge in various cases.
    608///
    609/// Host environments such as VMs or container orchestrators may want to
    610/// restrict the amount of parallelism made available to programs in them. This
    611/// is often done to limit the potential impact of (unintentionally)
    612/// resource-intensive programs on other programs running on the same machine.
    613///
    614/// # Limitations
    615///
    616/// The purpose of this API is to provide an easy and portable way to query
    617/// the default amount of parallelism the program should use. Among other things it
    618/// does not expose information on NUMA regions, does not account for
    619/// differences in (co)processor capabilities or current system load,
    620/// and will not modify the program's global state in order to more accurately
    621/// query the amount of available parallelism.
    622///
    623/// Where both fixed steady-state and burst limits are available the steady-state
    624/// capacity will be used to ensure more predictable latencies.
    625///
    626/// Resource limits can be changed during the runtime of a program, therefore the value is
    627/// not cached and instead recomputed every time this function is called. It should not be
    628/// called from hot code.
    629///
    630/// The value returned by this function should be considered a simplified
    631/// approximation of the actual amount of parallelism available at any given
    632/// time. To get a more detailed or precise overview of the amount of
    633/// parallelism available to the program, you may wish to use
    634/// platform-specific APIs as well. The following platform limitations currently
    635/// apply to `available_parallelism`:
    636///
    637/// On Windows:
    638/// - It may undercount the amount of parallelism available on systems with more
    639///   than 64 logical CPUs. However, programs typically need specific support to
    640///   take advantage of more than 64 logical CPUs, and in the absence of such
    641///   support, the number returned by this function accurately reflects the
    642///   number of logical CPUs the program can use by default.
    643/// - It may overcount the amount of parallelism available on systems limited by
    644///   process-wide affinity masks, or job object limitations.
    645///
    646/// On Linux:
    647/// - It may overcount the amount of parallelism available when limited by a
    648///   process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be
    649///   queried, e.g. due to sandboxing.
    650/// - It may undercount the amount of parallelism if the current thread's affinity mask
    651///   does not reflect the process' cpuset, e.g. due to pinned threads.
    652/// - If the process is in a cgroup v1 cpu controller, this may need to
    653///   scan mountpoints to find the corresponding cgroup v1 controller,
    654///   which may take time on systems with large numbers of mountpoints.
    655///   (This does not apply to cgroup v2, or to processes not in a
    656///   cgroup.)
    657/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of
    658///   threads, `available_parallelism` cannot know how much of that limit a Rust program should
    659///   take, or know in a reliable and race-free way how much of that limit is already taken.
    660///
    661/// On all targets:
    662/// - It may overcount the amount of parallelism available when running in a VM
    663/// with CPU usage limits (e.g. an overcommitted host).
    664///
    665/// # Errors
    666///
    667/// This function will, but is not limited to, return errors in the following
    668/// cases:
    669///
    670/// - If the amount of parallelism is not known for the target platform.
    671/// - If the program lacks permission to query the amount of parallelism made
    672///   available to it.
    673///
    674/// # Examples
    675///
    676/// ```
    677/// # #![allow(dead_code)]
    678/// use std::{io, thread};
    679///
    680/// fn main() -> io::Result<()> {
    681///     let count = thread::available_parallelism()?.get();
    682///     assert!(count >= 1_usize);
    683///     Ok(())
    684/// }
    685/// ```
    686#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable.
    687#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`.
    688#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality.
    689#[stable(feature = "available_parallelism", since = "1.59.0")]
    690pub fn available_parallelism() -> io::Result<NonZero<usize>> {
    691    imp::available_parallelism()
    692}