cuprate_helper/
thread.rs

1//! System thread related
2//!
3//! Requires `std`.
4
5//---------------------------------------------------------------------------------------------------- Use
6use std::{cmp::max, num::NonZeroUsize};
7
8//---------------------------------------------------------------------------------------------------- Thread Count & Percent
9/// Get the total amount of system threads.
10///
11/// ```rust
12/// # use cuprate_helper::thread::*;
13/// assert!(threads().get() >= 1);
14/// ```
15pub fn threads() -> NonZeroUsize {
16    std::thread::available_parallelism().unwrap_or(NonZeroUsize::MIN)
17}
18
19// Implement a function for the various
20// `x` thread-percent functions below.
21macro_rules! impl_thread_percent {
22    ($(
23    	$(#[$doc:meta])*
24    	$fn_name:ident => // Name of the function
25		$percent:literal  // The target percent of threads
26	),* $(,)?) => {
27		$(
28			$(#[$doc])*
29			pub fn $fn_name() -> NonZeroUsize {
30                // unwrap here is okay because:
31                // - THREADS().get() is always non-zero
32                // - max() guards against 0
33                #[expect(
34                    clippy::cast_possible_truncation,
35                    clippy::cast_sign_loss,
36                    clippy::cast_precision_loss,
37                    reason = "we need to round integers"
38                )]
39		        NonZeroUsize::new(max(1, (threads().get() as f64 * $percent).ceil() as usize)).unwrap()
40		    }
41		)*
42    }
43}
44impl_thread_percent! {
45    /// Get 90% (rounded up) of available amount of system threads.
46    threads_90 => 0.90,
47    /// Get 75% (rounded up) of available amount of system threads.
48    threads_75 => 0.75,
49    /// Get 50% (rounded up) of available amount of system threads.
50    threads_50 => 0.50,
51    /// Get 25% (rounded up) of available amount of system threads.
52    threads_25 => 0.25,
53    /// Get 10% (rounded up) of available amount of system threads.
54    threads_10 => 0.10,
55}
56
57//---------------------------------------------------------------------------------------------------- Thread Priority
58/// Low Priority Thread
59///
60/// Sets the calling thread’s priority to the lowest platform-specific value possible.
61///
62/// Originally from <https://docs.rs/lpt>.
63///
64/// # Windows
65/// Uses `SetThreadPriority()` with `THREAD_PRIORITY_IDLE` (-15).
66///
67/// # Unix
68/// Uses `libc::nice()` with the max nice level.
69///
70/// On macOS and *BSD: +20
71/// On Linux: +19
72pub fn low_priority_thread() {
73    #[cfg(target_os = "windows")]
74    {
75        use target_os_lib as windows;
76        use windows::Win32::System::Threading::*;
77
78        // SAFETY: calling C.
79        // We are _lowering_ our priority, not increasing, so this function should never fail.
80        unsafe {
81            drop(SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE));
82        }
83    }
84
85    #[cfg(target_family = "unix")]
86    {
87        use target_os_lib as libc;
88
89        const NICE_MAX: libc::c_int = if cfg!(target_os = "linux") { 19 } else { 20 };
90
91        // SAFETY: calling C.
92        // We are _lowering_ our priority, not increasing, so this function should never fail.
93        unsafe {
94            libc::nice(NICE_MAX);
95        }
96    }
97}
98
99//---------------------------------------------------------------------------------------------------- TESTS
100#[cfg(test)]
101mod tests {}