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 {}