1 use crate::setref::multiple::RefMulti; 2 use crate::DashSet; 3 use core::hash::{BuildHasher, Hash}; 4 use rayon::iter::plumbing::UnindexedConsumer; 5 use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; 6 use std::collections::hash_map::RandomState; 7 8 impl<K, S> ParallelExtend<K> for DashSet<K, S> 9 where 10 K: Send + Sync + Eq + Hash, 11 S: Send + Sync + Clone + BuildHasher, 12 { par_extend<I>(&mut self, par_iter: I) where I: IntoParallelIterator<Item = K>,13 fn par_extend<I>(&mut self, par_iter: I) 14 where 15 I: IntoParallelIterator<Item = K>, 16 { 17 (&*self).par_extend(par_iter); 18 } 19 } 20 21 // Since we don't actually need mutability, we can implement this on a 22 // reference, similar to `io::Write for &File`. 23 impl<K, S> ParallelExtend<K> for &'_ DashSet<K, S> 24 where 25 K: Send + Sync + Eq + Hash, 26 S: Send + Sync + Clone + BuildHasher, 27 { par_extend<I>(&mut self, par_iter: I) where I: IntoParallelIterator<Item = K>,28 fn par_extend<I>(&mut self, par_iter: I) 29 where 30 I: IntoParallelIterator<Item = K>, 31 { 32 let &mut set = self; 33 par_iter.into_par_iter().for_each(move |key| { 34 set.insert(key); 35 }); 36 } 37 } 38 39 impl<K, S> FromParallelIterator<K> for DashSet<K, S> 40 where 41 K: Send + Sync + Eq + Hash, 42 S: Send + Sync + Clone + Default + BuildHasher, 43 { from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = K>,44 fn from_par_iter<I>(par_iter: I) -> Self 45 where 46 I: IntoParallelIterator<Item = K>, 47 { 48 let set = Self::default(); 49 (&set).par_extend(par_iter); 50 set 51 } 52 } 53 54 impl<K, S> IntoParallelIterator for DashSet<K, S> 55 where 56 K: Send + Eq + Hash, 57 S: Send + Clone + BuildHasher, 58 { 59 type Iter = OwningIter<K, S>; 60 type Item = K; 61 into_par_iter(self) -> Self::Iter62 fn into_par_iter(self) -> Self::Iter { 63 OwningIter { 64 inner: self.inner.into_par_iter(), 65 } 66 } 67 } 68 69 pub struct OwningIter<K, S = RandomState> { 70 inner: super::map::OwningIter<K, (), S>, 71 } 72 73 impl<K, S> ParallelIterator for OwningIter<K, S> 74 where 75 K: Send + Eq + Hash, 76 S: Send + Clone + BuildHasher, 77 { 78 type Item = K; 79 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,80 fn drive_unindexed<C>(self, consumer: C) -> C::Result 81 where 82 C: UnindexedConsumer<Self::Item>, 83 { 84 self.inner.map(|(k, _)| k).drive_unindexed(consumer) 85 } 86 } 87 88 // This impl also enables `IntoParallelRefIterator::par_iter` 89 impl<'a, K, S> IntoParallelIterator for &'a DashSet<K, S> 90 where 91 K: Send + Sync + Eq + Hash, 92 S: Send + Sync + Clone + BuildHasher, 93 { 94 type Iter = Iter<'a, K, S>; 95 type Item = RefMulti<'a, K, S>; 96 into_par_iter(self) -> Self::Iter97 fn into_par_iter(self) -> Self::Iter { 98 Iter { 99 inner: (&self.inner).into_par_iter(), 100 } 101 } 102 } 103 104 pub struct Iter<'a, K, S = RandomState> { 105 inner: super::map::Iter<'a, K, (), S>, 106 } 107 108 impl<'a, K, S> ParallelIterator for Iter<'a, K, S> 109 where 110 K: Send + Sync + Eq + Hash, 111 S: Send + Sync + Clone + BuildHasher, 112 { 113 type Item = RefMulti<'a, K, S>; 114 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,115 fn drive_unindexed<C>(self, consumer: C) -> C::Result 116 where 117 C: UnindexedConsumer<Self::Item>, 118 { 119 self.inner.map(RefMulti::new).drive_unindexed(consumer) 120 } 121 } 122