1 //! Rayon extensions for `HashMap`.
3 use crate::hash_map
::HashMap
;
5 use core
::hash
::{BuildHasher, Hash}
;
6 use rayon
::iter
::plumbing
::UnindexedConsumer
;
7 use rayon
::iter
::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}
;
9 /// Parallel iterator over shared references to entries in a map.
11 /// This iterator is created by the [`par_iter`] method on [`HashMap`]
12 /// (provided by the [`IntoParallelRefIterator`] trait).
13 /// See its documentation for more.
15 /// [`par_iter`]: /hashbrown/struct.HashMap.html#method.par_iter
16 /// [`HashMap`]: /hashbrown/struct.HashMap.html
17 /// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
18 pub struct ParIter
<'a
, K
, V
, S
> {
19 map
: &'a HashMap
<K
, V
, S
>,
22 impl<'a
, K
: Sync
, V
: Sync
, S
: Sync
> ParallelIterator
for ParIter
<'a
, K
, V
, S
> {
23 type Item
= (&'a K
, &'a V
);
25 #[cfg_attr(feature = "inline-more", inline)]
26 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
28 C
: UnindexedConsumer
<Self::Item
>,
30 unsafe { self.map.table.par_iter() }
35 .drive_unindexed(consumer
)
39 impl<K
, V
, S
> Clone
for ParIter
<'_
, K
, V
, S
> {
40 #[cfg_attr(feature = "inline-more", inline)]
41 fn clone(&self) -> Self {
42 ParIter { map: self.map }
46 impl<K
: fmt
::Debug
+ Eq
+ Hash
, V
: fmt
::Debug
, S
: BuildHasher
> fmt
::Debug
for ParIter
<'_
, K
, V
, S
> {
47 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
48 self.map
.iter().fmt(f
)
52 /// Parallel iterator over shared references to keys in a map.
54 /// This iterator is created by the [`par_keys`] method on [`HashMap`].
55 /// See its documentation for more.
57 /// [`par_keys`]: /hashbrown/struct.HashMap.html#method.par_keys
58 /// [`HashMap`]: /hashbrown/struct.HashMap.html
59 pub struct ParKeys
<'a
, K
, V
, S
> {
60 map
: &'a HashMap
<K
, V
, S
>,
63 impl<'a
, K
: Sync
, V
: Sync
, S
: Sync
> ParallelIterator
for ParKeys
<'a
, K
, V
, S
> {
66 #[cfg_attr(feature = "inline-more", inline)]
67 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
69 C
: UnindexedConsumer
<Self::Item
>,
71 unsafe { self.map.table.par_iter() }
72 .map(|x
| unsafe { &x.as_ref().0 }
)
73 .drive_unindexed(consumer
)
77 impl<K
, V
, S
> Clone
for ParKeys
<'_
, K
, V
, S
> {
78 #[cfg_attr(feature = "inline-more", inline)]
79 fn clone(&self) -> Self {
80 ParKeys { map: self.map }
84 impl<K
: fmt
::Debug
+ Eq
+ Hash
, V
, S
: BuildHasher
> fmt
::Debug
for ParKeys
<'_
, K
, V
, S
> {
85 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
86 self.map
.keys().fmt(f
)
90 /// Parallel iterator over shared references to values in a map.
92 /// This iterator is created by the [`par_values`] method on [`HashMap`].
93 /// See its documentation for more.
95 /// [`par_values`]: /hashbrown/struct.HashMap.html#method.par_values
96 /// [`HashMap`]: /hashbrown/struct.HashMap.html
97 pub struct ParValues
<'a
, K
, V
, S
> {
98 map
: &'a HashMap
<K
, V
, S
>,
101 impl<'a
, K
: Sync
, V
: Sync
, S
: Sync
> ParallelIterator
for ParValues
<'a
, K
, V
, S
> {
104 #[cfg_attr(feature = "inline-more", inline)]
105 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
107 C
: UnindexedConsumer
<Self::Item
>,
109 unsafe { self.map.table.par_iter() }
110 .map(|x
| unsafe { &x.as_ref().1 }
)
111 .drive_unindexed(consumer
)
115 impl<K
, V
, S
> Clone
for ParValues
<'_
, K
, V
, S
> {
116 #[cfg_attr(feature = "inline-more", inline)]
117 fn clone(&self) -> Self {
118 ParValues { map: self.map }
122 impl<K
: Eq
+ Hash
, V
: fmt
::Debug
, S
: BuildHasher
> fmt
::Debug
for ParValues
<'_
, K
, V
, S
> {
123 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
124 self.map
.values().fmt(f
)
128 /// Parallel iterator over mutable references to entries in a map.
130 /// This iterator is created by the [`par_iter_mut`] method on [`HashMap`]
131 /// (provided by the [`IntoParallelRefMutIterator`] trait).
132 /// See its documentation for more.
134 /// [`par_iter_mut`]: /hashbrown/struct.HashMap.html#method.par_iter_mut
135 /// [`HashMap`]: /hashbrown/struct.HashMap.html
136 /// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html
137 pub struct ParIterMut
<'a
, K
, V
, S
> {
138 map
: &'a
mut HashMap
<K
, V
, S
>,
141 impl<'a
, K
: Send
+ Sync
, V
: Send
, S
: Send
> ParallelIterator
for ParIterMut
<'a
, K
, V
, S
> {
142 type Item
= (&'a K
, &'a
mut V
);
144 #[cfg_attr(feature = "inline-more", inline)]
145 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
147 C
: UnindexedConsumer
<Self::Item
>,
149 unsafe { self.map.table.par_iter() }
154 .drive_unindexed(consumer
)
158 impl<K
: fmt
::Debug
+ Eq
+ Hash
, V
: fmt
::Debug
, S
: BuildHasher
> fmt
::Debug
159 for ParIterMut
<'_
, K
, V
, S
>
161 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
162 self.map
.iter().fmt(f
)
166 /// Parallel iterator over mutable references to values in a map.
168 /// This iterator is created by the [`par_values_mut`] method on [`HashMap`].
169 /// See its documentation for more.
171 /// [`par_values_mut`]: /hashbrown/struct.HashMap.html#method.par_values_mut
172 /// [`HashMap`]: /hashbrown/struct.HashMap.html
173 pub struct ParValuesMut
<'a
, K
, V
, S
> {
174 map
: &'a
mut HashMap
<K
, V
, S
>,
177 impl<'a
, K
: Send
, V
: Send
, S
: Send
> ParallelIterator
for ParValuesMut
<'a
, K
, V
, S
> {
178 type Item
= &'a
mut V
;
180 #[cfg_attr(feature = "inline-more", inline)]
181 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
183 C
: UnindexedConsumer
<Self::Item
>,
185 unsafe { self.map.table.par_iter() }
186 .map(|x
| unsafe { &mut x.as_mut().1 }
)
187 .drive_unindexed(consumer
)
191 impl<K
: Eq
+ Hash
, V
: fmt
::Debug
, S
: BuildHasher
> fmt
::Debug
for ParValuesMut
<'_
, K
, V
, S
> {
192 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
193 self.map
.values().fmt(f
)
197 /// Parallel iterator over entries of a consumed map.
199 /// This iterator is created by the [`into_par_iter`] method on [`HashMap`]
200 /// (provided by the [`IntoParallelIterator`] trait).
201 /// See its documentation for more.
203 /// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter
204 /// [`HashMap`]: /hashbrown/struct.HashMap.html
205 /// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
206 pub struct IntoParIter
<K
, V
, S
> {
207 map
: HashMap
<K
, V
, S
>,
210 impl<K
: Send
, V
: Send
, S
: Send
> ParallelIterator
for IntoParIter
<K
, V
, S
> {
213 #[cfg_attr(feature = "inline-more", inline)]
214 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
216 C
: UnindexedConsumer
<Self::Item
>,
218 self.map
.table
.into_par_iter().drive_unindexed(consumer
)
222 impl<K
: fmt
::Debug
+ Eq
+ Hash
, V
: fmt
::Debug
, S
: BuildHasher
> fmt
::Debug
for IntoParIter
<K
, V
, S
> {
223 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
224 self.map
.iter().fmt(f
)
228 /// Parallel draining iterator over entries of a map.
230 /// This iterator is created by the [`par_drain`] method on [`HashMap`].
231 /// See its documentation for more.
233 /// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain
234 /// [`HashMap`]: /hashbrown/struct.HashMap.html
235 pub struct ParDrain
<'a
, K
, V
, S
> {
236 map
: &'a
mut HashMap
<K
, V
, S
>,
239 impl<K
: Send
, V
: Send
, S
: Send
> ParallelIterator
for ParDrain
<'_
, K
, V
, S
> {
242 #[cfg_attr(feature = "inline-more", inline)]
243 fn drive_unindexed
<C
>(self, consumer
: C
) -> C
::Result
245 C
: UnindexedConsumer
<Self::Item
>,
247 self.map
.table
.par_drain().drive_unindexed(consumer
)
251 impl<K
: fmt
::Debug
+ Eq
+ Hash
, V
: fmt
::Debug
, S
: BuildHasher
> fmt
::Debug
252 for ParDrain
<'_
, K
, V
, S
>
254 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
255 self.map
.iter().fmt(f
)
259 impl<K
: Sync
, V
: Sync
, S
: Sync
> HashMap
<K
, V
, S
> {
260 /// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order.
261 #[cfg_attr(feature = "inline-more", inline)]
262 pub fn par_keys(&self) -> ParKeys
<'_
, K
, V
, S
> {
263 ParKeys { map: self }
266 /// Visits (potentially in parallel) immutably borrowed values in an arbitrary order.
267 #[cfg_attr(feature = "inline-more", inline)]
268 pub fn par_values(&self) -> ParValues
<'_
, K
, V
, S
> {
269 ParValues { map: self }
273 impl<K
: Send
, V
: Send
, S
: Send
> HashMap
<K
, V
, S
> {
274 /// Visits (potentially in parallel) mutably borrowed values in an arbitrary order.
275 #[cfg_attr(feature = "inline-more", inline)]
276 pub fn par_values_mut(&mut self) -> ParValuesMut
<'_
, K
, V
, S
> {
277 ParValuesMut { map: self }
280 /// Consumes (potentially in parallel) all values in an arbitrary order,
281 /// while preserving the map's allocated memory for reuse.
282 #[cfg_attr(feature = "inline-more", inline)]
283 pub fn par_drain(&mut self) -> ParDrain
<'_
, K
, V
, S
> {
284 ParDrain { map: self }
288 impl<K
, V
, S
> HashMap
<K
, V
, S
>
292 S
: BuildHasher
+ Sync
,
294 /// Returns `true` if the map is equal to another,
295 /// i.e. both maps contain the same keys mapped to the same values.
297 /// This method runs in a potentially parallel fashion.
298 pub fn par_eq(&self, other
: &Self) -> bool
{
299 self.len() == other
.len()
302 .all(|(key
, value
)| other
.get(key
).map_or(false, |v
| *value
== *v
))
306 impl<K
: Send
, V
: Send
, S
: Send
> IntoParallelIterator
for HashMap
<K
, V
, S
> {
308 type Iter
= IntoParIter
<K
, V
, S
>;
310 #[cfg_attr(feature = "inline-more", inline)]
311 fn into_par_iter(self) -> Self::Iter
{
312 IntoParIter { map: self }
316 impl<'a
, K
: Sync
, V
: Sync
, S
: Sync
> IntoParallelIterator
for &'a HashMap
<K
, V
, S
> {
317 type Item
= (&'a K
, &'a V
);
318 type Iter
= ParIter
<'a
, K
, V
, S
>;
320 #[cfg_attr(feature = "inline-more", inline)]
321 fn into_par_iter(self) -> Self::Iter
{
322 ParIter { map: self }
326 impl<'a
, K
: Send
+ Sync
, V
: Send
, S
: Send
> IntoParallelIterator
for &'a
mut HashMap
<K
, V
, S
> {
327 type Item
= (&'a K
, &'a
mut V
);
328 type Iter
= ParIterMut
<'a
, K
, V
, S
>;
330 #[cfg_attr(feature = "inline-more", inline)]
331 fn into_par_iter(self) -> Self::Iter
{
332 ParIterMut { map: self }
336 /// Collect (key, value) pairs from a parallel iterator into a
337 /// hashmap. If multiple pairs correspond to the same key, then the
338 /// ones produced earlier in the parallel iterator will be
339 /// overwritten, just as with a sequential iterator.
340 impl<K
, V
, S
> FromParallelIterator
<(K
, V
)> for HashMap
<K
, V
, S
>
344 S
: BuildHasher
+ Default
,
346 fn from_par_iter
<P
>(par_iter
: P
) -> Self
348 P
: IntoParallelIterator
<Item
= (K
, V
)>,
350 let mut map
= HashMap
::default();
351 map
.par_extend(par_iter
);
356 /// Extend a hash map with items from a parallel iterator.
357 impl<K
, V
, S
> ParallelExtend
<(K
, V
)> for HashMap
<K
, V
, S
>
363 fn par_extend
<I
>(&mut self, par_iter
: I
)
365 I
: IntoParallelIterator
<Item
= (K
, V
)>,
367 extend(self, par_iter
);
371 /// Extend a hash map with copied items from a parallel iterator.
372 impl<'a
, K
, V
, S
> ParallelExtend
<(&'a K
, &'a V
)> for HashMap
<K
, V
, S
>
374 K
: Copy
+ Eq
+ Hash
+ Sync
,
378 fn par_extend
<I
>(&mut self, par_iter
: I
)
380 I
: IntoParallelIterator
<Item
= (&'a K
, &'a V
)>,
382 extend(self, par_iter
);
386 // This is equal to the normal `HashMap` -- no custom advantage.
387 fn extend
<K
, V
, S
, I
>(map
: &mut HashMap
<K
, V
, S
>, par_iter
: I
)
391 I
: IntoParallelIterator
,
392 HashMap
<K
, V
, S
>: Extend
<I
::Item
>,
394 let (list
, len
) = super::helpers
::collect(par_iter
);
396 // Keys may be already present or show multiple times in the iterator.
397 // Reserve the entire length if the map is empty.
398 // Otherwise reserve half the length (rounded up), so the map
399 // will only resize twice in the worst case.
400 let reserve
= if map
.is_empty() { len }
else { (len + 1) / 2 }
;
401 map
.reserve(reserve
);
410 use core
::hash
::{Hash, Hasher}
;
411 use core
::sync
::atomic
::{AtomicUsize, Ordering}
;
413 use rayon
::prelude
::*;
415 use crate::hash_map
::HashMap
;
417 struct Dropable
<'a
> {
419 counter
: &'a AtomicUsize
,
423 fn new(k
: usize, counter
: &AtomicUsize
) -> Dropable
<'_
> {
424 counter
.fetch_add(1, Ordering
::Relaxed
);
426 Dropable { k, counter }
430 impl Drop
for Dropable
<'_
> {
432 self.counter
.fetch_sub(1, Ordering
::Relaxed
);
436 impl Clone
for Dropable
<'_
> {
437 fn clone(&self) -> Self {
438 Dropable
::new(self.k
, self.counter
)
442 impl Hash
for Dropable
<'_
> {
443 fn hash
<H
>(&self, state
: &mut H
)
451 impl PartialEq
for Dropable
<'_
> {
452 fn eq(&self, other
: &Self) -> bool
{
457 impl Eq
for Dropable
<'_
> {}
460 fn test_into_iter_drops() {
461 let key
= AtomicUsize
::new(0);
462 let value
= AtomicUsize
::new(0);
465 let mut hm
= HashMap
::new();
467 assert_eq
!(key
.load(Ordering
::Relaxed
), 0);
468 assert_eq
!(value
.load(Ordering
::Relaxed
), 0);
471 let d1
= Dropable
::new(i
, &key
);
472 let d2
= Dropable
::new(i
+ 100, &value
);
476 assert_eq
!(key
.load(Ordering
::Relaxed
), 100);
477 assert_eq
!(value
.load(Ordering
::Relaxed
), 100);
482 // By the way, ensure that cloning doesn't screw up the dropping.
485 assert_eq
!(key
.load(Ordering
::Relaxed
), 100);
486 assert_eq
!(value
.load(Ordering
::Relaxed
), 100);
488 // Ensure that dropping the iterator does not leak anything.
489 drop(hm
.clone().into_par_iter());
492 assert_eq
!(key
.load(Ordering
::Relaxed
), 100);
493 assert_eq
!(value
.load(Ordering
::Relaxed
), 100);
498 .filter(|&(ref key
, _
)| key
.k
< 50)
501 assert_eq
!(key
.load(Ordering
::Relaxed
), 50);
502 assert_eq
!(value
.load(Ordering
::Relaxed
), 50);
505 assert_eq
!(key
.load(Ordering
::Relaxed
), 0);
506 assert_eq
!(value
.load(Ordering
::Relaxed
), 0);
510 fn test_drain_drops() {
511 let key
= AtomicUsize
::new(0);
512 let value
= AtomicUsize
::new(0);
515 let mut hm
= HashMap
::new();
517 assert_eq
!(key
.load(Ordering
::Relaxed
), 0);
518 assert_eq
!(value
.load(Ordering
::Relaxed
), 0);
521 let d1
= Dropable
::new(i
, &key
);
522 let d2
= Dropable
::new(i
+ 100, &value
);
526 assert_eq
!(key
.load(Ordering
::Relaxed
), 100);
527 assert_eq
!(value
.load(Ordering
::Relaxed
), 100);
532 // By the way, ensure that cloning doesn't screw up the dropping.
535 assert_eq
!(key
.load(Ordering
::Relaxed
), 100);
536 assert_eq
!(value
.load(Ordering
::Relaxed
), 100);
538 // Ensure that dropping the drain iterator does not leak anything.
539 drop(hm
.clone().par_drain());
542 assert_eq
!(key
.load(Ordering
::Relaxed
), 100);
543 assert_eq
!(value
.load(Ordering
::Relaxed
), 100);
546 let _v
: Vec
<_
> = hm
.drain().filter(|&(ref key
, _
)| key
.k
< 50).collect();
547 assert
!(hm
.is_empty());
549 assert_eq
!(key
.load(Ordering
::Relaxed
), 50);
550 assert_eq
!(value
.load(Ordering
::Relaxed
), 50);
553 assert_eq
!(key
.load(Ordering
::Relaxed
), 0);
554 assert_eq
!(value
.load(Ordering
::Relaxed
), 0);
558 fn test_empty_iter() {
559 let mut m
: HashMap
<isize, bool
> = HashMap
::new();
560 assert_eq
!(m
.par_drain().count(), 0);
561 assert_eq
!(m
.par_keys().count(), 0);
562 assert_eq
!(m
.par_values().count(), 0);
563 assert_eq
!(m
.par_values_mut().count(), 0);
564 assert_eq
!(m
.par_iter().count(), 0);
565 assert_eq
!(m
.par_iter_mut().count(), 0);
566 assert_eq
!(m
.len(), 0);
567 assert
!(m
.is_empty());
568 assert_eq
!(m
.into_par_iter().count(), 0);
573 let mut m
= HashMap
::with_capacity(4);
575 assert
!(m
.insert(i
, i
* 2).is_none());
577 assert_eq
!(m
.len(), 32);
579 let observed
= AtomicUsize
::new(0);
581 m
.par_iter().for_each(|(k
, v
)| {
582 assert_eq
!(*v
, *k
* 2);
583 observed
.fetch_or(1 << *k
, Ordering
::Relaxed
);
585 assert_eq
!(observed
.into_inner(), 0xFFFF_FFFF);
590 let vec
= vec
![(1, 'a'
), (2, 'b'
), (3, 'c'
)];
591 let map
: HashMap
<_
, _
> = vec
.into_par_iter().collect();
592 let keys
: Vec
<_
> = map
.par_keys().cloned().collect();
593 assert_eq
!(keys
.len(), 3);
594 assert
!(keys
.contains(&1));
595 assert
!(keys
.contains(&2));
596 assert
!(keys
.contains(&3));
601 let vec
= vec
![(1, 'a'
), (2, 'b'
), (3, 'c'
)];
602 let map
: HashMap
<_
, _
> = vec
.into_par_iter().collect();
603 let values
: Vec
<_
> = map
.par_values().cloned().collect();
604 assert_eq
!(values
.len(), 3);
605 assert
!(values
.contains(&'a'
));
606 assert
!(values
.contains(&'b'
));
607 assert
!(values
.contains(&'c'
));
611 fn test_values_mut() {
612 let vec
= vec
![(1, 1), (2, 2), (3, 3)];
613 let mut map
: HashMap
<_
, _
> = vec
.into_par_iter().collect();
614 map
.par_values_mut().for_each(|value
| *value
= (*value
) * 2);
615 let values
: Vec
<_
> = map
.par_values().cloned().collect();
616 assert_eq
!(values
.len(), 3);
617 assert
!(values
.contains(&2));
618 assert
!(values
.contains(&4));
619 assert
!(values
.contains(&6));
624 let mut m1
= HashMap
::new();
629 let mut m2
= HashMap
::new();
633 assert
!(!m1
.par_eq(&m2
));
637 assert
!(m1
.par_eq(&m2
));
641 fn test_from_iter() {
642 let xs
= [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
644 let map
: HashMap
<_
, _
> = xs
.par_iter().cloned().collect();
647 assert_eq
!(map
.get(&k
), Some(&v
));
652 fn test_extend_ref() {
653 let mut a
= HashMap
::new();
655 let mut b
= HashMap
::new();
657 b
.insert(3, "three");
661 assert_eq
!(a
.len(), 3);
662 assert_eq
!(a
[&1], "one");
663 assert_eq
!(a
[&2], "two");
664 assert_eq
!(a
[&3], "three");