1use crate::cht::map::{
33 bucket::{self, BucketArray},
34 bucket_array_ref::BucketArrayRef,
35 DefaultHashBuilder,
36};
37
38use super::iter::{Iter, ScanningGet};
39
40use std::{
41 borrow::Borrow,
42 hash::{BuildHasher, Hash},
43 ptr,
44 sync::atomic::{self, AtomicUsize, Ordering},
45};
46
47use crossbeam_epoch::Atomic;
48
49pub(crate) struct HashMap<K, V, S = DefaultHashBuilder> {
108 segments: Box<[Segment<K, V>]>,
109 build_hasher: S,
110 len: AtomicUsize,
111 segment_shift: u32,
112}
113
114#[cfg(test)]
115impl<K, V> HashMap<K, V, DefaultHashBuilder> {
116 pub fn with_capacity(capacity: usize) -> Self {
126 Self::with_num_segments_capacity_and_hasher(
127 default_num_segments(),
128 capacity,
129 DefaultHashBuilder::default(),
130 )
131 }
132}
133
134impl<K, V, S> HashMap<K, V, S> {
135 pub(crate) fn with_num_segments_and_hasher(num_segments: usize, build_hasher: S) -> Self {
146 Self::with_num_segments_capacity_and_hasher(num_segments, 0, build_hasher)
147 }
148
149 pub(crate) fn with_num_segments_capacity_and_hasher(
161 num_segments: usize,
162 capacity: usize,
163 build_hasher: S,
164 ) -> Self {
165 assert!(num_segments > 0);
166
167 let actual_num_segments = num_segments.next_power_of_two();
168 let segment_shift = 64 - actual_num_segments.trailing_zeros();
169
170 let mut segments = Vec::with_capacity(actual_num_segments);
171
172 if capacity == 0 {
173 unsafe {
174 ptr::write_bytes(segments.as_mut_ptr(), 0, actual_num_segments);
175 segments.set_len(actual_num_segments);
176 }
177 } else {
178 let actual_capacity = (capacity * 2 / actual_num_segments).next_power_of_two();
179
180 for _ in 0..actual_num_segments {
181 segments.push(Segment {
182 bucket_array: Atomic::new(BucketArray::with_length(0, actual_capacity)),
183 len: AtomicUsize::new(0),
184 });
185 }
186 }
187
188 let segments = segments.into_boxed_slice();
189
190 Self {
191 segments,
192 build_hasher,
193 len: AtomicUsize::new(0),
194 segment_shift,
195 }
196 }
197
198 pub(crate) fn actual_num_segments(&self) -> usize {
199 self.segments.len()
200 }
201
202 pub(crate) fn len(&self) -> usize {
209 self.len.load(Ordering::Relaxed)
210 }
211
212 pub(crate) fn is_empty(&self) -> bool {
219 self.len() == 0
220 }
221
222 #[cfg(any(test, feature = "unstable-debug-counters"))]
233 pub(crate) fn capacity(&self) -> usize {
234 let guard = &crossbeam_epoch::pin();
235
236 self.segments
237 .iter()
238 .map(|s| s.bucket_array.load_consume(guard))
239 .map(|p| unsafe { p.as_ref() })
240 .map(|a| a.map_or(0, BucketArray::capacity))
241 .sum::<usize>()
242 }
243
244 #[cfg(test)]
245 pub(crate) fn num_segments(&self) -> usize {
247 self.segments.len()
248 }
249}
250
251impl<K: Hash + Eq, V, S: BuildHasher> HashMap<K, V, S> {
252 #[inline]
253 pub(crate) fn contains_key(&self, hash: u64, eq: impl FnMut(&K) -> bool) -> bool {
254 self.get_key_value_and_then(hash, eq, |_, _| Some(()))
255 .is_some()
256 }
257
258 #[inline]
260 pub(crate) fn get(&self, hash: u64, eq: impl FnMut(&K) -> bool) -> Option<V>
261 where
262 V: Clone,
263 {
264 self.get_key_value_and(hash, eq, |_, v| v.clone())
265 }
266
267 #[inline]
270 pub(crate) fn get_key_value_and<T>(
271 &self,
272 hash: u64,
273 eq: impl FnMut(&K) -> bool,
274 with_entry: impl FnOnce(&K, &V) -> T,
275 ) -> Option<T> {
276 self.get_key_value_and_then(hash, eq, |k, v| Some(with_entry(k, v)))
277 }
278
279 #[inline]
282 pub(crate) fn get_key_value_and_then<T>(
283 &self,
284 hash: u64,
285 eq: impl FnMut(&K) -> bool,
286 with_entry: impl FnOnce(&K, &V) -> Option<T>,
287 ) -> Option<T> {
288 self.bucket_array_ref(hash)
289 .get_key_value_and_then(hash, eq, with_entry)
290 }
291
292 #[inline]
299 pub fn insert_entry_and<T>(
300 &self,
301 key: K,
302 hash: u64,
303 value: V,
304 with_previous_entry: impl FnOnce(&K, &V) -> T,
305 ) -> Option<T>
306 where
307 V: Clone,
308 {
309 let result = self
310 .bucket_array_ref(hash)
311 .insert_with_or_modify_entry_and(
313 key,
314 hash,
315 || value,
316 |_k, v| v.clone(),
317 with_previous_entry,
318 );
319
320 if result.is_none() {
321 self.len.fetch_add(1, Ordering::Relaxed);
322 }
323
324 result
325 }
326
327 #[inline]
330 pub(crate) fn remove(&self, hash: u64, eq: impl FnMut(&K) -> bool) -> Option<V>
331 where
332 V: Clone,
333 {
334 self.remove_entry_if_and(hash, eq, |_, _| true, |_, v| v.clone())
335 }
336
337 #[inline]
340 pub(crate) fn remove_entry(&self, hash: u64, eq: impl FnMut(&K) -> bool) -> Option<(K, V)>
341 where
342 K: Clone,
343 V: Clone,
344 {
345 self.remove_entry_if_and(hash, eq, |_, _| true, |k, v| (k.clone(), v.clone()))
346 }
347
348 pub(crate) fn remove_if(
357 &self,
358 hash: u64,
359 eq: impl FnMut(&K) -> bool,
360 condition: impl FnMut(&K, &V) -> bool,
361 ) -> Option<V>
362 where
363 V: Clone,
364 {
365 self.remove_entry_if_and(hash, eq, condition, move |_, v| v.clone())
366 }
367
368 #[inline]
378 pub(crate) fn remove_entry_if_and<T>(
379 &self,
380 hash: u64,
381 eq: impl FnMut(&K) -> bool,
382 condition: impl FnMut(&K, &V) -> bool,
383 with_previous_entry: impl FnOnce(&K, &V) -> T,
384 ) -> Option<T> {
385 self.bucket_array_ref(hash)
386 .remove_entry_if_and(hash, eq, condition, move |k, v| {
387 self.len.fetch_sub(1, Ordering::Relaxed);
388
389 with_previous_entry(k, v)
390 })
391 }
392
393 #[inline]
405 pub(crate) fn insert_with_or_modify(
406 &self,
407 key: K,
408 hash: u64,
409 on_insert: impl FnOnce() -> V,
410 on_modify: impl FnMut(&K, &V) -> V,
411 ) -> Option<V>
412 where
413 V: Clone,
414 {
415 self.insert_with_or_modify_entry_and(key, hash, on_insert, on_modify, |_, v| v.clone())
416 }
417
418 #[inline]
431 pub(crate) fn insert_with_or_modify_entry_and<T>(
432 &self,
433 key: K,
434 hash: u64,
435 on_insert: impl FnOnce() -> V,
436 on_modify: impl FnMut(&K, &V) -> V,
437 with_old_entry: impl FnOnce(&K, &V) -> T,
438 ) -> Option<T> {
439 let result = self.bucket_array_ref(hash).insert_with_or_modify_entry_and(
440 key,
441 hash,
442 on_insert,
443 on_modify,
444 with_old_entry,
445 );
446
447 if result.is_none() {
448 self.len.fetch_add(1, Ordering::Relaxed);
449 }
450
451 result
452 }
453
454 #[inline]
455 pub(crate) fn insert_if_not_present(&self, key: K, hash: u64, value: V) -> Option<V>
456 where
457 V: Clone,
458 {
459 let result = self.bucket_array_ref(hash).insert_if_not_present_and(
460 key,
461 hash,
462 || value,
463 |_, v| v.clone(),
464 );
465
466 if result.is_none() {
467 self.len.fetch_add(1, Ordering::Relaxed);
468 }
469
470 result
471 }
472
473 pub(crate) fn keys<T>(&self, segment: usize, with_key: impl FnMut(&K) -> T) -> Option<Vec<T>> {
474 if segment >= self.segments.len() {
475 return None;
476 }
477
478 let Segment {
479 ref bucket_array,
480 ref len,
481 } = self.segments[segment];
482
483 let bucket_array_ref = BucketArrayRef {
484 bucket_array,
485 build_hasher: &self.build_hasher,
486 len,
487 };
488
489 Some(bucket_array_ref.keys(with_key))
490 }
491
492 pub(crate) fn iter(&self) -> Iter<'_, K, V>
493 where
494 K: Clone,
495 V: Clone,
496 {
497 Iter::with_single_cache_segment(self, self.actual_num_segments())
498 }
499
500 #[inline]
501 pub(crate) fn hash<Q>(&self, key: &Q) -> u64
502 where
503 Q: Hash + Eq + ?Sized,
504 K: Borrow<Q>,
505 {
506 bucket::hash(&self.build_hasher, key)
507 }
508}
509
510impl<K, V, S> ScanningGet<K, V> for HashMap<K, V, S>
511where
512 K: Hash + Eq + Clone,
513 V: Clone,
514 S: BuildHasher,
515{
516 fn scanning_get(&self, key: &K) -> Option<V> {
517 let hash = self.hash(key);
518 self.get_key_value_and_then(hash, |k| k == key, |_k, v| Some(v.clone()))
519 }
520
521 fn keys(&self, cht_segment: usize) -> Option<Vec<K>> {
522 self.keys(cht_segment, Clone::clone)
523 }
524}
525
526impl<K, V, S> Drop for HashMap<K, V, S> {
527 fn drop(&mut self) {
528 let guard = unsafe { &crossbeam_epoch::unprotected() };
531 atomic::fence(Ordering::Acquire);
532
533 for Segment {
534 bucket_array: this_bucket_array,
535 ..
536 } in self.segments.iter()
537 {
538 let mut current_ptr = this_bucket_array.load(Ordering::Relaxed, guard);
539
540 while let Some(current_ref) = unsafe { current_ptr.as_ref() } {
541 let next_ptr = current_ref.next.load(Ordering::Relaxed, guard);
542
543 for this_bucket_ptr in current_ref
544 .buckets
545 .iter()
546 .map(|b| b.load(Ordering::Relaxed, guard))
547 .filter(|p| !p.is_null())
548 {
549 if bucket::is_tombstone(this_bucket_ptr) {
550 if next_ptr.is_null() {
556 unsafe { bucket::defer_acquire_destroy(guard, this_bucket_ptr) };
559 }
560 } else {
561 unsafe { bucket::defer_destroy_bucket(guard, this_bucket_ptr) };
563 }
564 }
565
566 unsafe { bucket::defer_acquire_destroy(guard, current_ptr) };
567
568 current_ptr = next_ptr;
569 }
570 }
571 }
572}
573
574impl<K, V, S> HashMap<K, V, S> {
575 #[inline]
576 fn bucket_array_ref(&'_ self, hash: u64) -> BucketArrayRef<'_, K, V, S> {
577 let index = self.segment_index_from_hash(hash);
578
579 let Segment {
580 ref bucket_array,
581 ref len,
582 } = self.segments[index];
583
584 BucketArrayRef {
585 bucket_array,
586 build_hasher: &self.build_hasher,
587 len,
588 }
589 }
590
591 #[inline]
592 fn segment_index_from_hash(&'_ self, hash: u64) -> usize {
593 if self.segment_shift == 64 {
594 0
595 } else {
596 (hash >> self.segment_shift) as usize
597 }
598 }
599}
600
601struct Segment<K, V> {
602 bucket_array: Atomic<BucketArray<K, V>>,
603 len: AtomicUsize,
604}
605
606#[cfg(test)]
607fn default_num_segments() -> usize {
608 crate::common::available_parallelism() * 2
609}
610
611#[cfg(test)]
612mod tests {
613 use std::{
614 collections::BTreeMap,
615 sync::{Arc, Barrier},
616 thread::{spawn, JoinHandle},
617 };
618
619 use super::*;
620 use crate::cht::test_util::{run_deferred, DropNotifier, NoisyDropper};
621
622 #[test]
623 fn single_segment() {
624 let map =
625 HashMap::with_num_segments_capacity_and_hasher(1, 0, DefaultHashBuilder::default());
626
627 assert!(map.is_empty());
628 assert_eq!(map.len(), 0);
629
630 let key = "key1";
631 let hash = map.hash(key);
632
633 assert_eq!(map.insert_entry_and(key, hash, 5, |_, v| *v), None);
634 assert_eq!(map.get(hash, |k| k == &key), Some(5));
635
636 assert!(!map.is_empty());
637 assert_eq!(map.len(), 1);
638
639 assert_eq!(map.remove(hash, |k| k == &key), Some(5));
640 assert!(map.is_empty());
641 assert_eq!(map.len(), 0);
642
643 run_deferred();
644 }
645
646 #[test]
647 fn insert_if_not_present() {
648 let map =
649 HashMap::with_num_segments_capacity_and_hasher(1, 0, DefaultHashBuilder::default());
650
651 let key = "key1";
652 let hash = map.hash(key);
653
654 assert_eq!(map.insert_if_not_present(key, hash, 5), None);
655 assert_eq!(map.get(hash, |k| k == &key), Some(5));
656
657 assert_eq!(map.insert_if_not_present(key, hash, 6), Some(5));
658 assert_eq!(map.get(hash, |k| k == &key), Some(5));
659
660 assert_eq!(map.remove(hash, |k| k == &key), Some(5));
661
662 assert_eq!(map.insert_if_not_present(key, hash, 7), None);
663 assert_eq!(map.get(hash, |k| k == &key), Some(7));
664
665 assert_eq!(map.remove(hash, |k| k == &key), Some(7));
666 assert!(map.is_empty());
667 assert_eq!(map.len(), 0);
668
669 run_deferred();
670 }
671
672 #[cfg_attr(mips, ignore)]
673 #[test]
674 fn concurrent_insert_if_not_present() {
675 const NUM_THREADS: usize = 64;
676 const MAX_VALUE: usize = 512;
677
678 let hashmap = Arc::new(HashMap::with_capacity(0));
679 let barrier = Arc::new(Barrier::new(NUM_THREADS));
680
681 #[allow(clippy::needless_collect)]
682 let threads: Vec<_> = (0..NUM_THREADS)
683 .map(|thread_id| {
684 let hashmap = Arc::clone(&hashmap);
685 let barrier = Arc::clone(&barrier);
686
687 spawn(move || {
688 barrier.wait();
689 let mut success_count = 0usize;
690
691 for key in 0..MAX_VALUE {
692 let hash = hashmap.hash(&key);
693 let result = hashmap.insert_if_not_present(key, hash, thread_id);
694 if result.is_none() {
695 success_count += 1;
696 }
697 }
698
699 (thread_id, success_count)
700 })
701 })
702 .collect();
703
704 let results1 = threads
707 .into_iter()
708 .map(JoinHandle::join)
709 .collect::<Result<BTreeMap<_, _>, _>>()
710 .expect("Got an error from a thread");
711
712 assert_eq!(hashmap.len(), MAX_VALUE);
713
714 let sum_of_insertions: usize = results1.values().sum();
716 assert_eq!(sum_of_insertions, MAX_VALUE);
717
718 let mut results2 = (0..NUM_THREADS)
723 .map(|thread_id| (thread_id, 0usize))
724 .collect::<BTreeMap<_, _>>();
725
726 for key in 0..MAX_VALUE {
728 let hash = hashmap.hash(&key);
729 if let Some(thread_id) = hashmap.get(hash, |&k| k == key) {
730 let count = results2.get_mut(&thread_id).unwrap();
731 *count += 1;
732 }
733 }
734
735 assert_eq!(results1, results2);
737
738 run_deferred();
739 }
740
741 #[test]
742 fn insertion() {
743 const MAX_VALUE: i32 = 512;
744
745 let map = HashMap::with_capacity(MAX_VALUE as usize);
746
747 for i in 0..MAX_VALUE {
748 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
749
750 assert!(!map.is_empty());
751 assert_eq!(map.len(), (i + 1) as usize);
752
753 for j in 0..=i {
754 let hash = map.hash(&j);
755 assert_eq!(map.get(hash, |&k| k == j), Some(j));
756 assert_eq!(map.insert_entry_and(j, hash, j, |_, v| *v), Some(j));
757 }
758
759 for l in i + 1..MAX_VALUE {
760 assert_eq!(map.get(map.hash(&l), |&k| k == l), None);
761 }
762 }
763
764 run_deferred();
765 }
766
767 #[test]
768 fn growth() {
769 const MAX_VALUE: i32 = 512;
770
771 let map = HashMap::with_capacity(0);
772
773 for i in 0..MAX_VALUE {
774 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
775
776 assert!(!map.is_empty());
777 assert_eq!(map.len(), (i + 1) as usize);
778
779 for j in 0..=i {
780 let hash = map.hash(&j);
781 assert_eq!(map.get(hash, |&k| k == j), Some(j));
782 assert_eq!(map.insert_entry_and(j, hash, j, |_, v| *v), Some(j));
783 }
784
785 for l in i + 1..MAX_VALUE {
786 assert_eq!(map.get(map.hash(&l), |&k| k == l), None);
787 }
788 }
789
790 run_deferred();
791 }
792
793 #[cfg_attr(mips, ignore)]
799 #[test]
800 fn concurrent_insertion() {
801 const MAX_VALUE: i32 = 512;
802 const NUM_THREADS: usize = 64;
803 const MAX_INSERTED_VALUE: i32 = (NUM_THREADS as i32) * MAX_VALUE;
804
805 let map = Arc::new(HashMap::with_capacity(MAX_INSERTED_VALUE as usize));
806 let barrier = Arc::new(Barrier::new(NUM_THREADS));
807
808 #[allow(clippy::needless_collect)]
809 let threads: Vec<_> = (0..NUM_THREADS)
810 .map(|i| {
811 let map = Arc::clone(&map);
812 let barrier = Arc::clone(&barrier);
813
814 spawn(move || {
815 barrier.wait();
816
817 for j in (0..MAX_VALUE).map(|j| j + (i as i32 * MAX_VALUE)) {
818 assert_eq!(map.insert_entry_and(j, map.hash(&j), j, |_, v| *v), None);
819 }
820 })
821 })
822 .collect();
823
824 for result in threads.into_iter().map(JoinHandle::join) {
825 assert!(result.is_ok());
826 }
827
828 assert!(!map.is_empty());
829 assert_eq!(map.len(), MAX_INSERTED_VALUE as usize);
830
831 for i in 0..MAX_INSERTED_VALUE {
832 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
833 }
834
835 run_deferred();
836 }
837
838 #[cfg_attr(mips, ignore)]
839 #[test]
840 fn concurrent_growth() {
841 const MAX_VALUE: i32 = 512;
842 const NUM_THREADS: usize = 64;
843 const MAX_INSERTED_VALUE: i32 = (NUM_THREADS as i32) * MAX_VALUE;
844
845 let map = Arc::new(HashMap::with_capacity(0));
846 let barrier = Arc::new(Barrier::new(NUM_THREADS));
847
848 #[allow(clippy::needless_collect)]
849 let threads: Vec<_> = (0..NUM_THREADS)
850 .map(|i| {
851 let map = Arc::clone(&map);
852 let barrier = Arc::clone(&barrier);
853
854 spawn(move || {
855 barrier.wait();
856
857 for j in (0..MAX_VALUE).map(|j| j + (i as i32 * MAX_VALUE)) {
858 assert_eq!(map.insert_entry_and(j, map.hash(&j), j, |_, v| *v), None);
859 }
860 })
861 })
862 .collect();
863
864 for result in threads.into_iter().map(|t| t.join()) {
865 assert!(result.is_ok());
866 }
867
868 assert!(!map.is_empty());
869 assert_eq!(map.len(), MAX_INSERTED_VALUE as usize);
870
871 for i in 0..MAX_INSERTED_VALUE {
872 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
873 }
874
875 run_deferred();
876 }
877
878 #[test]
879 fn removal() {
880 const MAX_VALUE: i32 = 512;
881
882 let map = HashMap::with_capacity(MAX_VALUE as usize);
883
884 for i in 0..MAX_VALUE {
885 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
886 }
887
888 for i in 0..MAX_VALUE {
889 assert_eq!(map.remove(map.hash(&i), |&k| k == i), Some(i));
890 }
891
892 assert!(map.is_empty());
893 assert_eq!(map.len(), 0);
894
895 for i in 0..MAX_VALUE {
896 assert_eq!(map.get(map.hash(&i), |&k| k == i), None);
897 }
898
899 run_deferred();
900 }
901
902 #[cfg_attr(mips, ignore)]
903 #[test]
904 fn concurrent_removal() {
905 const MAX_VALUE: i32 = 512;
906 const NUM_THREADS: usize = 64;
907 const MAX_INSERTED_VALUE: i32 = (NUM_THREADS as i32) * MAX_VALUE;
908
909 let map = HashMap::with_capacity(MAX_INSERTED_VALUE as usize);
910
911 for i in 0..MAX_INSERTED_VALUE {
912 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
913 }
914
915 let map = Arc::new(map);
916 let barrier = Arc::new(Barrier::new(NUM_THREADS));
917
918 #[allow(clippy::needless_collect)]
919 let threads: Vec<_> = (0..NUM_THREADS)
920 .map(|i| {
921 let map = Arc::clone(&map);
922 let barrier = Arc::clone(&barrier);
923
924 spawn(move || {
925 barrier.wait();
926
927 for j in (0..MAX_VALUE).map(|j| j + (i as i32 * MAX_VALUE)) {
928 assert_eq!(map.remove(map.hash(&j), |&k| k == j), Some(j));
929 }
930 })
931 })
932 .collect();
933
934 for result in threads.into_iter().map(|t| t.join()) {
935 assert!(result.is_ok());
936 }
937
938 assert_eq!(map.len(), 0);
939
940 for i in 0..MAX_INSERTED_VALUE {
941 assert_eq!(map.get(map.hash(&i), |&k| k == i), None);
942 }
943
944 run_deferred();
945 }
946
947 #[cfg_attr(mips, ignore)]
948 #[test]
949 fn concurrent_insertion_and_removal() {
950 const MAX_VALUE: i32 = 512;
951 const NUM_THREADS: usize = 64;
952 const MAX_INSERTED_VALUE: i32 = (NUM_THREADS as i32) * MAX_VALUE * 2;
953 const INSERTED_MIDPOINT: i32 = MAX_INSERTED_VALUE / 2;
954
955 let map = HashMap::with_capacity(MAX_INSERTED_VALUE as usize);
956
957 for i in INSERTED_MIDPOINT..MAX_INSERTED_VALUE {
958 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
959 }
960
961 let map = Arc::new(map);
962 let barrier = Arc::new(Barrier::new(NUM_THREADS * 2));
963
964 #[allow(clippy::needless_collect)]
965 let insert_threads: Vec<_> = (0..NUM_THREADS)
966 .map(|i| {
967 let map = Arc::clone(&map);
968 let barrier = Arc::clone(&barrier);
969
970 spawn(move || {
971 barrier.wait();
972
973 for j in (0..MAX_VALUE).map(|j| j + (i as i32 * MAX_VALUE)) {
974 assert_eq!(map.insert_entry_and(j, map.hash(&j), j, |_, v| *v), None);
975 }
976 })
977 })
978 .collect();
979
980 #[allow(clippy::needless_collect)]
981 let remove_threads: Vec<_> = (0..NUM_THREADS)
982 .map(|i| {
983 let map = Arc::clone(&map);
984 let barrier = Arc::clone(&barrier);
985
986 spawn(move || {
987 barrier.wait();
988
989 for j in (0..MAX_VALUE).map(|j| INSERTED_MIDPOINT + j + (i as i32 * MAX_VALUE))
990 {
991 assert_eq!(map.remove(map.hash(&j), |&k| k == j), Some(j));
992 }
993 })
994 })
995 .collect();
996
997 for result in insert_threads
998 .into_iter()
999 .chain(remove_threads)
1000 .map(|t| t.join())
1001 {
1002 assert!(result.is_ok());
1003 }
1004
1005 assert!(!map.is_empty());
1006 assert_eq!(map.len(), INSERTED_MIDPOINT as usize);
1007
1008 for i in 0..INSERTED_MIDPOINT {
1009 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
1010 }
1011
1012 for i in INSERTED_MIDPOINT..MAX_INSERTED_VALUE {
1013 assert_eq!(map.get(map.hash(&i), |&k| k == i), None);
1014 }
1015
1016 run_deferred();
1017 }
1018
1019 #[cfg_attr(mips, ignore)]
1020 #[test]
1021 fn concurrent_growth_and_removal() {
1022 const MAX_VALUE: i32 = 512;
1023 const NUM_THREADS: usize = 64;
1024 const MAX_INSERTED_VALUE: i32 = (NUM_THREADS as i32) * MAX_VALUE * 2;
1025 const INSERTED_MIDPOINT: i32 = MAX_INSERTED_VALUE / 2;
1026
1027 let map = HashMap::with_capacity(INSERTED_MIDPOINT as usize);
1028
1029 for i in INSERTED_MIDPOINT..MAX_INSERTED_VALUE {
1030 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
1031 }
1032
1033 let map = Arc::new(map);
1034 let barrier = Arc::new(Barrier::new(NUM_THREADS * 2));
1035
1036 #[allow(clippy::needless_collect)]
1037 let insert_threads: Vec<_> = (0..NUM_THREADS)
1038 .map(|i| {
1039 let map = Arc::clone(&map);
1040 let barrier = Arc::clone(&barrier);
1041
1042 spawn(move || {
1043 barrier.wait();
1044
1045 for j in (0..MAX_VALUE).map(|j| j + (i as i32 * MAX_VALUE)) {
1046 assert_eq!(map.insert_entry_and(j, map.hash(&j), j, |_, v| *v), None);
1047 }
1048 })
1049 })
1050 .collect();
1051
1052 #[allow(clippy::needless_collect)]
1053 let remove_threads: Vec<_> = (0..NUM_THREADS)
1054 .map(|i| {
1055 let map = Arc::clone(&map);
1056 let barrier = Arc::clone(&barrier);
1057
1058 spawn(move || {
1059 barrier.wait();
1060
1061 for j in (0..MAX_VALUE).map(|j| INSERTED_MIDPOINT + j + (i as i32 * MAX_VALUE))
1062 {
1063 assert_eq!(map.remove(map.hash(&j), |&k| k == j), Some(j));
1064 }
1065 })
1066 })
1067 .collect();
1068
1069 for result in insert_threads
1070 .into_iter()
1071 .chain(remove_threads)
1072 .map(JoinHandle::join)
1073 {
1074 assert!(result.is_ok());
1075 }
1076
1077 assert!(!map.is_empty());
1078 assert_eq!(map.len(), INSERTED_MIDPOINT as usize);
1079
1080 for i in 0..INSERTED_MIDPOINT {
1081 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
1082 }
1083
1084 for i in INSERTED_MIDPOINT..MAX_INSERTED_VALUE {
1085 assert_eq!(map.get(map.hash(&i), |&k| k == i), None);
1086 }
1087
1088 run_deferred();
1089 }
1090
1091 #[test]
1092 fn insert_with_or_modify() {
1093 let map = HashMap::with_capacity(0);
1094
1095 let key = "key1";
1096 let hash = map.hash(&key);
1097
1098 assert_eq!(
1099 map.insert_with_or_modify(key, hash, || 1, |_, x| x + 1),
1100 None
1101 );
1102 assert_eq!(map.get(hash, |&k| k == key), Some(1));
1103
1104 assert_eq!(
1105 map.insert_with_or_modify(key, hash, || 1, |_, x| x + 1),
1106 Some(1)
1107 );
1108 assert_eq!(map.get(hash, |&k| k == key), Some(2));
1109
1110 run_deferred();
1111 }
1112
1113 #[cfg_attr(mips, ignore)]
1114 #[test]
1115 fn concurrent_insert_with_or_modify() {
1116 const NUM_THREADS: usize = 64;
1117 const MAX_VALUE: i32 = 512;
1118
1119 let map = Arc::new(HashMap::with_capacity(0));
1120 let barrier = Arc::new(Barrier::new(NUM_THREADS));
1121
1122 #[allow(clippy::needless_collect)]
1123 let threads: Vec<_> = (0..NUM_THREADS)
1124 .map(|_| {
1125 let map = Arc::clone(&map);
1126 let barrier = Arc::clone(&barrier);
1127
1128 spawn(move || {
1129 barrier.wait();
1130
1131 for j in 0..MAX_VALUE {
1132 map.insert_with_or_modify(j, map.hash(&j), || 1, |_, x| x + 1);
1133 }
1134 })
1135 })
1136 .collect();
1137
1138 for result in threads.into_iter().map(JoinHandle::join) {
1139 assert!(result.is_ok());
1140 }
1141
1142 assert_eq!(map.len(), MAX_VALUE as usize);
1143
1144 for i in 0..MAX_VALUE {
1145 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(NUM_THREADS as i32));
1146 }
1147
1148 run_deferred();
1149 }
1150
1151 #[cfg_attr(mips, ignore)]
1152 #[test]
1153 fn concurrent_overlapped_insertion() {
1154 const NUM_THREADS: usize = 64;
1155 const MAX_VALUE: i32 = 512;
1156
1157 let map = Arc::new(HashMap::with_capacity(MAX_VALUE as usize));
1158 let barrier = Arc::new(Barrier::new(NUM_THREADS));
1159
1160 #[allow(clippy::needless_collect)]
1161 let threads: Vec<_> = (0..NUM_THREADS)
1162 .map(|_| {
1163 let map = Arc::clone(&map);
1164 let barrier = Arc::clone(&barrier);
1165
1166 spawn(move || {
1167 barrier.wait();
1168
1169 for j in 0..MAX_VALUE {
1170 map.insert_entry_and(j, map.hash(&j), j, |_, v| *v);
1171 }
1172 })
1173 })
1174 .collect();
1175
1176 for result in threads.into_iter().map(JoinHandle::join) {
1177 assert!(result.is_ok());
1178 }
1179
1180 assert_eq!(map.len(), MAX_VALUE as usize);
1181
1182 for i in 0..MAX_VALUE {
1183 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
1184 }
1185
1186 run_deferred();
1187 }
1188
1189 #[cfg_attr(any(armv5te, mips), ignore)]
1200 #[test]
1201 fn concurrent_overlapped_growth() {
1202 const NUM_THREADS: usize = 64;
1203 const MAX_VALUE: i32 = 512;
1204
1205 let map = Arc::new(HashMap::with_capacity(1));
1206 let barrier = Arc::new(Barrier::new(NUM_THREADS));
1207
1208 #[allow(clippy::needless_collect)]
1209 let threads: Vec<_> = (0..NUM_THREADS)
1210 .map(|_| {
1211 let map = Arc::clone(&map);
1212 let barrier = Arc::clone(&barrier);
1213
1214 spawn(move || {
1215 barrier.wait();
1216
1217 for j in 0..MAX_VALUE {
1218 map.insert_entry_and(j, map.hash(&j), j, |_, v| *v);
1219 }
1220 })
1221 })
1222 .collect();
1223
1224 for result in threads.into_iter().map(JoinHandle::join) {
1225 assert!(result.is_ok());
1226 }
1227
1228 assert_eq!(map.len(), MAX_VALUE as usize);
1229
1230 for i in 0..MAX_VALUE {
1231 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
1232 }
1233
1234 run_deferred();
1235 }
1236
1237 #[cfg_attr(mips, ignore)]
1238 #[test]
1239 fn concurrent_overlapped_removal() {
1240 const NUM_THREADS: usize = 64;
1241 const MAX_VALUE: i32 = 512;
1242
1243 let map = HashMap::with_capacity(MAX_VALUE as usize);
1244
1245 for i in 0..MAX_VALUE {
1246 map.insert_entry_and(i, map.hash(&i), i, |_, v| *v);
1247 }
1248
1249 let map = Arc::new(map);
1250 let barrier = Arc::new(Barrier::new(NUM_THREADS));
1251
1252 #[allow(clippy::needless_collect)]
1253 let threads: Vec<_> = (0..NUM_THREADS)
1254 .map(|_| {
1255 let map = Arc::clone(&map);
1256 let barrier = Arc::clone(&barrier);
1257
1258 spawn(move || {
1259 barrier.wait();
1260
1261 for j in 0..MAX_VALUE {
1262 let prev_value = map.remove(map.hash(&j), |&k| k == j);
1263
1264 if let Some(v) = prev_value {
1265 assert_eq!(v, j);
1266 }
1267 }
1268 })
1269 })
1270 .collect();
1271
1272 for result in threads.into_iter().map(JoinHandle::join) {
1273 assert!(result.is_ok());
1274 }
1275
1276 assert!(map.is_empty());
1277 assert_eq!(map.len(), 0);
1278
1279 for i in 0..MAX_VALUE {
1280 assert_eq!(map.get(map.hash(&i), |&k| k == i), None);
1281 }
1282
1283 run_deferred();
1284 }
1285
1286 #[test]
1287 fn drop_value() {
1288 let key_parent = Arc::new(DropNotifier::new());
1289 let value_parent = Arc::new(DropNotifier::new());
1290
1291 {
1292 let map = HashMap::with_capacity(0);
1293 let hash = map.hash(&0);
1294
1295 assert_eq!(
1296 map.insert_entry_and(
1297 NoisyDropper::new(Arc::clone(&key_parent), 0),
1298 hash,
1299 NoisyDropper::new(Arc::clone(&value_parent), 0),
1300 |_, _| ()
1301 ),
1302 None
1303 );
1304 assert!(!map.is_empty());
1305 assert_eq!(map.len(), 1);
1306 map.get_key_value_and(hash, |k| k == &0, |_k, v| assert_eq!(v, &0));
1307
1308 map.remove_entry_if_and(hash, |k| k == &0, |_, _| true, |_k, v| assert_eq!(v, &0));
1309 assert!(map.is_empty());
1310 assert_eq!(map.len(), 0);
1311 assert_eq!(map.get_key_value_and(hash, |k| k == &0, |_, _| ()), None);
1312
1313 run_deferred();
1314
1315 assert!(!key_parent.was_dropped());
1316 assert!(value_parent.was_dropped());
1317 }
1318
1319 run_deferred();
1320
1321 assert!(key_parent.was_dropped());
1322 assert!(value_parent.was_dropped());
1323 }
1324
1325 #[test]
1326 fn drop_many_values() {
1327 const NUM_VALUES: usize = 1 << 16;
1328
1329 let key_parents: Vec<_> = std::iter::repeat_with(|| Arc::new(DropNotifier::new()))
1330 .take(NUM_VALUES)
1331 .collect();
1332 let value_parents: Vec<_> = std::iter::repeat_with(|| Arc::new(DropNotifier::new()))
1333 .take(NUM_VALUES)
1334 .collect();
1335
1336 {
1337 let map = HashMap::with_capacity(0);
1338 assert!(map.is_empty());
1339 assert_eq!(map.len(), 0);
1340
1341 for (i, (this_key_parent, this_value_parent)) in
1342 key_parents.iter().zip(value_parents.iter()).enumerate()
1343 {
1344 assert_eq!(
1345 map.insert_entry_and(
1346 NoisyDropper::new(Arc::clone(this_key_parent), i),
1347 map.hash(&i),
1348 NoisyDropper::new(Arc::clone(this_value_parent), i),
1349 |_, _| ()
1350 ),
1351 None
1352 );
1353
1354 assert!(!map.is_empty());
1355 assert_eq!(map.len(), i + 1);
1356 }
1357
1358 for i in 0..NUM_VALUES {
1359 assert_eq!(
1360 map.get_key_value_and(
1361 map.hash(&i),
1362 |k| k == &i,
1363 |k, v| {
1364 assert_eq!(**k, i);
1365 assert_eq!(*v, i);
1366 }
1367 ),
1368 Some(())
1369 );
1370 }
1371
1372 for i in 0..NUM_VALUES {
1373 assert_eq!(
1374 map.remove_entry_if_and(
1375 map.hash(&i),
1376 |k| k == &i,
1377 |_, _| true,
1378 |k, v| {
1379 assert_eq!(**k, i);
1380 assert_eq!(*v, i);
1381 }
1382 ),
1383 Some(())
1384 );
1385 }
1386
1387 assert!(map.is_empty());
1388 assert_eq!(map.len(), 0);
1389
1390 run_deferred();
1391
1392 let live_key_count =
1393 NUM_VALUES - key_parents.iter().filter(|k| k.was_dropped()).count();
1394 let bucket_array_len = map.capacity() * 2;
1395 assert_eq!(bucket_array_len, map.num_segments() * 128 * 2);
1396 assert!(live_key_count <= bucket_array_len / 10);
1397
1398 for this_value_parent in value_parents.iter() {
1399 assert!(this_value_parent.was_dropped());
1400 }
1401
1402 for i in 0..NUM_VALUES {
1403 assert_eq!(
1404 map.get_key_value_and(map.hash(&i), |k| k == &i, |_, _| ()),
1405 None
1406 );
1407 }
1408 } run_deferred();
1411
1412 for this_key_parent in key_parents.into_iter() {
1413 assert!(this_key_parent.was_dropped());
1414 }
1415
1416 for this_value_parent in value_parents.into_iter() {
1417 assert!(this_value_parent.was_dropped());
1418 }
1419 }
1420
1421 #[test]
1422 fn drop_many_values_concurrent() {
1423 const NUM_THREADS: usize = 64;
1424 const NUM_VALUES_PER_THREAD: usize = 512;
1425 const NUM_VALUES: usize = NUM_THREADS * NUM_VALUES_PER_THREAD;
1426
1427 let key_parents: Arc<Vec<_>> = Arc::new(
1428 std::iter::repeat_with(|| Arc::new(DropNotifier::new()))
1429 .take(NUM_VALUES)
1430 .collect(),
1431 );
1432 let value_parents: Arc<Vec<_>> = Arc::new(
1433 std::iter::repeat_with(|| Arc::new(DropNotifier::new()))
1434 .take(NUM_VALUES)
1435 .collect(),
1436 );
1437
1438 {
1439 let map = Arc::new(HashMap::with_capacity(0));
1440 assert!(map.is_empty());
1441 assert_eq!(map.len(), 0);
1442
1443 let barrier = Arc::new(Barrier::new(NUM_THREADS));
1444
1445 #[allow(clippy::needless_collect)]
1446 let handles: Vec<_> = (0..NUM_THREADS)
1447 .map(|i| {
1448 let map = Arc::clone(&map);
1449 let barrier = Arc::clone(&barrier);
1450 let key_parents = Arc::clone(&key_parents);
1451 let value_parents = Arc::clone(&value_parents);
1452
1453 spawn(move || {
1454 barrier.wait();
1455
1456 let these_key_parents = &key_parents
1457 [i * NUM_VALUES_PER_THREAD..(i + 1) * NUM_VALUES_PER_THREAD];
1458 let these_value_parents = &value_parents
1459 [i * NUM_VALUES_PER_THREAD..(i + 1) * NUM_VALUES_PER_THREAD];
1460
1461 for (j, (this_key_parent, this_value_parent)) in these_key_parents
1462 .iter()
1463 .zip(these_value_parents.iter())
1464 .enumerate()
1465 {
1466 let key_value = (i * NUM_VALUES_PER_THREAD + j) as i32;
1467 let hash = map.hash(&key_value);
1468
1469 assert_eq!(
1470 map.insert_entry_and(
1471 NoisyDropper::new(Arc::clone(this_key_parent), key_value),
1472 hash,
1473 NoisyDropper::new(Arc::clone(this_value_parent), key_value),
1474 |_, _| ()
1475 ),
1476 None
1477 );
1478 }
1479 })
1480 })
1481 .collect();
1482
1483 for result in handles.into_iter().map(JoinHandle::join) {
1484 assert!(result.is_ok());
1485 }
1486
1487 assert!(!map.is_empty());
1488 assert_eq!(map.len(), NUM_VALUES);
1489
1490 run_deferred();
1491
1492 for this_key_parent in key_parents.iter() {
1493 assert!(!this_key_parent.was_dropped());
1494 }
1495
1496 for this_value_parent in value_parents.iter() {
1497 assert!(!this_value_parent.was_dropped());
1498 }
1499
1500 for i in (0..NUM_VALUES).map(|i| i as i32) {
1501 assert_eq!(
1502 map.get_key_value_and(
1503 map.hash(&i),
1504 |k| k == &i,
1505 |k, v| {
1506 assert_eq!(**k, i);
1507 assert_eq!(*v, i);
1508 }
1509 ),
1510 Some(())
1511 );
1512 }
1513
1514 #[allow(clippy::needless_collect)]
1515 let handles: Vec<_> = (0..NUM_THREADS)
1516 .map(|i| {
1517 let map = Arc::clone(&map);
1518 let barrier = Arc::clone(&barrier);
1519
1520 spawn(move || {
1521 barrier.wait();
1522
1523 for j in 0..NUM_VALUES_PER_THREAD {
1524 let key_value = (i * NUM_VALUES_PER_THREAD + j) as i32;
1525
1526 assert_eq!(
1527 map.remove_entry_if_and(
1528 map.hash(&key_value),
1529 |k| k == &key_value,
1530 |_, _| true,
1531 |k, v| {
1532 assert_eq!(**k, key_value);
1533 assert_eq!(*v, key_value);
1534 }
1535 ),
1536 Some(())
1537 );
1538 }
1539 })
1540 })
1541 .collect();
1542
1543 for result in handles.into_iter().map(JoinHandle::join) {
1544 assert!(result.is_ok());
1545 }
1546
1547 assert!(map.is_empty());
1548 assert_eq!(map.len(), 0);
1549
1550 run_deferred();
1551
1552 let live_key_count =
1553 NUM_VALUES - key_parents.iter().filter(|k| k.was_dropped()).count();
1554 let bucket_array_len = map.capacity() * 2;
1555 assert_eq!(bucket_array_len, map.num_segments() * 128 * 2);
1556 assert!(live_key_count <= bucket_array_len / 10);
1557
1558 for this_value_parent in value_parents.iter() {
1559 assert!(this_value_parent.was_dropped());
1560 }
1561
1562 for i in (0..NUM_VALUES).map(|i| i as i32) {
1563 assert_eq!(
1564 map.get_key_value_and(map.hash(&i), |k| k == &i, |_, _| ()),
1565 None
1566 );
1567 }
1568 } run_deferred();
1571
1572 for this_key_parent in key_parents.iter() {
1573 assert!(this_key_parent.was_dropped());
1574 }
1575
1576 for this_value_parent in value_parents.iter() {
1577 assert!(this_value_parent.was_dropped());
1578 }
1579 }
1580
1581 #[test]
1582 fn drop_map_after_concurrent_updates() {
1583 const NUM_THREADS: usize = 64;
1584 const NUM_VALUES_PER_THREAD: usize = 512;
1585 const NUM_VALUES: usize = NUM_THREADS * NUM_VALUES_PER_THREAD;
1586
1587 let key_parents: Arc<Vec<_>> = Arc::new(
1588 std::iter::repeat_with(|| Arc::new(DropNotifier::new()))
1589 .take(NUM_VALUES)
1590 .collect(),
1591 );
1592 let value_parents: Arc<Vec<_>> = Arc::new(
1593 std::iter::repeat_with(|| Arc::new(DropNotifier::new()))
1594 .take(NUM_VALUES)
1595 .collect(),
1596 );
1597
1598 {
1599 let map = Arc::new(HashMap::with_capacity(0));
1600 assert!(map.is_empty());
1601 assert_eq!(map.len(), 0);
1602
1603 let barrier = Arc::new(Barrier::new(NUM_THREADS));
1604
1605 #[allow(clippy::needless_collect)]
1606 let handles: Vec<_> = (0..NUM_THREADS)
1607 .map(|i| {
1608 let map = Arc::clone(&map);
1609 let barrier = Arc::clone(&barrier);
1610 let key_parents = Arc::clone(&key_parents);
1611 let value_parents = Arc::clone(&value_parents);
1612
1613 spawn(move || {
1614 barrier.wait();
1615
1616 let these_key_parents = &key_parents
1617 [i * NUM_VALUES_PER_THREAD..(i + 1) * NUM_VALUES_PER_THREAD];
1618 let these_value_parents = &value_parents
1619 [i * NUM_VALUES_PER_THREAD..(i + 1) * NUM_VALUES_PER_THREAD];
1620
1621 for (j, (this_key_parent, this_value_parent)) in these_key_parents
1622 .iter()
1623 .zip(these_value_parents.iter())
1624 .enumerate()
1625 {
1626 let key_value = (i * NUM_VALUES_PER_THREAD + j) as i32;
1627 let hash = map.hash(&key_value);
1628
1629 assert_eq!(
1630 map.insert_entry_and(
1631 NoisyDropper::new(Arc::clone(this_key_parent), key_value),
1632 hash,
1633 NoisyDropper::new(Arc::clone(this_value_parent), key_value),
1634 |_, _| ()
1635 ),
1636 None
1637 );
1638 }
1639 })
1640 })
1641 .collect();
1642
1643 for result in handles.into_iter().map(JoinHandle::join) {
1644 assert!(result.is_ok());
1645 }
1646
1647 assert!(!map.is_empty());
1648 assert_eq!(map.len(), NUM_VALUES);
1649
1650 run_deferred();
1651
1652 for this_key_parent in key_parents.iter() {
1653 assert!(!this_key_parent.was_dropped());
1654 }
1655
1656 for this_value_parent in value_parents.iter() {
1657 assert!(!this_value_parent.was_dropped());
1658 }
1659
1660 for i in (0..NUM_VALUES).map(|i| i as i32) {
1661 assert_eq!(
1662 map.get_key_value_and(
1663 map.hash(&i),
1664 |k| k == &i,
1665 |k, v| {
1666 assert_eq!(**k, i);
1667 assert_eq!(*v, i);
1668 }
1669 ),
1670 Some(())
1671 );
1672 }
1673
1674 #[allow(clippy::needless_collect)]
1675 let handles: Vec<_> = (0..NUM_THREADS)
1676 .map(|i| {
1677 let map = Arc::clone(&map);
1678 let barrier = Arc::clone(&barrier);
1679
1680 spawn(move || {
1681 barrier.wait();
1682
1683 for j in 0..NUM_VALUES_PER_THREAD {
1684 let key_value = (i * NUM_VALUES_PER_THREAD + j) as i32;
1685
1686 if key_value % 4 == 0 {
1687 assert_eq!(
1688 map.remove_entry_if_and(
1689 map.hash(&key_value),
1690 |k| k == &key_value,
1691 |_, _| true,
1692 |k, v| {
1693 assert_eq!(**k, key_value);
1694 assert_eq!(*v, key_value);
1695 }
1696 ),
1697 Some(())
1698 );
1699 }
1700 }
1701 })
1702 })
1703 .collect();
1704
1705 for result in handles.into_iter().map(JoinHandle::join) {
1706 assert!(result.is_ok());
1707 }
1708
1709 assert!(!map.is_empty());
1710 assert_eq!(map.len(), NUM_VALUES / 4 * 3);
1711 } run_deferred();
1714
1715 for this_key_parent in key_parents.iter() {
1716 assert!(this_key_parent.was_dropped());
1717 }
1718
1719 for this_value_parent in value_parents.iter() {
1720 assert!(this_value_parent.was_dropped());
1721 }
1722 }
1723
1724 #[test]
1725 fn remove_if() {
1726 const NUM_VALUES: i32 = 512;
1727
1728 let is_even = |_: &i32, v: &i32| *v % 2 == 0;
1729
1730 let map = HashMap::with_capacity(0);
1731
1732 for i in 0..NUM_VALUES {
1733 assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None);
1734 }
1735
1736 for i in 0..NUM_VALUES {
1737 if is_even(&i, &i) {
1738 assert_eq!(map.remove_if(map.hash(&i), |&k| k == i, is_even), Some(i));
1739 } else {
1740 assert_eq!(map.remove_if(map.hash(&i), |&k| k == i, is_even), None);
1741 }
1742 }
1743
1744 for i in (0..NUM_VALUES).filter(|i| i % 2 == 0) {
1745 assert_eq!(map.get(map.hash(&i), |&k| k == i), None);
1746 }
1747
1748 for i in (0..NUM_VALUES).filter(|i| i % 2 != 0) {
1749 assert_eq!(map.get(map.hash(&i), |&k| k == i), Some(i));
1750 }
1751
1752 run_deferred();
1753 }
1754
1755 #[test]
1756 fn keys_in_single_segment() {
1757 let map =
1758 HashMap::with_num_segments_capacity_and_hasher(1, 0, DefaultHashBuilder::default());
1759
1760 assert!(map.is_empty());
1761 assert_eq!(map.len(), 0);
1762
1763 const NUM_KEYS: usize = 200;
1764
1765 for i in 0..NUM_KEYS {
1766 let hash = map.hash(&i);
1767 assert_eq!(map.insert_entry_and(i, hash, i, |_, v| *v), None);
1768 }
1769
1770 assert!(!map.is_empty());
1771 assert_eq!(map.len(), NUM_KEYS);
1772
1773 let mut keys = map.keys(0, |k| *k).unwrap();
1774 assert_eq!(keys.len(), NUM_KEYS);
1775 keys.sort_unstable();
1776
1777 for (i, key) in keys.into_iter().enumerate() {
1778 assert_eq!(i, key);
1779 }
1780
1781 for i in (0..NUM_KEYS).step_by(2) {
1782 assert_eq!(map.remove(map.hash(&i), |&k| k == i), Some(i));
1783 }
1784
1785 assert!(!map.is_empty());
1786 assert_eq!(map.len(), NUM_KEYS / 2);
1787
1788 let mut keys = map.keys(0, |k| *k).unwrap();
1789 assert_eq!(keys.len(), NUM_KEYS / 2);
1790 keys.sort_unstable();
1791
1792 for (i, key) in keys.into_iter().enumerate() {
1793 assert_eq!(i, key / 2);
1794 }
1795
1796 run_deferred();
1797 }
1798}