Skip to main content

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/// | Apple     | `mach_wait_until`                                                    |
322/// | Other     | `sleep_until` uses [`sleep`] and does not issue a syscall itself     |
323///
324/// [currently]: crate::io#platform-specific-behavior
325/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep
326///
327/// **Disclaimer:** These system calls might change over time.
328///
329/// # Examples
330///
331/// A simple game loop that limits the game to 60 frames per second.
332///
333/// ```no_run
334/// #![feature(thread_sleep_until)]
335/// # use std::time::{Duration, Instant};
336/// # use std::thread;
337/// #
338/// # fn update() {}
339/// # fn render() {}
340/// #
341/// let max_fps = 60.0;
342/// let frame_time = Duration::from_secs_f32(1.0/max_fps);
343/// let mut next_frame = Instant::now();
344/// loop {
345///     thread::sleep_until(next_frame);
346///     next_frame += frame_time;
347///     update();
348///     render();
349/// }
350/// ```
351///
352/// A slow API we must not call too fast and which takes a few
353/// tries before succeeding. By using `sleep_until` the time the
354/// API call takes does not influence when we retry or when we give up
355///
356/// ```no_run
357/// #![feature(thread_sleep_until)]
358/// # use std::time::{Duration, Instant};
359/// # use std::thread;
360/// #
361/// # enum Status {
362/// #     Ready(usize),
363/// #     Waiting,
364/// # }
365/// # fn slow_web_api_call() -> Status { Status::Ready(42) }
366/// #
367/// # const MAX_DURATION: Duration = Duration::from_secs(10);
368/// #
369/// # fn try_api_call() -> Result<usize, ()> {
370/// let deadline = Instant::now() + MAX_DURATION;
371/// let delay = Duration::from_millis(250);
372/// let mut next_attempt = Instant::now();
373/// loop {
374///     if Instant::now() > deadline {
375///         break Err(());
376///     }
377///     if let Status::Ready(data) = slow_web_api_call() {
378///         break Ok(data);
379///     }
380///
381///     next_attempt = deadline.min(next_attempt + delay);
382///     thread::sleep_until(next_attempt);
383/// }
384/// # }
385/// # let _data = try_api_call();
386/// ```
387#[unstable(feature = "thread_sleep_until", issue = "113752")]
388pub fn sleep_until(deadline: Instant) {
389    imp::sleep_until(deadline)
390}
391
392/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
393/// cause undefined behavior if not handled correctly (see #102398 for context).
394struct PanicGuard;
395
396impl Drop for PanicGuard {
397    fn drop(&mut self) {
398        rtabort!("an irrecoverable error occurred while synchronizing threads")
399    }
400}
401
402/// Blocks unless or until the current thread's token is made available.
403///
404/// A call to `park` does not guarantee that the thread will remain parked
405/// forever, and callers should be prepared for this possibility. However,
406/// it is guaranteed that this function will not panic (it may abort the
407/// process if the implementation encounters some rare errors).
408///
409/// # `park` and `unpark`
410///
411/// Every thread is equipped with some basic low-level blocking support, via the
412/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
413/// method. [`park`] blocks the current thread, which can then be resumed from
414/// another thread by calling the [`unpark`] method on the blocked thread's
415/// handle.
416///
417/// Conceptually, each [`Thread`] handle has an associated token, which is
418/// initially not present:
419///
420/// * The [`thread::park`][`park`] function blocks the current thread unless or
421///   until the token is available for its thread handle, at which point it
422///   atomically consumes the token. It may also return *spuriously*, without
423///   consuming the token. [`thread::park_timeout`] does the same, but allows
424///   specifying a maximum time to block the thread for.
425///
426/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
427///   if it wasn't already. Because the token can be held by a thread even if it is currently not
428///   parked, [`unpark`] followed by [`park`] will result in the second call returning immediately.
429///   However, note that to rely on this guarantee, you need to make sure that your `unpark` happens
430///   after all `park` that may be done by other data structures!
431///
432/// The API is typically used by acquiring a handle to the current thread, placing that handle in a
433/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some
434/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point
435/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it
436/// will be woken up properly.
437///
438/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread
439/// without first establishing that it is about to be `park`ing within your code, that `unpark` may
440/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means
441/// you must not call unknown code between setting up for parking and calling `park`; for instance,
442/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a
443/// deadlock.
444///
445/// The motivation for this design is twofold:
446///
447/// * It avoids the need to allocate mutexes and condvars when building new
448///   synchronization primitives; the threads already provide basic
449///   blocking/signaling.
450///
451/// * It can be implemented very efficiently on many platforms.
452///
453/// # Memory Ordering
454///
455/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory
456/// operations performed before a call to `unpark` are made visible to the thread that
457/// consumes the token and returns from `park`. Note that all `park` and `unpark`
458/// operations for a given thread form a total order and _all_ prior `unpark` operations
459/// synchronize-with `park`.
460///
461/// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
462/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
463/// thread form a [release sequence].
464///
465/// Note that being unblocked does not imply a call was made to `unpark`, because
466/// wakeups can also be spurious. For example, a valid, but inefficient,
467/// implementation could have `park` and `unpark` return immediately without doing anything,
468/// making *all* wakeups spurious.
469///
470/// # Examples
471///
472/// ```
473/// use std::thread;
474/// use std::sync::atomic::{Ordering, AtomicBool};
475/// use std::time::Duration;
476///
477/// static QUEUED: AtomicBool = AtomicBool::new(false);
478/// static FLAG: AtomicBool = AtomicBool::new(false);
479///
480/// let parked_thread = thread::spawn(move || {
481///     println!("Thread spawned");
482///     // Signal that we are going to `park`. Between this store and our `park`, there may
483///     // be no other `park`, or else that `park` could consume our `unpark` token!
484///     QUEUED.store(true, Ordering::Release);
485///     // We want to wait until the flag is set. We *could* just spin, but using
486///     // park/unpark is more efficient.
487///     while !FLAG.load(Ordering::Acquire) {
488///         // We can *not* use `println!` here since that could use thread parking internally.
489///         thread::park();
490///         // We *could* get here spuriously, i.e., way before the 10ms below are over!
491///         // But that is no problem, we are in a loop until the flag is set anyway.
492///     }
493///     println!("Flag received");
494/// });
495///
496/// // Let some time pass for the thread to be spawned.
497/// thread::sleep(Duration::from_millis(10));
498///
499/// // Ensure the thread is about to park.
500/// // This is crucial! It guarantees that the `unpark` below is not consumed
501/// // by some other code in the parked thread (e.g. inside `println!`).
502/// while !QUEUED.load(Ordering::Acquire) {
503///     // Spinning is of course inefficient; in practice, this would more likely be
504///     // a dequeue where we have no work to do if there's nobody queued.
505///     std::hint::spin_loop();
506/// }
507///
508/// // Set the flag, and let the thread wake up.
509/// // There is no race condition here: if `unpark`
510/// // happens first, `park` will return immediately.
511/// // There is also no other `park` that could consume this token,
512/// // since we waited until the other thread got queued.
513/// // Hence there is no risk of a deadlock.
514/// FLAG.store(true, Ordering::Release);
515/// println!("Unpark the thread");
516/// parked_thread.thread().unpark();
517///
518/// parked_thread.join().unwrap();
519/// ```
520///
521/// [`Thread`]: super::Thread
522/// [`unpark`]: super::Thread::unpark
523/// [`thread::park_timeout`]: park_timeout
524/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
525#[stable(feature = "rust1", since = "1.0.0")]
526pub fn park() {
527    let guard = PanicGuard;
528    // SAFETY: park_timeout is called on the parker owned by this thread.
529    unsafe {
530        current().park();
531    }
532    // No panic occurred, do not abort.
533    forget(guard);
534}
535
536/// Uses [`park_timeout`].
537///
538/// Blocks unless or until the current thread's token is made available or
539/// the specified duration has been reached (may wake spuriously).
540///
541/// The semantics of this function are equivalent to [`park`] except
542/// that the thread will be blocked for roughly no longer than `dur`. This
543/// method should not be used for precise timing due to anomalies such as
544/// preemption or platform differences that might not cause the maximum
545/// amount of time waited to be precisely `ms` long.
546///
547/// See the [park documentation][`park`] for more detail.
548#[stable(feature = "rust1", since = "1.0.0")]
549#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")]
550pub fn park_timeout_ms(ms: u32) {
551    park_timeout(Duration::from_millis(ms as u64))
552}
553
554/// Blocks unless or until the current thread's token is made available or
555/// the specified duration has been reached (may wake spuriously).
556///
557/// The semantics of this function are equivalent to [`park`][park] except
558/// that the thread will be blocked for roughly no longer than `dur`. This
559/// method should not be used for precise timing due to anomalies such as
560/// preemption or platform differences that might not cause the maximum
561/// amount of time waited to be precisely `dur` long.
562///
563/// See the [park documentation][park] for more details.
564///
565/// # Platform-specific behavior
566///
567/// Platforms which do not support nanosecond precision for sleeping will have
568/// `dur` rounded up to the nearest granularity of time they can sleep for.
569///
570/// # Examples
571///
572/// Waiting for the complete expiration of the timeout:
573///
574/// ```rust,no_run
575/// use std::thread::park_timeout;
576/// use std::time::{Instant, Duration};
577///
578/// let timeout = Duration::from_secs(2);
579/// let beginning_park = Instant::now();
580///
581/// let mut timeout_remaining = timeout;
582/// loop {
583///     park_timeout(timeout_remaining);
584///     let elapsed = beginning_park.elapsed();
585///     if elapsed >= timeout {
586///         break;
587///     }
588///     println!("restarting park_timeout after {elapsed:?}");
589///     timeout_remaining = timeout - elapsed;
590/// }
591/// ```
592#[stable(feature = "park_timeout", since = "1.4.0")]
593pub fn park_timeout(dur: Duration) {
594    let guard = PanicGuard;
595    // SAFETY: park_timeout is called on a handle owned by this thread.
596    unsafe {
597        current().park_timeout(dur);
598    }
599    // No panic occurred, do not abort.
600    forget(guard);
601}
602
603/// Returns an estimate of the default amount of parallelism a program should use.
604///
605/// Parallelism is a resource. A given machine provides a certain capacity for
606/// parallelism, i.e., a bound on the number of computations it can perform
607/// simultaneously. This number often corresponds to the amount of CPUs a
608/// computer has, but it may diverge in various cases.
609///
610/// Host environments such as VMs or container orchestrators may want to
611/// restrict the amount of parallelism made available to programs in them. This
612/// is often done to limit the potential impact of (unintentionally)
613/// resource-intensive programs on other programs running on the same machine.
614///
615/// # Limitations
616///
617/// The purpose of this API is to provide an easy and portable way to query
618/// the default amount of parallelism the program should use. Among other things it
619/// does not expose information on NUMA regions, does not account for
620/// differences in (co)processor capabilities or current system load,
621/// and will not modify the program's global state in order to more accurately
622/// query the amount of available parallelism.
623///
624/// Where both fixed steady-state and burst limits are available the steady-state
625/// capacity will be used to ensure more predictable latencies.
626///
627/// Resource limits can be changed during the runtime of a program, therefore the value is
628/// not cached and instead recomputed every time this function is called. It should not be
629/// called from hot code.
630///
631/// The value returned by this function should be considered a simplified
632/// approximation of the actual amount of parallelism available at any given
633/// time. To get a more detailed or precise overview of the amount of
634/// parallelism available to the program, you may wish to use
635/// platform-specific APIs as well. The following platform limitations currently
636/// apply to `available_parallelism`:
637///
638/// On Windows:
639/// - It may undercount the amount of parallelism available on systems with more
640///   than 64 logical CPUs. However, programs typically need specific support to
641///   take advantage of more than 64 logical CPUs, and in the absence of such
642///   support, the number returned by this function accurately reflects the
643///   number of logical CPUs the program can use by default.
644/// - It may overcount the amount of parallelism available on systems limited by
645///   process-wide affinity masks, or job object limitations.
646///
647/// On Linux:
648/// - It may overcount the amount of parallelism available when limited by a
649///   process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be
650///   queried, e.g. due to sandboxing.
651/// - It may undercount the amount of parallelism if the current thread's affinity mask
652///   does not reflect the process' cpuset, e.g. due to pinned threads.
653/// - If the process is in a cgroup v1 cpu controller, this may need to
654///   scan mountpoints to find the corresponding cgroup v1 controller,
655///   which may take time on systems with large numbers of mountpoints.
656///   (This does not apply to cgroup v2, or to processes not in a
657///   cgroup.)
658/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of
659///   threads, `available_parallelism` cannot know how much of that limit a Rust program should
660///   take, or know in a reliable and race-free way how much of that limit is already taken.
661///
662/// On all targets:
663/// - It may overcount the amount of parallelism available when running in a VM
664/// with CPU usage limits (e.g. an overcommitted host).
665///
666/// # Errors
667///
668/// This function will, but is not limited to, return errors in the following
669/// cases:
670///
671/// - If the amount of parallelism is not known for the target platform.
672/// - If the program lacks permission to query the amount of parallelism made
673///   available to it.
674///
675/// # Examples
676///
677/// ```
678/// # #![allow(dead_code)]
679/// use std::{io, thread};
680///
681/// fn main() -> io::Result<()> {
682///     let count = thread::available_parallelism()?.get();
683///     assert!(count >= 1_usize);
684///     Ok(())
685/// }
686/// ```
687#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable.
688#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`.
689#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality.
690#[stable(feature = "available_parallelism", since = "1.59.0")]
691pub fn available_parallelism() -> io::Result<NonZero<usize>> {
692    imp::available_parallelism()
693}