1 //! Rayon extensions for `HashSet`.
3 use crate::hash_set
::HashSet
;
4 use core
::hash
::{BuildHasher, Hash}
;
5 use rayon
::iter
::plumbing
::UnindexedConsumer
;
6 use rayon
::iter
::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}
;
8 /// Parallel iterator over elements of a consumed set.
10 /// This iterator is created by the [`into_par_iter`] method on [`HashSet`]
11 /// (provided by the [`IntoParallelIterator`] trait).
12 /// See its documentation for more.
14 /// [`into_par_iter`]: /hashbrown/struct.HashSet.html#method.into_par_iter
15 /// [`HashSet`]: /hashbrown/struct.HashSet.html
16 /// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
17 pub struct IntoParIter
<T
, S
> {
21 impl<T
: Send
, S
: Send
> ParallelIterator
for IntoParIter
<T
, S
> {
24 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
26 C
: UnindexedConsumer
<Self::Item
>,
32 .drive_unindexed(consumer
)
36 /// Parallel draining iterator over entries of a set.
38 /// This iterator is created by the [`par_drain`] method on [`HashSet`].
39 /// See its documentation for more.
41 /// [`par_drain`]: /hashbrown/struct.HashSet.html#method.par_drain
42 /// [`HashSet`]: /hashbrown/struct.HashSet.html
43 pub struct ParDrain
<'a
, T
, S
> {
44 set
: &'a
mut HashSet
<T
, S
>,
47 impl<T
: Send
, S
: Send
> ParallelIterator
for ParDrain
<'_
, T
, S
> {
50 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
52 C
: UnindexedConsumer
<Self::Item
>,
58 .drive_unindexed(consumer
)
62 /// Parallel iterator over shared references to elements in a set.
64 /// This iterator is created by the [`par_iter`] method on [`HashSet`]
65 /// (provided by the [`IntoParallelRefIterator`] trait).
66 /// See its documentation for more.
68 /// [`par_iter`]: /hashbrown/struct.HashSet.html#method.par_iter
69 /// [`HashSet`]: /hashbrown/struct.HashSet.html
70 /// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
71 pub struct ParIter
<'a
, T
, S
> {
72 set
: &'a HashSet
<T
, S
>,
75 impl<'a
, T
: Sync
, S
: Sync
> ParallelIterator
for ParIter
<'a
, T
, S
> {
78 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
80 C
: UnindexedConsumer
<Self::Item
>,
82 self.set
.map
.par_keys().drive_unindexed(consumer
)
86 /// Parallel iterator over shared references to elements in the difference of
89 /// This iterator is created by the [`par_difference`] method on [`HashSet`].
90 /// See its documentation for more.
92 /// [`par_difference`]: /hashbrown/struct.HashSet.html#method.par_difference
93 /// [`HashSet`]: /hashbrown/struct.HashSet.html
94 pub struct ParDifference
<'a
, T
, S
> {
99 impl<'a
, T
, S
> ParallelIterator
for ParDifference
<'a
, T
, S
>
102 S
: BuildHasher
+ Sync
,
106 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
108 C
: UnindexedConsumer
<Self::Item
>,
112 .filter(|&x
| !self.b
.contains(x
))
113 .drive_unindexed(consumer
)
117 /// Parallel iterator over shared references to elements in the symmetric
118 /// difference of sets.
120 /// This iterator is created by the [`par_symmetric_difference`] method on
122 /// See its documentation for more.
124 /// [`par_symmetric_difference`]: /hashbrown/struct.HashSet.html#method.par_symmetric_difference
125 /// [`HashSet`]: /hashbrown/struct.HashSet.html
126 pub struct ParSymmetricDifference
<'a
, T
, S
> {
127 a
: &'a HashSet
<T
, S
>,
128 b
: &'a HashSet
<T
, S
>,
131 impl<'a
, T
, S
> ParallelIterator
for ParSymmetricDifference
<'a
, T
, S
>
134 S
: BuildHasher
+ Sync
,
138 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
140 C
: UnindexedConsumer
<Self::Item
>,
143 .par_difference(self.b
)
144 .chain(self.b
.par_difference(self.a
))
145 .drive_unindexed(consumer
)
149 /// Parallel iterator over shared references to elements in the intersection of
152 /// This iterator is created by the [`par_intersection`] method on [`HashSet`].
153 /// See its documentation for more.
155 /// [`par_intersection`]: /hashbrown/struct.HashSet.html#method.par_intersection
156 /// [`HashSet`]: /hashbrown/struct.HashSet.html
157 pub struct ParIntersection
<'a
, T
, S
> {
158 a
: &'a HashSet
<T
, S
>,
159 b
: &'a HashSet
<T
, S
>,
162 impl<'a
, T
, S
> ParallelIterator
for ParIntersection
<'a
, T
, S
>
165 S
: BuildHasher
+ Sync
,
169 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
171 C
: UnindexedConsumer
<Self::Item
>,
175 .filter(|&x
| self.b
.contains(x
))
176 .drive_unindexed(consumer
)
180 /// Parallel iterator over shared references to elements in the union of sets.
182 /// This iterator is created by the [`par_union`] method on [`HashSet`].
183 /// See its documentation for more.
185 /// [`par_union`]: /hashbrown/struct.HashSet.html#method.par_union
186 /// [`HashSet`]: /hashbrown/struct.HashSet.html
187 pub struct ParUnion
<'a
, T
, S
> {
188 a
: &'a HashSet
<T
, S
>,
189 b
: &'a HashSet
<T
, S
>,
192 impl<'a
, T
, S
> ParallelIterator
for ParUnion
<'a
, T
, S
>
195 S
: BuildHasher
+ Sync
,
199 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
201 C
: UnindexedConsumer
<Self::Item
>,
205 .chain(self.b
.par_difference(self.a
))
206 .drive_unindexed(consumer
)
210 impl<T
, S
> HashSet
<T
, S
>
213 S
: BuildHasher
+ Sync
,
215 /// Visits (potentially in parallel) the values representing the difference,
216 /// i.e. the values that are in `self` but not in `other`.
217 #[cfg_attr(feature = "inline-more", inline)]
218 pub fn par_difference
<'a
>(&'a
self, other
: &'a
Self) -> ParDifference
<'a
, T
, S
> {
219 ParDifference { a: self, b: other }
222 /// Visits (potentially in parallel) the values representing the symmetric
223 /// difference, i.e. the values that are in `self` or in `other` but not in both.
224 #[cfg_attr(feature = "inline-more", inline)]
225 pub fn par_symmetric_difference
<'a
>(
228 ) -> ParSymmetricDifference
<'a
, T
, S
> {
229 ParSymmetricDifference { a: self, b: other }
232 /// Visits (potentially in parallel) the values representing the
233 /// intersection, i.e. the values that are both in `self` and `other`.
234 #[cfg_attr(feature = "inline-more", inline)]
235 pub fn par_intersection
<'a
>(&'a
self, other
: &'a
Self) -> ParIntersection
<'a
, T
, S
> {
236 ParIntersection { a: self, b: other }
239 /// Visits (potentially in parallel) the values representing the union,
240 /// i.e. all the values in `self` or `other`, without duplicates.
241 #[cfg_attr(feature = "inline-more", inline)]
242 pub fn par_union
<'a
>(&'a
self, other
: &'a
Self) -> ParUnion
<'a
, T
, S
> {
243 ParUnion { a: self, b: other }
246 /// Returns `true` if `self` has no elements in common with `other`.
247 /// This is equivalent to checking for an empty intersection.
249 /// This method runs in a potentially parallel fashion.
250 pub fn par_is_disjoint(&self, other
: &Self) -> bool
{
251 self.into_par_iter().all(|x
| !other
.contains(x
))
254 /// Returns `true` if the set is a subset of another,
255 /// i.e. `other` contains at least all the values in `self`.
257 /// This method runs in a potentially parallel fashion.
258 pub fn par_is_subset(&self, other
: &Self) -> bool
{
259 if self.len() <= other
.len() {
260 self.into_par_iter().all(|x
| other
.contains(x
))
266 /// Returns `true` if the set is a superset of another,
267 /// i.e. `self` contains at least all the values in `other`.
269 /// This method runs in a potentially parallel fashion.
270 pub fn par_is_superset(&self, other
: &Self) -> bool
{
271 other
.par_is_subset(self)
274 /// Returns `true` if the set is equal to another,
275 /// i.e. both sets contain the same values.
277 /// This method runs in a potentially parallel fashion.
278 pub fn par_eq(&self, other
: &Self) -> bool
{
279 self.len() == other
.len() && self.par_is_subset(other
)
283 impl<T
, S
> HashSet
<T
, S
>
286 S
: BuildHasher
+ Send
,
288 /// Consumes (potentially in parallel) all values in an arbitrary order,
289 /// while preserving the set's allocated memory for reuse.
290 #[cfg_attr(feature = "inline-more", inline)]
291 pub fn par_drain(&mut self) -> ParDrain
<'_
, T
, S
> {
292 ParDrain { set: self }
296 impl<T
: Send
, S
: Send
> IntoParallelIterator
for HashSet
<T
, S
> {
298 type Iter
= IntoParIter
<T
, S
>;
300 #[cfg_attr(feature = "inline-more", inline)]
301 fn into_par_iter(self) -> Self::Iter
{
302 IntoParIter { set: self }
306 impl<'a
, T
: Sync
, S
: Sync
> IntoParallelIterator
for &'a HashSet
<T
, S
> {
308 type Iter
= ParIter
<'a
, T
, S
>;
310 #[cfg_attr(feature = "inline-more", inline)]
311 fn into_par_iter(self) -> Self::Iter
{
312 ParIter { set: self }
316 /// Collect values from a parallel iterator into a hashset.
317 impl<T
, S
> FromParallelIterator
<T
> for HashSet
<T
, S
>
320 S
: BuildHasher
+ Default
,
322 fn from_par_iter
<P
>(par_iter
: P
) -> Self
324 P
: IntoParallelIterator
<Item
= T
>,
326 let mut set
= HashSet
::default();
327 set
.par_extend(par_iter
);
332 /// Extend a hash set with items from a parallel iterator.
333 impl<T
, S
> ParallelExtend
<T
> for HashSet
<T
, S
>
338 fn par_extend
<I
>(&mut self, par_iter
: I
)
340 I
: IntoParallelIterator
<Item
= T
>,
342 extend(self, par_iter
);
346 /// Extend a hash set with copied items from a parallel iterator.
347 impl<'a
, T
, S
> ParallelExtend
<&'a T
> for HashSet
<T
, S
>
349 T
: 'a
+ Copy
+ Eq
+ Hash
+ Sync
,
352 fn par_extend
<I
>(&mut self, par_iter
: I
)
354 I
: IntoParallelIterator
<Item
= &'a T
>,
356 extend(self, par_iter
);
360 // This is equal to the normal `HashSet` -- no custom advantage.
361 fn extend
<T
, S
, I
>(set
: &mut HashSet
<T
, S
>, par_iter
: I
)
365 I
: IntoParallelIterator
,
366 HashSet
<T
, S
>: Extend
<I
::Item
>,
368 let (list
, len
) = super::helpers
::collect(par_iter
);
370 // Values may be already present or show multiple times in the iterator.
371 // Reserve the entire length if the set is empty.
372 // Otherwise reserve half the length (rounded up), so the set
373 // will only resize twice in the worst case.
374 let reserve
= if set
.is_empty() { len }
else { (len + 1) / 2 }
;
375 set
.reserve(reserve
);
384 use core
::sync
::atomic
::{AtomicUsize, Ordering}
;
386 use rayon
::prelude
::*;
388 use crate::hash_set
::HashSet
;
392 let mut xs
= HashSet
::new();
393 let mut ys
= HashSet
::new();
394 assert
!(xs
.par_is_disjoint(&ys
));
395 assert
!(ys
.par_is_disjoint(&xs
));
396 assert
!(xs
.insert(5));
397 assert
!(ys
.insert(11));
398 assert
!(xs
.par_is_disjoint(&ys
));
399 assert
!(ys
.par_is_disjoint(&xs
));
400 assert
!(xs
.insert(7));
401 assert
!(xs
.insert(19));
402 assert
!(xs
.insert(4));
403 assert
!(ys
.insert(2));
404 assert
!(ys
.insert(-11));
405 assert
!(xs
.par_is_disjoint(&ys
));
406 assert
!(ys
.par_is_disjoint(&xs
));
407 assert
!(ys
.insert(7));
408 assert
!(!xs
.par_is_disjoint(&ys
));
409 assert
!(!ys
.par_is_disjoint(&xs
));
413 fn test_subset_and_superset() {
414 let mut a
= HashSet
::new();
415 assert
!(a
.insert(0));
416 assert
!(a
.insert(5));
417 assert
!(a
.insert(11));
418 assert
!(a
.insert(7));
420 let mut b
= HashSet
::new();
421 assert
!(b
.insert(0));
422 assert
!(b
.insert(7));
423 assert
!(b
.insert(19));
424 assert
!(b
.insert(250));
425 assert
!(b
.insert(11));
426 assert
!(b
.insert(200));
428 assert
!(!a
.par_is_subset(&b
));
429 assert
!(!a
.par_is_superset(&b
));
430 assert
!(!b
.par_is_subset(&a
));
431 assert
!(!b
.par_is_superset(&a
));
433 assert
!(b
.insert(5));
435 assert
!(a
.par_is_subset(&b
));
436 assert
!(!a
.par_is_superset(&b
));
437 assert
!(!b
.par_is_subset(&a
));
438 assert
!(b
.par_is_superset(&a
));
443 let mut a
= HashSet
::new();
445 assert
!(a
.insert(i
));
447 let observed
= AtomicUsize
::new(0);
448 a
.par_iter().for_each(|k
| {
449 observed
.fetch_or(1 << *k
, Ordering
::Relaxed
);
451 assert_eq
!(observed
.into_inner(), 0xFFFF_FFFF);
455 fn test_intersection() {
456 let mut a
= HashSet
::new();
457 let mut b
= HashSet
::new();
459 assert
!(a
.insert(11));
460 assert
!(a
.insert(1));
461 assert
!(a
.insert(3));
462 assert
!(a
.insert(77));
463 assert
!(a
.insert(103));
464 assert
!(a
.insert(5));
465 assert
!(a
.insert(-5));
467 assert
!(b
.insert(2));
468 assert
!(b
.insert(11));
469 assert
!(b
.insert(77));
470 assert
!(b
.insert(-9));
471 assert
!(b
.insert(-42));
472 assert
!(b
.insert(5));
473 assert
!(b
.insert(3));
475 let expected
= [3, 5, 11, 77];
477 .par_intersection(&b
)
479 assert
!(expected
.contains(x
));
483 assert_eq
!(i
, expected
.len());
487 fn test_difference() {
488 let mut a
= HashSet
::new();
489 let mut b
= HashSet
::new();
491 assert
!(a
.insert(1));
492 assert
!(a
.insert(3));
493 assert
!(a
.insert(5));
494 assert
!(a
.insert(9));
495 assert
!(a
.insert(11));
497 assert
!(b
.insert(3));
498 assert
!(b
.insert(9));
500 let expected
= [1, 5, 11];
504 assert
!(expected
.contains(x
));
508 assert_eq
!(i
, expected
.len());
512 fn test_symmetric_difference() {
513 let mut a
= HashSet
::new();
514 let mut b
= HashSet
::new();
516 assert
!(a
.insert(1));
517 assert
!(a
.insert(3));
518 assert
!(a
.insert(5));
519 assert
!(a
.insert(9));
520 assert
!(a
.insert(11));
522 assert
!(b
.insert(-2));
523 assert
!(b
.insert(3));
524 assert
!(b
.insert(9));
525 assert
!(b
.insert(14));
526 assert
!(b
.insert(22));
528 let expected
= [-2, 1, 5, 11, 14, 22];
530 .par_symmetric_difference(&b
)
532 assert
!(expected
.contains(x
));
536 assert_eq
!(i
, expected
.len());
541 let mut a
= HashSet
::new();
542 let mut b
= HashSet
::new();
544 assert
!(a
.insert(1));
545 assert
!(a
.insert(3));
546 assert
!(a
.insert(5));
547 assert
!(a
.insert(9));
548 assert
!(a
.insert(11));
549 assert
!(a
.insert(16));
550 assert
!(a
.insert(19));
551 assert
!(a
.insert(24));
553 assert
!(b
.insert(-2));
554 assert
!(b
.insert(1));
555 assert
!(b
.insert(5));
556 assert
!(b
.insert(9));
557 assert
!(b
.insert(13));
558 assert
!(b
.insert(19));
560 let expected
= [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
564 assert
!(expected
.contains(x
));
568 assert_eq
!(i
, expected
.len());
572 fn test_from_iter() {
573 let xs
= [1, 2, 3, 4, 5, 6, 7, 8, 9];
575 let set
: HashSet
<_
> = xs
.par_iter().cloned().collect();
578 assert
!(set
.contains(x
));
583 fn test_move_iter() {
585 let mut hs
= HashSet
::new();
593 let v
= hs
.into_par_iter().collect
::<Vec
<char>>();
594 assert
!(v
== ['a'
, 'b'
] || v
== ['b'
, 'a'
]);
599 // These constants once happened to expose a bug in insert().
600 // I'm keeping them around to prevent a regression.
601 let mut s1
= HashSet
::new();
607 let mut s2
= HashSet
::new();
612 assert
!(!s1
.par_eq(&s2
));
616 assert
!(s1
.par_eq(&s2
));
620 fn test_extend_ref() {
621 let mut a
= HashSet
::new();
624 a
.par_extend(&[2, 3, 4][..]);
626 assert_eq
!(a
.len(), 4);
627 assert
!(a
.contains(&1));
628 assert
!(a
.contains(&2));
629 assert
!(a
.contains(&3));
630 assert
!(a
.contains(&4));
632 let mut b
= HashSet
::new();
638 assert_eq
!(a
.len(), 6);
639 assert
!(a
.contains(&1));
640 assert
!(a
.contains(&2));
641 assert
!(a
.contains(&3));
642 assert
!(a
.contains(&4));
643 assert
!(a
.contains(&5));
644 assert
!(a
.contains(&6));