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 panicking.
172///
173/// This returns `true` both when the thread is unwinding due to a panic,
174/// or executing a panic hook. Note that the latter case will still happen
175/// when `panic=abort` is set.
176///
177/// A common use of this feature is to poison shared resources when writing
178/// unsafe code, by checking `panicking` when the `drop` is called.
179///
180/// This is usually not needed when writing safe code, as [`Mutex`es][Mutex]
181/// already poison themselves when a thread panics while holding the lock.
182///
183/// This can also be used in multithreaded applications, in order to send a
184/// message to other threads warning that a thread has panicked (e.g., for
185/// monitoring purposes).
186///
187/// # Examples
188///
189/// ```should_panic
190/// use std::thread;
191///
192/// struct SomeStruct;
193///
194/// impl Drop for SomeStruct {
195///     fn drop(&mut self) {
196///         if thread::panicking() {
197///             println!("dropped while unwinding");
198///         } else {
199///             println!("dropped while not unwinding");
200///         }
201///     }
202/// }
203///
204/// {
205///     print!("a: ");
206///     let a = SomeStruct;
207/// }
208///
209/// {
210///     print!("b: ");
211///     let b = SomeStruct;
212///     panic!()
213/// }
214/// ```
215///
216/// [Mutex]: crate::sync::Mutex
217#[inline]
218#[must_use]
219#[stable(feature = "rust1", since = "1.0.0")]
220pub fn panicking() -> bool {
221    panicking::panicking()
222}
223
224/// Uses [`sleep`].
225///
226/// Puts the current thread to sleep for at least the specified amount of time.
227///
228/// The thread may sleep longer than the duration specified due to scheduling
229/// specifics or platform-dependent functionality. It will never sleep less.
230///
231/// This function is blocking, and should not be used in `async` functions.
232///
233/// # Platform-specific behavior
234///
235/// On Unix platforms, the underlying syscall may be interrupted by a
236/// spurious wakeup or signal handler. To ensure the sleep occurs for at least
237/// the specified duration, this function may invoke that system call multiple
238/// times.
239///
240/// # Examples
241///
242/// ```no_run
243/// use std::thread;
244///
245/// // Let's sleep for 2 seconds:
246/// thread::sleep_ms(2000);
247/// ```
248#[stable(feature = "rust1", since = "1.0.0")]
249#[deprecated(since = "1.6.0", note = "replaced by `std::thread::sleep`")]
250pub fn sleep_ms(ms: u32) {
251    sleep(Duration::from_millis(ms as u64))
252}
253
254/// Puts the current thread to sleep for at least the specified amount of time.
255///
256/// The thread may sleep longer than the duration specified due to scheduling
257/// specifics or platform-dependent functionality. It will never sleep less.
258///
259/// This function is blocking, and should not be used in `async` functions.
260///
261/// # Platform-specific behavior
262///
263/// On Unix platforms, the underlying syscall may be interrupted by a
264/// spurious wakeup or signal handler. To ensure the sleep occurs for at least
265/// the specified duration, this function may invoke that system call multiple
266/// times.
267/// Platforms which do not support nanosecond precision for sleeping will
268/// have `dur` rounded up to the nearest granularity of time they can sleep for.
269///
270/// Currently, specifying a zero duration on Unix platforms returns immediately
271/// without invoking the underlying [`nanosleep`] syscall, whereas on Windows
272/// platforms the underlying [`Sleep`] syscall is always invoked.
273/// If the intention is to yield the current time-slice you may want to use
274/// [`yield_now`] instead.
275///
276/// [`nanosleep`]: https://linux.die.net/man/2/nanosleep
277/// [`Sleep`]: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
278///
279/// # Examples
280///
281/// ```no_run
282/// use std::{thread, time};
283///
284/// let ten_millis = time::Duration::from_millis(10);
285/// let now = time::Instant::now();
286///
287/// thread::sleep(ten_millis);
288///
289/// assert!(now.elapsed() >= ten_millis);
290/// ```
291#[stable(feature = "thread_sleep", since = "1.4.0")]
292pub fn sleep(dur: Duration) {
293    imp::sleep(dur)
294}
295
296/// Puts the current thread to sleep until the specified deadline has passed.
297///
298/// If the deadline has already passed at the time this function is called, it
299/// will return immediately. Note that the thread may still be asleep after the
300/// deadline specified due to scheduling specifics or platform-dependent
301/// functionality. It will never wake before.
302///
303/// This function is blocking, and should not be used in `async` functions.
304///
305/// # Platform-specific behavior
306///
307/// In most cases this function will call an OS specific function. Where that
308/// is not supported [`sleep`] is used. Those platforms are referred to as other
309/// in the table below.
310///
311/// # Underlying System calls
312///
313/// The following system calls are [currently] being used:
314///
315/// |  Platform |               System call                                            |
316/// |-----------|----------------------------------------------------------------------|
317/// | Linux     | [`clock_nanosleep`] (Monotonic Clock)                                |
318/// | BSD except OpenBSD | [`clock_nanosleep`] (Monotonic Clock)                       |
319/// | Android   | [`clock_nanosleep`] (Monotonic Clock)                                |
320/// | Solaris   | [`clock_nanosleep`] (Monotonic Clock)                                |
321/// | Illumos   | [`clock_nanosleep`] (Monotonic Clock)                                |
322/// | Dragonfly | [`clock_nanosleep`] (Monotonic Clock)                                |
323/// | Hurd      | [`clock_nanosleep`] (Monotonic Clock)                                |
324/// | Vxworks   | [`clock_nanosleep`] (Monotonic Clock)                                |
325/// | Apple     | `mach_wait_until`                                                    |
326/// | Fuchsia   | [`zx_nanosleep`]                                                     |
327/// | Other     | `sleep_until` uses [`sleep`] and does not issue a syscall itself     |
328///
329/// [currently]: crate::io#platform-specific-behavior
330/// [`clock_nanosleep`]: https://linux.die.net/man/3/clock_nanosleep
331/// [`zx_nanosleep`]: https://fuchsia.dev/reference/syscalls/nanosleep
332///
333/// **Disclaimer:** These system calls might change over time.
334///
335/// # Examples
336///
337/// A simple game loop that limits the game to 60 frames per second.
338///
339/// ```no_run
340/// #![feature(thread_sleep_until)]
341/// # use std::time::{Duration, Instant};
342/// # use std::thread;
343/// #
344/// # fn update() {}
345/// # fn render() {}
346/// #
347/// let max_fps = 60.0;
348/// let frame_time = Duration::from_secs_f32(1.0/max_fps);
349/// let mut next_frame = Instant::now();
350/// loop {
351///     thread::sleep_until(next_frame);
352///     next_frame += frame_time;
353///     update();
354///     render();
355/// }
356/// ```
357///
358/// A slow API we must not call too fast and which takes a few
359/// tries before succeeding. By using `sleep_until` the time the
360/// API call takes does not influence when we retry or when we give up
361///
362/// ```no_run
363/// #![feature(thread_sleep_until)]
364/// # use std::time::{Duration, Instant};
365/// # use std::thread;
366/// #
367/// # enum Status {
368/// #     Ready(usize),
369/// #     Waiting,
370/// # }
371/// # fn slow_web_api_call() -> Status { Status::Ready(42) }
372/// #
373/// # const MAX_DURATION: Duration = Duration::from_secs(10);
374/// #
375/// # fn try_api_call() -> Result<usize, ()> {
376/// let deadline = Instant::now() + MAX_DURATION;
377/// let delay = Duration::from_millis(250);
378/// let mut next_attempt = Instant::now();
379/// loop {
380///     if Instant::now() > deadline {
381///         break Err(());
382///     }
383///     if let Status::Ready(data) = slow_web_api_call() {
384///         break Ok(data);
385///     }
386///
387///     next_attempt = deadline.min(next_attempt + delay);
388///     thread::sleep_until(next_attempt);
389/// }
390/// # }
391/// # let _data = try_api_call();
392/// ```
393#[unstable(feature = "thread_sleep_until", issue = "113752")]
394pub fn sleep_until(deadline: Instant) {
395    imp::sleep_until(deadline)
396}
397
398/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
399/// cause undefined behavior if not handled correctly (see #102398 for context).
400struct PanicGuard;
401
402impl Drop for PanicGuard {
403    fn drop(&mut self) {
404        rtabort!("an irrecoverable error occurred while synchronizing threads")
405    }
406}
407
408/// Blocks unless or until the current thread's token is made available.
409///
410/// A call to `park` does not guarantee that the thread will remain parked
411/// forever, and callers should be prepared for this possibility. However,
412/// it is guaranteed that this function will not panic (it may abort the
413/// process if the implementation encounters some rare errors).
414///
415/// # `park` and `unpark`
416///
417/// Every thread is equipped with some basic low-level blocking support, via the
418/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
419/// method. [`park`] blocks the current thread, which can then be resumed from
420/// another thread by calling the [`unpark`] method on the blocked thread's
421/// handle.
422///
423/// Conceptually, each [`Thread`] handle has an associated token, which is
424/// initially not present:
425///
426/// * The [`thread::park`][`park`] function blocks the current thread unless or
427///   until the token is available for its thread handle, at which point it
428///   atomically consumes the token. It may also return *spuriously*, without
429///   consuming the token. [`thread::park_timeout`] does the same, but allows
430///   specifying a maximum time to block the thread for.
431///
432/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
433///   if it wasn't already. Because the token can be held by a thread even if it is currently not
434///   parked, [`unpark`] followed by [`park`] will result in the second call returning immediately.
435///   However, note that to rely on this guarantee, you need to make sure that your `unpark` happens
436///   after all `park` that may be done by other data structures!
437///
438/// The API is typically used by acquiring a handle to the current thread, placing that handle in a
439/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some
440/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point
441/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it
442/// will be woken up properly.
443///
444/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread
445/// without first establishing that it is about to be `park`ing within your code, that `unpark` may
446/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means
447/// you must not call unknown code between setting up for parking and calling `park`; for instance,
448/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a
449/// deadlock.
450///
451/// The motivation for this design is twofold:
452///
453/// * It avoids the need to allocate mutexes and condvars when building new
454///   synchronization primitives; the threads already provide basic
455///   blocking/signaling.
456///
457/// * It can be implemented very efficiently on many platforms.
458///
459/// # Memory Ordering
460///
461/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory
462/// operations performed before a call to `unpark` are made visible to the thread that
463/// consumes the token and returns from `park`. Note that all `park` and `unpark`
464/// operations for a given thread form a total order and _all_ prior `unpark` operations
465/// synchronize-with `park`.
466///
467/// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
468/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
469/// thread form a [release sequence].
470///
471/// Note that being unblocked does not imply a call was made to `unpark`, because
472/// wakeups can also be spurious. For example, a valid, but inefficient,
473/// implementation could have `park` and `unpark` return immediately without doing anything,
474/// making *all* wakeups spurious.
475///
476/// # Examples
477///
478/// ```
479/// use std::thread;
480/// use std::sync::atomic::{Ordering, AtomicBool};
481/// use std::time::Duration;
482///
483/// static QUEUED: AtomicBool = AtomicBool::new(false);
484/// static FLAG: AtomicBool = AtomicBool::new(false);
485///
486/// let parked_thread = thread::spawn(move || {
487///     println!("Thread spawned");
488///     // Signal that we are going to `park`. Between this store and our `park`, there may
489///     // be no other `park`, or else that `park` could consume our `unpark` token!
490///     QUEUED.store(true, Ordering::Release);
491///     // We want to wait until the flag is set. We *could* just spin, but using
492///     // park/unpark is more efficient.
493///     while !FLAG.load(Ordering::Acquire) {
494///         // We can *not* use `println!` here since that could use thread parking internally.
495///         thread::park();
496///         // We *could* get here spuriously, i.e., way before the 10ms below are over!
497///         // But that is no problem, we are in a loop until the flag is set anyway.
498///     }
499///     println!("Flag received");
500/// });
501///
502/// // Let some time pass for the thread to be spawned.
503/// thread::sleep(Duration::from_millis(10));
504///
505/// // Ensure the thread is about to park.
506/// // This is crucial! It guarantees that the `unpark` below is not consumed
507/// // by some other code in the parked thread (e.g. inside `println!`).
508/// while !QUEUED.load(Ordering::Acquire) {
509///     // Spinning is of course inefficient; in practice, this would more likely be
510///     // a dequeue where we have no work to do if there's nobody queued.
511///     std::hint::spin_loop();
512/// }
513///
514/// // Set the flag, and let the thread wake up.
515/// // There is no race condition here: if `unpark`
516/// // happens first, `park` will return immediately.
517/// // There is also no other `park` that could consume this token,
518/// // since we waited until the other thread got queued.
519/// // Hence there is no risk of a deadlock.
520/// FLAG.store(true, Ordering::Release);
521/// println!("Unpark the thread");
522/// parked_thread.thread().unpark();
523///
524/// parked_thread.join().unwrap();
525/// ```
526///
527/// [`Thread`]: super::Thread
528/// [`unpark`]: super::Thread::unpark
529/// [`thread::park_timeout`]: park_timeout
530/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
531#[stable(feature = "rust1", since = "1.0.0")]
532pub fn park() {
533    let guard = PanicGuard;
534    // SAFETY: park_timeout is called on the parker owned by this thread.
535    unsafe {
536        current().park();
537    }
538    // No panic occurred, do not abort.
539    forget(guard);
540}
541
542/// Uses [`park_timeout`].
543///
544/// Blocks unless or until the current thread's token is made available or
545/// the specified duration has been reached (may wake spuriously).
546///
547/// The semantics of this function are equivalent to [`park`] except
548/// that the thread will be blocked for roughly no longer than `dur`. This
549/// method should not be used for precise timing due to anomalies such as
550/// preemption or platform differences that might not cause the maximum
551/// amount of time waited to be precisely `ms` long.
552///
553/// See the [park documentation][`park`] for more detail.
554#[stable(feature = "rust1", since = "1.0.0")]
555#[deprecated(since = "1.6.0", note = "replaced by `std::thread::park_timeout`")]
556pub fn park_timeout_ms(ms: u32) {
557    park_timeout(Duration::from_millis(ms as u64))
558}
559
560/// Blocks unless or until the current thread's token is made available or
561/// the specified duration has been reached (may wake spuriously).
562///
563/// The semantics of this function are equivalent to [`park`][park] except
564/// that the thread will be blocked for roughly no longer than `dur`. This
565/// method should not be used for precise timing due to anomalies such as
566/// preemption or platform differences that might not cause the maximum
567/// amount of time waited to be precisely `dur` long.
568///
569/// See the [park documentation][park] for more details.
570///
571/// # Platform-specific behavior
572///
573/// Platforms which do not support nanosecond precision for sleeping will have
574/// `dur` rounded up to the nearest granularity of time they can sleep for.
575///
576/// # Examples
577///
578/// Waiting for the complete expiration of the timeout:
579///
580/// ```rust,no_run
581/// use std::thread::park_timeout;
582/// use std::time::{Instant, Duration};
583///
584/// let timeout = Duration::from_secs(2);
585/// let beginning_park = Instant::now();
586///
587/// let mut timeout_remaining = timeout;
588/// loop {
589///     park_timeout(timeout_remaining);
590///     let elapsed = beginning_park.elapsed();
591///     if elapsed >= timeout {
592///         break;
593///     }
594///     println!("restarting park_timeout after {elapsed:?}");
595///     timeout_remaining = timeout - elapsed;
596/// }
597/// ```
598#[stable(feature = "park_timeout", since = "1.4.0")]
599pub fn park_timeout(dur: Duration) {
600    let guard = PanicGuard;
601    // SAFETY: park_timeout is called on a handle owned by this thread.
602    unsafe {
603        current().park_timeout(dur);
604    }
605    // No panic occurred, do not abort.
606    forget(guard);
607}
608
609/// Returns an estimate of the default amount of parallelism a program should use.
610///
611/// Parallelism is a resource. A given machine provides a certain capacity for
612/// parallelism, i.e., a bound on the number of computations it can perform
613/// simultaneously. This number often corresponds to the amount of CPUs a
614/// computer has, but it may diverge in various cases.
615///
616/// Host environments such as VMs or container orchestrators may want to
617/// restrict the amount of parallelism made available to programs in them. This
618/// is often done to limit the potential impact of (unintentionally)
619/// resource-intensive programs on other programs running on the same machine.
620///
621/// # Limitations
622///
623/// The purpose of this API is to provide an easy and portable way to query
624/// the default amount of parallelism the program should use. Among other things it
625/// does not expose information on NUMA regions, does not account for
626/// differences in (co)processor capabilities or current system load,
627/// and will not modify the program's global state in order to more accurately
628/// query the amount of available parallelism.
629///
630/// Where both fixed steady-state and burst limits are available the steady-state
631/// capacity will be used to ensure more predictable latencies.
632///
633/// Resource limits can be changed during the runtime of a program, therefore the value is
634/// not cached and instead recomputed every time this function is called. It should not be
635/// called from hot code.
636///
637/// The value returned by this function should be considered a simplified
638/// approximation of the actual amount of parallelism available at any given
639/// time. To get a more detailed or precise overview of the amount of
640/// parallelism available to the program, you may wish to use
641/// platform-specific APIs as well. The following platform limitations currently
642/// apply to `available_parallelism`:
643///
644/// On Windows:
645/// - It may undercount the amount of parallelism available on systems with more
646///   than 64 logical CPUs, because it reports only the logical CPUs in one
647///   processor group. Before Windows 11 and Windows Server 2022, a process was by
648///   default confined to a single processor group, so this count reflected the CPUs
649///   it could use without explicitly opting into other groups. Starting with Windows
650///   11 and Windows Server 2022, a process and its threads have affinities that by
651///   default span all processor groups, so on systems with more than 64 logical CPUs
652///   this may report fewer CPUs than are available to the program.
653/// - It may overcount the amount of parallelism available on systems limited by
654///   process-wide affinity masks, or job object limitations.
655///
656/// On Linux:
657/// - It may overcount the amount of parallelism available when limited by a
658///   process-wide affinity mask or cgroup quotas and `sched_getaffinity()` or cgroup fs can't be
659///   queried, e.g. due to sandboxing.
660/// - It may undercount the amount of parallelism if the current thread's affinity mask
661///   does not reflect the process' cpuset, e.g. due to pinned threads.
662/// - If the process is in a cgroup v1 cpu controller, this may need to
663///   scan mountpoints to find the corresponding cgroup v1 controller,
664///   which may take time on systems with large numbers of mountpoints.
665///   (This does not apply to cgroup v2, or to processes not in a
666///   cgroup.)
667/// - It does not attempt to take `ulimit` into account. If there is a limit set on the number of
668///   threads, `available_parallelism` cannot know how much of that limit a Rust program should
669///   take, or know in a reliable and race-free way how much of that limit is already taken.
670///
671/// On all targets:
672/// - It may overcount the amount of parallelism available when running in a VM
673/// with CPU usage limits (e.g. an overcommitted host).
674///
675/// # Errors
676///
677/// This function will, but is not limited to, return errors in the following
678/// cases:
679///
680/// - If the amount of parallelism is not known for the target platform.
681/// - If the program lacks permission to query the amount of parallelism made
682///   available to it.
683///
684/// # Examples
685///
686/// ```
687/// use std::thread;
688///
689/// if let Ok(count) = thread::available_parallelism() {
690///   assert!(count.get() >= 1_usize);
691/// }
692/// ```
693#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable.
694#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`.
695#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality.
696#[stable(feature = "available_parallelism", since = "1.59.0")]
697pub fn available_parallelism() -> io::Result<NonZero<usize>> {
698    imp::available_parallelism()
699}