1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use crate::raw::Bucket;
use crate::raw::RawTable;
use rayon_::iter::{
    plumbing::{Reducer, UnindexedConsumer},
    ParallelIterator,
};

/// Parallel iterator which returns a raw pointer to every full bucket in the table.
pub struct RawParIter<T> {
    iter: hashbrown::raw::rayon::RawParIter<T>,
    leftovers: Option<hashbrown::raw::rayon::RawParIter<T>>,
}

impl<T> ParallelIterator for RawParIter<T> {
    type Item = Bucket<T>;

    #[cfg_attr(feature = "inline-more", inline)]
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
    where
        C: UnindexedConsumer<Self::Item>,
    {
        if let Some(lo) = self.leftovers {
            let left = consumer.split_off_left();
            let reducer = consumer.to_reducer();
            let left_half = self
                .iter
                .map(|bucket| Bucket {
                    bucket,
                    in_main: true,
                })
                .drive_unindexed(left);
            let right_half = lo
                .map(|bucket| Bucket {
                    bucket,
                    in_main: false,
                })
                .drive_unindexed(consumer);
            reducer.reduce(left_half, right_half)
        } else {
            self.iter
                .map(|bucket| Bucket {
                    bucket,
                    in_main: true,
                })
                .drive_unindexed(consumer)
        }
    }
}

impl<T> RawTable<T> {
    /// Returns a parallel iterator over the elements in a `RawTable`.
    #[cfg_attr(feature = "inline-more", inline)]
    pub unsafe fn par_iter(&self) -> RawParIter<T> {
        RawParIter {
            iter: self.main().par_iter(),
            leftovers: self.leftovers().map(|t| t.par_iter()),
        }
    }
}