#![forbid(missing_docs)]
#![feature(thread_spawn_unchecked)]
#![feature(slice_split_at_unchecked)]
#![doc = include_str!("../README.md")]
mod raw;
pub mod iter;
use raw::spawn_threads;
use std::cell::Cell;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::available_parallelism;
pub trait Divvy
where
Self::Output: Iterator<Item = Self::Chunk>,
Self: Sized,
{
type Chunk;
type Output;
fn divvy(self, n: usize) -> Self::Output;
fn divvy_cpus(self) -> Self::Output {
self.divvy(available_parallelism().unwrap().get())
}
}
pub trait IteratorExt<T, C>
where
Self: Iterator<Item = C> + Sized,
C: IntoIterator<Item = T> + Send,
{
fn par_for_each(self, f: impl Fn(T) + Sync) {
let f = &f;
let panicked = &Cell::new(false);
spawn_threads(self, |chunk| chunk.into_iter().for_each(f), drop, panicked)
}
fn find_map_any<F, U>(self, f: F) -> Option<U>
where
F: Fn(T) -> Option<U> + Sync,
U: Send,
{
let f = &f;
let done = &AtomicBool::new(false);
let panicked = &Cell::new(false);
spawn_threads(
self,
|chunk| {
for x in chunk {
if done.load(Ordering::Relaxed) {
return None;
} else {
let ret = f(x);
if ret.is_some() {
done.store(true, Ordering::Relaxed);
return ret;
}
}
}
None
},
|mut x| x.find_map(|x| x),
panicked,
)
}
fn find_map_all<F, U>(self, f: F) -> Vec<U>
where
F: Fn(T) -> Option<U> + Sync,
U: Send,
{
let f = &f;
let panicked = &Cell::new(false);
spawn_threads(
self,
|chunk| chunk.into_iter().filter_map(f).collect::<Vec<_>>(),
|x| x.into_iter().flat_map(|x| x.into_iter()).collect(),
panicked,
)
}
fn find_any<F>(self, f: F) -> Option<T>
where
F: Fn(&T) -> bool + Sync,
T: Send,
{
self.find_map_any(|x| f(&x).then(move || x))
}
fn find_all<F>(self, f: F) -> Vec<T>
where
F: Fn(&T) -> bool + Sync,
T: Send,
{
self.find_map_all(|x| f(&x).then(move || x))
}
fn map_reduce<M, R, S, U>(self, map: M, state: S, reduce: R) -> S
where
M: Fn(C) -> U + Sync,
U: Send,
R: FnMut(S, U) -> S,
{
let panicked = &Cell::new(false);
spawn_threads(self, map, |it| it.fold(state, reduce), panicked)
}
}
impl<T, C, I> IteratorExt<T, C> for I
where
I: Iterator<Item = C> + Sized,
C: IntoIterator<Item = T> + Send,
{
}