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}