use rayon::prelude::*;
use std::thread;
pub fn parallel<T, R, F>(items: Vec<T>, f: F) -> Vec<R>
where
T: Send + Sync,
R: Send,
F: Fn(T) -> R + Send + Sync,
{
items.into_par_iter().map(f).collect()
}
pub fn background<T, F>(f: F) -> BackgroundTask<T>
where
T: Send + 'static,
F: FnOnce() -> T + Send + 'static,
{
let handle = thread::spawn(f);
BackgroundTask {
handle: Some(handle),
}
}
pub fn num_workers() -> usize {
rayon::current_num_threads()
}
pub fn join<A, B, FA, FB>(a: FA, b: FB) -> (A, B)
where
A: Send,
B: Send,
FA: FnOnce() -> A + Send,
FB: FnOnce() -> B + Send,
{
rayon::join(a, b)
}
pub fn map_reduce<T, R, M, Red>(items: Vec<T>, map_fn: M, reduce_fn: Red, initial: R) -> R
where
T: Send + Sync,
R: Send + Sync + Clone,
M: Fn(T) -> R + Send + Sync,
Red: Fn(R, R) -> R + Send + Sync,
{
items
.into_par_iter()
.map(map_fn)
.reduce(|| initial.clone(), reduce_fn)
}
pub struct BackgroundTask<T> {
handle: Option<thread::JoinHandle<T>>,
}
impl<T> BackgroundTask<T> {
pub fn await_result(mut self) -> T {
self.handle
.take()
.expect("BackgroundTask already consumed")
.join()
.expect("Background task panicked")
}
pub fn is_ready(&self) -> bool {
self.handle
.as_ref()
.map(|h| h.is_finished())
.unwrap_or(true)
}
}