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}