use std::sync::OnceLock;
pub mod rayon_impl;
pub use rayon_impl::RayonRailgun;
#[derive(Debug, Clone)]
pub struct ParallelConfig {
pub stack_size: Option<usize>,
pub num_threads: Option<usize>,
}
impl Default for ParallelConfig {
fn default() -> Self {
Self {
stack_size: Some(8 * 1024 * 1024), num_threads: None,
}
}
}
pub trait Railgun: Clone + Send + Sync {
fn par_map<T, U, F>(&self, input: &[T], f: F) -> Vec<U>
where
T: Sync,
U: Send,
F: Fn(&T) -> U + Sync + Send;
fn par_map_indexed<T, U, F>(&self, input: &[T], f: F) -> Vec<U>
where
T: Sync,
U: Send,
F: Fn(usize, &T) -> U + Sync + Send;
fn with_config<F, R>(&self, config: ParallelConfig, f: F) -> R
where
F: Fn() -> R + Send + Sync,
R: Send;
}
static DEFAULT_RAILGUN: OnceLock<RayonRailgun> = OnceLock::new();
pub fn default_railgun() -> &'static RayonRailgun {
DEFAULT_RAILGUN.get_or_init(RayonRailgun::default)
}
pub fn rayon_railgun(config: ParallelConfig) -> RayonRailgun {
RayonRailgun::with_config(config)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_par_map() {
let railgun = default_railgun();
let input = vec![1, 2, 3, 4, 5];
let result = railgun.par_map(&input, |x| x * 2);
assert_eq!(result, vec![2, 4, 6, 8, 10]);
}
#[test]
fn test_par_map_indexed() {
let railgun = default_railgun();
let input = vec![10, 20, 30];
let result = railgun.par_map_indexed(&input, |i, x| i + x);
assert_eq!(result, vec![10, 21, 32]);
}
#[test]
fn test_with_config() {
let railgun = default_railgun();
let config = ParallelConfig {
stack_size: Some(4 * 1024 * 1024),
num_threads: Some(2),
};
let result = railgun.with_config(config, || {
42
});
assert_eq!(result, 42);
}
}