1 //! Rayon extensions for `HashMap`.
2
3 use super::raw::{RawIntoParIter, RawParDrain, RawParIter};
4 use crate::hash_map::HashMap;
5 use crate::raw::{Allocator, Global};
6 use core::fmt;
7 use core::hash::{BuildHasher, Hash};
8 use core::marker::PhantomData;
9 use rayon::iter::plumbing::UnindexedConsumer;
10 use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
11
12 /// Parallel iterator over shared references to entries in a map.
13 ///
14 /// This iterator is created by the [`par_iter`] method on [`HashMap`]
15 /// (provided by the [`IntoParallelRefIterator`] trait).
16 /// See its documentation for more.
17 ///
18 /// [`par_iter`]: /hashbrown/struct.HashMap.html#method.par_iter
19 /// [`HashMap`]: /hashbrown/struct.HashMap.html
20 /// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
21 pub struct ParIter<'a, K, V> {
22 inner: RawParIter<(K, V)>,
23 marker: PhantomData<(&'a K, &'a V)>,
24 }
25
26 impl<'a, K: Sync, V: Sync> ParallelIterator for ParIter<'a, K, V> {
27 type Item = (&'a K, &'a V);
28
29 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,30 fn drive_unindexed<C>(self, consumer: C) -> C::Result
31 where
32 C: UnindexedConsumer<Self::Item>,
33 {
34 self.inner
35 .map(|x| unsafe {
36 let r = x.as_ref();
37 (&r.0, &r.1)
38 })
39 .drive_unindexed(consumer)
40 }
41 }
42
43 impl<K, V> Clone for ParIter<'_, K, V> {
44 #[cfg_attr(feature = "inline-more", inline)]
clone(&self) -> Self45 fn clone(&self) -> Self {
46 Self {
47 inner: self.inner.clone(),
48 marker: PhantomData,
49 }
50 }
51 }
52
53 impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug> fmt::Debug for ParIter<'_, K, V> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 let iter = unsafe { self.inner.iter() }.map(|x| unsafe {
56 let r = x.as_ref();
57 (&r.0, &r.1)
58 });
59 f.debug_list().entries(iter).finish()
60 }
61 }
62
63 /// Parallel iterator over shared references to keys in a map.
64 ///
65 /// This iterator is created by the [`par_keys`] method on [`HashMap`].
66 /// See its documentation for more.
67 ///
68 /// [`par_keys`]: /hashbrown/struct.HashMap.html#method.par_keys
69 /// [`HashMap`]: /hashbrown/struct.HashMap.html
70 pub struct ParKeys<'a, K, V> {
71 inner: RawParIter<(K, V)>,
72 marker: PhantomData<(&'a K, &'a V)>,
73 }
74
75 impl<'a, K: Sync, V: Sync> ParallelIterator for ParKeys<'a, K, V> {
76 type Item = &'a K;
77
78 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,79 fn drive_unindexed<C>(self, consumer: C) -> C::Result
80 where
81 C: UnindexedConsumer<Self::Item>,
82 {
83 self.inner
84 .map(|x| unsafe { &x.as_ref().0 })
85 .drive_unindexed(consumer)
86 }
87 }
88
89 impl<K, V> Clone for ParKeys<'_, K, V> {
90 #[cfg_attr(feature = "inline-more", inline)]
clone(&self) -> Self91 fn clone(&self) -> Self {
92 Self {
93 inner: self.inner.clone(),
94 marker: PhantomData,
95 }
96 }
97 }
98
99 impl<K: fmt::Debug + Eq + Hash, V> fmt::Debug for ParKeys<'_, K, V> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 let iter = unsafe { self.inner.iter() }.map(|x| unsafe { &x.as_ref().0 });
102 f.debug_list().entries(iter).finish()
103 }
104 }
105
106 /// Parallel iterator over shared references to values in a map.
107 ///
108 /// This iterator is created by the [`par_values`] method on [`HashMap`].
109 /// See its documentation for more.
110 ///
111 /// [`par_values`]: /hashbrown/struct.HashMap.html#method.par_values
112 /// [`HashMap`]: /hashbrown/struct.HashMap.html
113 pub struct ParValues<'a, K, V> {
114 inner: RawParIter<(K, V)>,
115 marker: PhantomData<(&'a K, &'a V)>,
116 }
117
118 impl<'a, K: Sync, V: Sync> ParallelIterator for ParValues<'a, K, V> {
119 type Item = &'a V;
120
121 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,122 fn drive_unindexed<C>(self, consumer: C) -> C::Result
123 where
124 C: UnindexedConsumer<Self::Item>,
125 {
126 self.inner
127 .map(|x| unsafe { &x.as_ref().1 })
128 .drive_unindexed(consumer)
129 }
130 }
131
132 impl<K, V> Clone for ParValues<'_, K, V> {
133 #[cfg_attr(feature = "inline-more", inline)]
clone(&self) -> Self134 fn clone(&self) -> Self {
135 Self {
136 inner: self.inner.clone(),
137 marker: PhantomData,
138 }
139 }
140 }
141
142 impl<K: Eq + Hash, V: fmt::Debug> fmt::Debug for ParValues<'_, K, V> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 let iter = unsafe { self.inner.iter() }.map(|x| unsafe { &x.as_ref().1 });
145 f.debug_list().entries(iter).finish()
146 }
147 }
148
149 /// Parallel iterator over mutable references to entries in a map.
150 ///
151 /// This iterator is created by the [`par_iter_mut`] method on [`HashMap`]
152 /// (provided by the [`IntoParallelRefMutIterator`] trait).
153 /// See its documentation for more.
154 ///
155 /// [`par_iter_mut`]: /hashbrown/struct.HashMap.html#method.par_iter_mut
156 /// [`HashMap`]: /hashbrown/struct.HashMap.html
157 /// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html
158 pub struct ParIterMut<'a, K, V> {
159 inner: RawParIter<(K, V)>,
160 marker: PhantomData<(&'a K, &'a mut V)>,
161 }
162
163 impl<'a, K: Sync, V: Send> ParallelIterator for ParIterMut<'a, K, V> {
164 type Item = (&'a K, &'a mut V);
165
166 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,167 fn drive_unindexed<C>(self, consumer: C) -> C::Result
168 where
169 C: UnindexedConsumer<Self::Item>,
170 {
171 self.inner
172 .map(|x| unsafe {
173 let r = x.as_mut();
174 (&r.0, &mut r.1)
175 })
176 .drive_unindexed(consumer)
177 }
178 }
179
180 impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug> fmt::Debug for ParIterMut<'_, K, V> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 ParIter {
183 inner: self.inner.clone(),
184 marker: PhantomData,
185 }
186 .fmt(f)
187 }
188 }
189
190 /// Parallel iterator over mutable references to values in a map.
191 ///
192 /// This iterator is created by the [`par_values_mut`] method on [`HashMap`].
193 /// See its documentation for more.
194 ///
195 /// [`par_values_mut`]: /hashbrown/struct.HashMap.html#method.par_values_mut
196 /// [`HashMap`]: /hashbrown/struct.HashMap.html
197 pub struct ParValuesMut<'a, K, V> {
198 inner: RawParIter<(K, V)>,
199 marker: PhantomData<(&'a K, &'a mut V)>,
200 }
201
202 impl<'a, K: Sync, V: Send> ParallelIterator for ParValuesMut<'a, K, V> {
203 type Item = &'a mut V;
204
205 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,206 fn drive_unindexed<C>(self, consumer: C) -> C::Result
207 where
208 C: UnindexedConsumer<Self::Item>,
209 {
210 self.inner
211 .map(|x| unsafe { &mut x.as_mut().1 })
212 .drive_unindexed(consumer)
213 }
214 }
215
216 impl<K: Eq + Hash, V: fmt::Debug> fmt::Debug for ParValuesMut<'_, K, V> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 ParValues {
219 inner: self.inner.clone(),
220 marker: PhantomData,
221 }
222 .fmt(f)
223 }
224 }
225
226 /// Parallel iterator over entries of a consumed map.
227 ///
228 /// This iterator is created by the [`into_par_iter`] method on [`HashMap`]
229 /// (provided by the [`IntoParallelIterator`] trait).
230 /// See its documentation for more.
231 ///
232 /// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter
233 /// [`HashMap`]: /hashbrown/struct.HashMap.html
234 /// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
235 pub struct IntoParIter<K, V, A: Allocator + Clone = Global> {
236 inner: RawIntoParIter<(K, V), A>,
237 }
238
239 impl<K: Send, V: Send, A: Allocator + Clone + Send> ParallelIterator for IntoParIter<K, V, A> {
240 type Item = (K, V);
241
242 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,243 fn drive_unindexed<C>(self, consumer: C) -> C::Result
244 where
245 C: UnindexedConsumer<Self::Item>,
246 {
247 self.inner.drive_unindexed(consumer)
248 }
249 }
250
251 impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug
252 for IntoParIter<K, V, A>
253 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255 ParIter {
256 inner: unsafe { self.inner.par_iter() },
257 marker: PhantomData,
258 }
259 .fmt(f)
260 }
261 }
262
263 /// Parallel draining iterator over entries of a map.
264 ///
265 /// This iterator is created by the [`par_drain`] method on [`HashMap`].
266 /// See its documentation for more.
267 ///
268 /// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain
269 /// [`HashMap`]: /hashbrown/struct.HashMap.html
270 pub struct ParDrain<'a, K, V, A: Allocator + Clone = Global> {
271 inner: RawParDrain<'a, (K, V), A>,
272 }
273
274 impl<K: Send, V: Send, A: Allocator + Clone + Sync> ParallelIterator for ParDrain<'_, K, V, A> {
275 type Item = (K, V);
276
277 #[cfg_attr(feature = "inline-more", inline)]
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,278 fn drive_unindexed<C>(self, consumer: C) -> C::Result
279 where
280 C: UnindexedConsumer<Self::Item>,
281 {
282 self.inner.drive_unindexed(consumer)
283 }
284 }
285
286 impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, A: Allocator + Clone> fmt::Debug
287 for ParDrain<'_, K, V, A>
288 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290 ParIter {
291 inner: unsafe { self.inner.par_iter() },
292 marker: PhantomData,
293 }
294 .fmt(f)
295 }
296 }
297
298 impl<K: Sync, V: Sync, S, A: Allocator + Clone> HashMap<K, V, S, A> {
299 /// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order.
300 #[cfg_attr(feature = "inline-more", inline)]
par_keys(&self) -> ParKeys<'_, K, V>301 pub fn par_keys(&self) -> ParKeys<'_, K, V> {
302 ParKeys {
303 inner: unsafe { self.table.par_iter() },
304 marker: PhantomData,
305 }
306 }
307
308 /// Visits (potentially in parallel) immutably borrowed values in an arbitrary order.
309 #[cfg_attr(feature = "inline-more", inline)]
par_values(&self) -> ParValues<'_, K, V>310 pub fn par_values(&self) -> ParValues<'_, K, V> {
311 ParValues {
312 inner: unsafe { self.table.par_iter() },
313 marker: PhantomData,
314 }
315 }
316 }
317
318 impl<K: Send, V: Send, S, A: Allocator + Clone> HashMap<K, V, S, A> {
319 /// Visits (potentially in parallel) mutably borrowed values in an arbitrary order.
320 #[cfg_attr(feature = "inline-more", inline)]
par_values_mut(&mut self) -> ParValuesMut<'_, K, V>321 pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> {
322 ParValuesMut {
323 inner: unsafe { self.table.par_iter() },
324 marker: PhantomData,
325 }
326 }
327
328 /// Consumes (potentially in parallel) all values in an arbitrary order,
329 /// while preserving the map's allocated memory for reuse.
330 #[cfg_attr(feature = "inline-more", inline)]
par_drain(&mut self) -> ParDrain<'_, K, V, A>331 pub fn par_drain(&mut self) -> ParDrain<'_, K, V, A> {
332 ParDrain {
333 inner: self.table.par_drain(),
334 }
335 }
336 }
337
338 impl<K, V, S, A> HashMap<K, V, S, A>
339 where
340 K: Eq + Hash + Sync,
341 V: PartialEq + Sync,
342 S: BuildHasher + Sync,
343 A: Allocator + Clone + Sync,
344 {
345 /// Returns `true` if the map is equal to another,
346 /// i.e. both maps contain the same keys mapped to the same values.
347 ///
348 /// This method runs in a potentially parallel fashion.
par_eq(&self, other: &Self) -> bool349 pub fn par_eq(&self, other: &Self) -> bool {
350 self.len() == other.len()
351 && self
352 .into_par_iter()
353 .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
354 }
355 }
356
357 impl<K: Send, V: Send, S, A: Allocator + Clone + Send> IntoParallelIterator
358 for HashMap<K, V, S, A>
359 {
360 type Item = (K, V);
361 type Iter = IntoParIter<K, V, A>;
362
363 #[cfg_attr(feature = "inline-more", inline)]
into_par_iter(self) -> Self::Iter364 fn into_par_iter(self) -> Self::Iter {
365 IntoParIter {
366 inner: self.table.into_par_iter(),
367 }
368 }
369 }
370
371 impl<'a, K: Sync, V: Sync, S, A: Allocator + Clone> IntoParallelIterator
372 for &'a HashMap<K, V, S, A>
373 {
374 type Item = (&'a K, &'a V);
375 type Iter = ParIter<'a, K, V>;
376
377 #[cfg_attr(feature = "inline-more", inline)]
into_par_iter(self) -> Self::Iter378 fn into_par_iter(self) -> Self::Iter {
379 ParIter {
380 inner: unsafe { self.table.par_iter() },
381 marker: PhantomData,
382 }
383 }
384 }
385
386 impl<'a, K: Sync, V: Send, S, A: Allocator + Clone> IntoParallelIterator
387 for &'a mut HashMap<K, V, S, A>
388 {
389 type Item = (&'a K, &'a mut V);
390 type Iter = ParIterMut<'a, K, V>;
391
392 #[cfg_attr(feature = "inline-more", inline)]
into_par_iter(self) -> Self::Iter393 fn into_par_iter(self) -> Self::Iter {
394 ParIterMut {
395 inner: unsafe { self.table.par_iter() },
396 marker: PhantomData,
397 }
398 }
399 }
400
401 /// Collect (key, value) pairs from a parallel iterator into a
402 /// hashmap. If multiple pairs correspond to the same key, then the
403 /// ones produced earlier in the parallel iterator will be
404 /// overwritten, just as with a sequential iterator.
405 impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S, Global>
406 where
407 K: Eq + Hash + Send,
408 V: Send,
409 S: BuildHasher + Default,
410 {
from_par_iter<P>(par_iter: P) -> Self where P: IntoParallelIterator<Item = (K, V)>,411 fn from_par_iter<P>(par_iter: P) -> Self
412 where
413 P: IntoParallelIterator<Item = (K, V)>,
414 {
415 let mut map = HashMap::default();
416 map.par_extend(par_iter);
417 map
418 }
419 }
420
421 /// Extend a hash map with items from a parallel iterator.
422 impl<K, V, S, A> ParallelExtend<(K, V)> for HashMap<K, V, S, A>
423 where
424 K: Eq + Hash + Send,
425 V: Send,
426 S: BuildHasher,
427 A: Allocator + Clone,
428 {
par_extend<I>(&mut self, par_iter: I) where I: IntoParallelIterator<Item = (K, V)>,429 fn par_extend<I>(&mut self, par_iter: I)
430 where
431 I: IntoParallelIterator<Item = (K, V)>,
432 {
433 extend(self, par_iter);
434 }
435 }
436
437 /// Extend a hash map with copied items from a parallel iterator.
438 impl<'a, K, V, S, A> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S, A>
439 where
440 K: Copy + Eq + Hash + Sync,
441 V: Copy + Sync,
442 S: BuildHasher,
443 A: Allocator + Clone,
444 {
par_extend<I>(&mut self, par_iter: I) where I: IntoParallelIterator<Item = (&'a K, &'a V)>,445 fn par_extend<I>(&mut self, par_iter: I)
446 where
447 I: IntoParallelIterator<Item = (&'a K, &'a V)>,
448 {
449 extend(self, par_iter);
450 }
451 }
452
453 // This is equal to the normal `HashMap` -- no custom advantage.
extend<K, V, S, A, I>(map: &mut HashMap<K, V, S, A>, par_iter: I) where K: Eq + Hash, S: BuildHasher, I: IntoParallelIterator, A: Allocator + Clone, HashMap<K, V, S, A>: Extend<I::Item>,454 fn extend<K, V, S, A, I>(map: &mut HashMap<K, V, S, A>, par_iter: I)
455 where
456 K: Eq + Hash,
457 S: BuildHasher,
458 I: IntoParallelIterator,
459 A: Allocator + Clone,
460 HashMap<K, V, S, A>: Extend<I::Item>,
461 {
462 let (list, len) = super::helpers::collect(par_iter);
463
464 // Keys may be already present or show multiple times in the iterator.
465 // Reserve the entire length if the map is empty.
466 // Otherwise reserve half the length (rounded up), so the map
467 // will only resize twice in the worst case.
468 let reserve = if map.is_empty() { len } else { (len + 1) / 2 };
469 map.reserve(reserve);
470 for vec in list {
471 map.extend(vec);
472 }
473 }
474
475 #[cfg(test)]
476 mod test_par_map {
477 use alloc::vec::Vec;
478 use core::hash::{Hash, Hasher};
479 use core::sync::atomic::{AtomicUsize, Ordering};
480
481 use rayon::prelude::*;
482
483 use crate::hash_map::HashMap;
484
485 struct Dropable<'a> {
486 k: usize,
487 counter: &'a AtomicUsize,
488 }
489
490 impl Dropable<'_> {
new(k: usize, counter: &AtomicUsize) -> Dropable<'_>491 fn new(k: usize, counter: &AtomicUsize) -> Dropable<'_> {
492 counter.fetch_add(1, Ordering::Relaxed);
493
494 Dropable { k, counter }
495 }
496 }
497
498 impl Drop for Dropable<'_> {
drop(&mut self)499 fn drop(&mut self) {
500 self.counter.fetch_sub(1, Ordering::Relaxed);
501 }
502 }
503
504 impl Clone for Dropable<'_> {
clone(&self) -> Self505 fn clone(&self) -> Self {
506 Dropable::new(self.k, self.counter)
507 }
508 }
509
510 impl Hash for Dropable<'_> {
hash<H>(&self, state: &mut H) where H: Hasher,511 fn hash<H>(&self, state: &mut H)
512 where
513 H: Hasher,
514 {
515 self.k.hash(state)
516 }
517 }
518
519 impl PartialEq for Dropable<'_> {
eq(&self, other: &Self) -> bool520 fn eq(&self, other: &Self) -> bool {
521 self.k == other.k
522 }
523 }
524
525 impl Eq for Dropable<'_> {}
526
527 #[test]
test_into_iter_drops()528 fn test_into_iter_drops() {
529 let key = AtomicUsize::new(0);
530 let value = AtomicUsize::new(0);
531
532 let hm = {
533 let mut hm = HashMap::new();
534
535 assert_eq!(key.load(Ordering::Relaxed), 0);
536 assert_eq!(value.load(Ordering::Relaxed), 0);
537
538 for i in 0..100 {
539 let d1 = Dropable::new(i, &key);
540 let d2 = Dropable::new(i + 100, &value);
541 hm.insert(d1, d2);
542 }
543
544 assert_eq!(key.load(Ordering::Relaxed), 100);
545 assert_eq!(value.load(Ordering::Relaxed), 100);
546
547 hm
548 };
549
550 // By the way, ensure that cloning doesn't screw up the dropping.
551 drop(hm.clone());
552
553 assert_eq!(key.load(Ordering::Relaxed), 100);
554 assert_eq!(value.load(Ordering::Relaxed), 100);
555
556 // Ensure that dropping the iterator does not leak anything.
557 drop(hm.clone().into_par_iter());
558
559 {
560 assert_eq!(key.load(Ordering::Relaxed), 100);
561 assert_eq!(value.load(Ordering::Relaxed), 100);
562
563 // retain only half
564 let _v: Vec<_> = hm
565 .into_par_iter()
566 .filter(|&(ref key, _)| key.k < 50)
567 .collect();
568
569 assert_eq!(key.load(Ordering::Relaxed), 50);
570 assert_eq!(value.load(Ordering::Relaxed), 50);
571 };
572
573 assert_eq!(key.load(Ordering::Relaxed), 0);
574 assert_eq!(value.load(Ordering::Relaxed), 0);
575 }
576
577 #[test]
test_drain_drops()578 fn test_drain_drops() {
579 let key = AtomicUsize::new(0);
580 let value = AtomicUsize::new(0);
581
582 let mut hm = {
583 let mut hm = HashMap::new();
584
585 assert_eq!(key.load(Ordering::Relaxed), 0);
586 assert_eq!(value.load(Ordering::Relaxed), 0);
587
588 for i in 0..100 {
589 let d1 = Dropable::new(i, &key);
590 let d2 = Dropable::new(i + 100, &value);
591 hm.insert(d1, d2);
592 }
593
594 assert_eq!(key.load(Ordering::Relaxed), 100);
595 assert_eq!(value.load(Ordering::Relaxed), 100);
596
597 hm
598 };
599
600 // By the way, ensure that cloning doesn't screw up the dropping.
601 drop(hm.clone());
602
603 assert_eq!(key.load(Ordering::Relaxed), 100);
604 assert_eq!(value.load(Ordering::Relaxed), 100);
605
606 // Ensure that dropping the drain iterator does not leak anything.
607 drop(hm.clone().par_drain());
608
609 {
610 assert_eq!(key.load(Ordering::Relaxed), 100);
611 assert_eq!(value.load(Ordering::Relaxed), 100);
612
613 // retain only half
614 let _v: Vec<_> = hm.drain().filter(|&(ref key, _)| key.k < 50).collect();
615 assert!(hm.is_empty());
616
617 assert_eq!(key.load(Ordering::Relaxed), 50);
618 assert_eq!(value.load(Ordering::Relaxed), 50);
619 };
620
621 assert_eq!(key.load(Ordering::Relaxed), 0);
622 assert_eq!(value.load(Ordering::Relaxed), 0);
623 }
624
625 #[test]
test_empty_iter()626 fn test_empty_iter() {
627 let mut m: HashMap<isize, bool> = HashMap::new();
628 assert_eq!(m.par_drain().count(), 0);
629 assert_eq!(m.par_keys().count(), 0);
630 assert_eq!(m.par_values().count(), 0);
631 assert_eq!(m.par_values_mut().count(), 0);
632 assert_eq!(m.par_iter().count(), 0);
633 assert_eq!(m.par_iter_mut().count(), 0);
634 assert_eq!(m.len(), 0);
635 assert!(m.is_empty());
636 assert_eq!(m.into_par_iter().count(), 0);
637 }
638
639 #[test]
test_iterate()640 fn test_iterate() {
641 let mut m = HashMap::with_capacity(4);
642 for i in 0..32 {
643 assert!(m.insert(i, i * 2).is_none());
644 }
645 assert_eq!(m.len(), 32);
646
647 let observed = AtomicUsize::new(0);
648
649 m.par_iter().for_each(|(k, v)| {
650 assert_eq!(*v, *k * 2);
651 observed.fetch_or(1 << *k, Ordering::Relaxed);
652 });
653 assert_eq!(observed.into_inner(), 0xFFFF_FFFF);
654 }
655
656 #[test]
test_keys()657 fn test_keys() {
658 let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
659 let map: HashMap<_, _> = vec.into_par_iter().collect();
660 let keys: Vec<_> = map.par_keys().cloned().collect();
661 assert_eq!(keys.len(), 3);
662 assert!(keys.contains(&1));
663 assert!(keys.contains(&2));
664 assert!(keys.contains(&3));
665 }
666
667 #[test]
test_values()668 fn test_values() {
669 let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
670 let map: HashMap<_, _> = vec.into_par_iter().collect();
671 let values: Vec<_> = map.par_values().cloned().collect();
672 assert_eq!(values.len(), 3);
673 assert!(values.contains(&'a'));
674 assert!(values.contains(&'b'));
675 assert!(values.contains(&'c'));
676 }
677
678 #[test]
test_values_mut()679 fn test_values_mut() {
680 let vec = vec![(1, 1), (2, 2), (3, 3)];
681 let mut map: HashMap<_, _> = vec.into_par_iter().collect();
682 map.par_values_mut().for_each(|value| *value = (*value) * 2);
683 let values: Vec<_> = map.par_values().cloned().collect();
684 assert_eq!(values.len(), 3);
685 assert!(values.contains(&2));
686 assert!(values.contains(&4));
687 assert!(values.contains(&6));
688 }
689
690 #[test]
test_eq()691 fn test_eq() {
692 let mut m1 = HashMap::new();
693 m1.insert(1, 2);
694 m1.insert(2, 3);
695 m1.insert(3, 4);
696
697 let mut m2 = HashMap::new();
698 m2.insert(1, 2);
699 m2.insert(2, 3);
700
701 assert!(!m1.par_eq(&m2));
702
703 m2.insert(3, 4);
704
705 assert!(m1.par_eq(&m2));
706 }
707
708 #[test]
test_from_iter()709 fn test_from_iter() {
710 let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
711
712 let map: HashMap<_, _> = xs.par_iter().cloned().collect();
713
714 for &(k, v) in &xs {
715 assert_eq!(map.get(&k), Some(&v));
716 }
717 }
718
719 #[test]
test_extend_ref()720 fn test_extend_ref() {
721 let mut a = HashMap::new();
722 a.insert(1, "one");
723 let mut b = HashMap::new();
724 b.insert(2, "two");
725 b.insert(3, "three");
726
727 a.par_extend(&b);
728
729 assert_eq!(a.len(), 3);
730 assert_eq!(a[&1], "one");
731 assert_eq!(a[&2], "two");
732 assert_eq!(a[&3], "three");
733 }
734 }
735