jobsteal 0.5.1

A work-stealing fork-join threadpool written in Rust.
Documentation
use super::{Callback, Consumer, Filter, Split, Spliterator};

const FILTER_COST: f32 = 0.05;

pub struct FilterBase<T>(T);

impl<T: IntoIterator> IntoIterator for FilterBase<T> {
    type Item = T::Item;
    type IntoIter = T::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<T: Split> Split for FilterBase<T> {
    fn should_split(&self, mul: f32) -> Option<usize> {
        self.0.should_split(mul + FILTER_COST)
    }

    fn split(self, idx: usize) -> (Self, Self) {
        let (a, b) = self.0.split(idx);

        (FilterBase(a), FilterBase(b))
    }
}

struct FilterCallback<C, F> {
    cb: C,
    pred: F,
}

impl<Item, C: Callback<Item>, F> Callback<Item> for FilterCallback<C, F>
where F: Fn(&Item) -> bool {
    type Out = C::Out;

    fn call<I: Iterator<Item=Item>>(self, iter: I) -> C::Out {
        self.cb.call(iter.filter(self.pred))
    }
}

impl<In: IntoIterator, T: Consumer<In>, F: Sync> Consumer<FilterBase<In>> for Filter<T, F>
where F: Fn(&T::Item) -> bool {
    type Item = T::Item;

    fn consume<C: Callback<Self::Item>>(&self, i: FilterBase<In>, cb: C) -> C::Out {
        let cb = FilterCallback {
            cb: cb,
            pred: &self.pred,
        };

        self.parent.consume(i.0, cb)
    }
}

impl<T: Spliterator, F: Sync> Spliterator for Filter<T, F>
where F: Fn(&T::Item) -> bool{
    type Item = T::Item;
    type Base = FilterBase<T::Base>;
    type Consumer = Filter<T::Consumer, F>;

    fn destructure(self) -> (Self::Base, Self::Consumer) {
        let (b, c) = self.parent.destructure();

        (FilterBase(b), Filter { parent: c, pred: self.pred })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, u) = self.parent.size_hint();

        (0, u)
    }
}

#[cfg(test)]
mod tests {
    use ::{Spliterator, IntoSpliterator, pool_harness};

    #[test]
    fn filter_basics() {
        pool_harness(|pool| {
            let v: Vec<_> = (0..1000).collect();
            v.into_split_iter().filter(|x| *x % 2 == 1).for_each(&pool.spawner(), |x| assert!(x % 2 == 1));
        });
    }
}