use std::sync::LazyLock;
#[derive(Copy, Debug, Clone)]
pub enum ThreadPriority {
Low = 0,
Normal = 1,
High = 2,
}
static THREAD_POOLS_BY_PRIORITY: LazyLock<[rayon::ThreadPool; 3]> = LazyLock::new(|| {
use thread_priority::{ThreadPriority, ThreadPriorityValue};
rayon::ThreadPoolBuilder::new()
.thread_name(move |j| format!("Global thread {}.", j))
.start_handler(move |_| {
thread_priority::set_current_thread_priority(ThreadPriority::Crossplatform(
ThreadPriorityValue::MIN,
))
.expect("Could not set thread priority");
})
.build_global()
.expect("Could not initialize global thread pool");
array_init::array_init(|i| {
let tp = match i {
0 => (Some(ThreadPriority::Min), "Minimal priority thread "),
1 => (None, "Normal priority thread "),
2 => (
Some(ThreadPriority::Crossplatform(
ThreadPriorityValue::try_from(48).unwrap(),
)),
"High priority thread ",
),
_ => panic!("Only three levels of thread priorities provided."),
};
rayon::ThreadPoolBuilder::new()
.thread_name(move |j| format!("{} {}.", tp.1, j))
.start_handler(move |_| {
if let Some(tp) = tp.0 {
thread_priority::set_current_thread_priority(tp)
.expect("Could not set thread priority");
}
})
.build()
.expect("Failed to create thread pool")
})
});
pub fn create_thread_pool_if_not_created() {
let _ = *THREAD_POOLS_BY_PRIORITY;
}
#[derive(Debug)]
pub struct JoinHandle<T>
where
T: Send + Sync + 'static,
{
rx: oneshot::Receiver<T>,
}
impl<T> JoinHandle<T>
where
T: Send + Sync + 'static,
{
pub fn join(self) -> T {
self.rx.recv().expect("Failed to receive result")
}
}
pub fn spawn<T, F>(function: F, prio: ThreadPriority) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + Sync + 'static,
{
let (tx, rx) = oneshot::channel();
let tp = &THREAD_POOLS_BY_PRIORITY[prio as usize];
tp.spawn(move || {
let res = function();
let _ = tx.send(res);
});
JoinHandle { rx }
}