dashmap/lib.rs
1#![allow(clippy::type_complexity)]
2
3#[cfg(feature = "arbitrary")]
4mod arbitrary;
5pub mod iter;
6pub mod iter_set;
7mod lock;
8pub mod mapref;
9mod read_only;
10#[cfg(feature = "serde")]
11mod serde;
12mod set;
13pub mod setref;
14mod t;
15pub mod try_result;
16mod util;
17
18#[cfg(feature = "rayon")]
19pub mod rayon {
20 pub mod map;
21 pub mod read_only;
22 pub mod set;
23}
24
25#[cfg(not(feature = "raw-api"))]
26use crate::lock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
27
28#[cfg(feature = "raw-api")]
29pub use crate::lock::{RawRwLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
30
31use cfg_if::cfg_if;
32use core::borrow::Borrow;
33use core::fmt;
34use core::hash::{BuildHasher, Hash, Hasher};
35use core::iter::FromIterator;
36use core::ops::{BitAnd, BitOr, Shl, Shr, Sub};
37use iter::{Iter, IterMut, OwningIter};
38use mapref::entry::{Entry, OccupiedEntry, VacantEntry};
39use mapref::multiple::RefMulti;
40use mapref::one::{Ref, RefMut};
41use once_cell::sync::OnceCell;
42pub use read_only::ReadOnlyView;
43pub use set::DashSet;
44use std::collections::hash_map::RandomState;
45pub use t::Map;
46use try_result::TryResult;
47
48cfg_if! {
49 if #[cfg(feature = "raw-api")] {
50 pub use util::SharedValue;
51 } else {
52 use util::SharedValue;
53 }
54}
55
56pub(crate) type HashMap<K, V, S> = hashbrown::HashMap<K, SharedValue<V>, S>;
57
58// Temporary reimplementation of [`std::collections::TryReserveError`]
59// util [`std::collections::TryReserveError`] stabilises.
60// We cannot easily create `std::collections` error type from `hashbrown` error type
61// without access to `TryReserveError::kind` method.
62#[non_exhaustive]
63#[derive(Clone, PartialEq, Eq, Debug)]
64pub struct TryReserveError {}
65
66fn default_shard_amount() -> usize {
67 static DEFAULT_SHARD_AMOUNT: OnceCell<usize> = OnceCell::new();
68 *DEFAULT_SHARD_AMOUNT.get_or_init(|| {
69 (std::thread::available_parallelism().map_or(1, usize::from) * 4).next_power_of_two()
70 })
71}
72
73fn ncb(shard_amount: usize) -> usize {
74 shard_amount.trailing_zeros() as usize
75}
76
77/// DashMap is an implementation of a concurrent associative array/hashmap in Rust.
78///
79/// DashMap tries to implement an easy to use API similar to `std::collections::HashMap`
80/// with some slight changes to handle concurrency.
81///
82/// DashMap tries to be very simple to use and to be a direct replacement for `RwLock<HashMap<K, V, S>>`.
83/// To accomplish this, all methods take `&self` instead of modifying methods taking `&mut self`.
84/// This allows you to put a DashMap in an `Arc<T>` and share it between threads while being able to modify it.
85///
86/// Documentation mentioning locking behaviour acts in the reference frame of the calling thread.
87/// This means that it is safe to ignore it across multiple threads.
88pub struct DashMap<K, V, S = RandomState> {
89 shift: usize,
90 shards: Box<[RwLock<HashMap<K, V, S>>]>,
91 hasher: S,
92}
93
94impl<K: Eq + Hash + Clone, V: Clone, S: Clone> Clone for DashMap<K, V, S> {
95 fn clone(&self) -> Self {
96 let mut inner_shards = Vec::new();
97
98 for shard in self.shards.iter() {
99 let shard = shard.read();
100
101 inner_shards.push(RwLock::new((*shard).clone()));
102 }
103
104 Self {
105 shift: self.shift,
106 shards: inner_shards.into_boxed_slice(),
107 hasher: self.hasher.clone(),
108 }
109 }
110}
111
112impl<K, V, S> Default for DashMap<K, V, S>
113where
114 K: Eq + Hash,
115 S: Default + BuildHasher + Clone,
116{
117 fn default() -> Self {
118 Self::with_hasher(Default::default())
119 }
120}
121
122impl<'a, K: 'a + Eq + Hash, V: 'a> DashMap<K, V, RandomState> {
123 /// Creates a new DashMap with a capacity of 0.
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// use dashmap::DashMap;
129 ///
130 /// let reviews = DashMap::new();
131 /// reviews.insert("Veloren", "What a fantastic game!");
132 /// ```
133 pub fn new() -> Self {
134 DashMap::with_hasher(RandomState::default())
135 }
136
137 /// Creates a new DashMap with a specified starting capacity.
138 ///
139 /// # Examples
140 ///
141 /// ```
142 /// use dashmap::DashMap;
143 ///
144 /// let mappings = DashMap::with_capacity(2);
145 /// mappings.insert(2, 4);
146 /// mappings.insert(8, 16);
147 /// ```
148 pub fn with_capacity(capacity: usize) -> Self {
149 DashMap::with_capacity_and_hasher(capacity, RandomState::default())
150 }
151
152 /// Creates a new DashMap with a specified shard amount
153 ///
154 /// shard_amount should greater than 0 and be a power of two.
155 /// If a shard_amount which is not a power of two is provided, the function will panic.
156 ///
157 /// # Examples
158 ///
159 /// ```
160 /// use dashmap::DashMap;
161 ///
162 /// let mappings = DashMap::with_shard_amount(32);
163 /// mappings.insert(2, 4);
164 /// mappings.insert(8, 16);
165 /// ```
166 pub fn with_shard_amount(shard_amount: usize) -> Self {
167 Self::with_capacity_and_hasher_and_shard_amount(0, RandomState::default(), shard_amount)
168 }
169
170 /// Creates a new DashMap with a specified capacity and shard amount.
171 ///
172 /// shard_amount should greater than 0 and be a power of two.
173 /// If a shard_amount which is not a power of two is provided, the function will panic.
174 ///
175 /// # Examples
176 ///
177 /// ```
178 /// use dashmap::DashMap;
179 ///
180 /// let mappings = DashMap::with_capacity_and_shard_amount(32, 32);
181 /// mappings.insert(2, 4);
182 /// mappings.insert(8, 16);
183 /// ```
184 pub fn with_capacity_and_shard_amount(capacity: usize, shard_amount: usize) -> Self {
185 Self::with_capacity_and_hasher_and_shard_amount(
186 capacity,
187 RandomState::default(),
188 shard_amount,
189 )
190 }
191}
192
193impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
194 /// Wraps this `DashMap` into a read-only view. This view allows to obtain raw references to the stored values.
195 pub fn into_read_only(self) -> ReadOnlyView<K, V, S> {
196 ReadOnlyView::new(self)
197 }
198
199 /// Creates a new DashMap with a capacity of 0 and the provided hasher.
200 ///
201 /// # Examples
202 ///
203 /// ```
204 /// use dashmap::DashMap;
205 /// use std::collections::hash_map::RandomState;
206 ///
207 /// let s = RandomState::new();
208 /// let reviews = DashMap::with_hasher(s);
209 /// reviews.insert("Veloren", "What a fantastic game!");
210 /// ```
211 pub fn with_hasher(hasher: S) -> Self {
212 Self::with_capacity_and_hasher(0, hasher)
213 }
214
215 /// Creates a new DashMap with a specified starting capacity and hasher.
216 ///
217 /// # Examples
218 ///
219 /// ```
220 /// use dashmap::DashMap;
221 /// use std::collections::hash_map::RandomState;
222 ///
223 /// let s = RandomState::new();
224 /// let mappings = DashMap::with_capacity_and_hasher(2, s);
225 /// mappings.insert(2, 4);
226 /// mappings.insert(8, 16);
227 /// ```
228 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
229 Self::with_capacity_and_hasher_and_shard_amount(capacity, hasher, default_shard_amount())
230 }
231
232 /// Creates a new DashMap with a specified hasher and shard amount
233 ///
234 /// shard_amount should be greater than 0 and a power of two.
235 /// If a shard_amount which is not a power of two is provided, the function will panic.
236 ///
237 /// # Examples
238 ///
239 /// ```
240 /// use dashmap::DashMap;
241 /// use std::collections::hash_map::RandomState;
242 ///
243 /// let s = RandomState::new();
244 /// let mappings = DashMap::with_hasher_and_shard_amount(s, 32);
245 /// mappings.insert(2, 4);
246 /// mappings.insert(8, 16);
247 /// ```
248 pub fn with_hasher_and_shard_amount(hasher: S, shard_amount: usize) -> Self {
249 Self::with_capacity_and_hasher_and_shard_amount(0, hasher, shard_amount)
250 }
251
252 /// Creates a new DashMap with a specified starting capacity, hasher and shard_amount.
253 ///
254 /// shard_amount should greater than 0 and be a power of two.
255 /// If a shard_amount which is not a power of two is provided, the function will panic.
256 ///
257 /// # Examples
258 ///
259 /// ```
260 /// use dashmap::DashMap;
261 /// use std::collections::hash_map::RandomState;
262 ///
263 /// let s = RandomState::new();
264 /// let mappings = DashMap::with_capacity_and_hasher_and_shard_amount(2, s, 32);
265 /// mappings.insert(2, 4);
266 /// mappings.insert(8, 16);
267 /// ```
268 pub fn with_capacity_and_hasher_and_shard_amount(
269 mut capacity: usize,
270 hasher: S,
271 shard_amount: usize,
272 ) -> Self {
273 assert!(shard_amount > 1);
274 assert!(shard_amount.is_power_of_two());
275
276 let shift = util::ptr_size_bits() - ncb(shard_amount);
277
278 if capacity != 0 {
279 capacity = (capacity + (shard_amount - 1)) & !(shard_amount - 1);
280 }
281
282 let cps = capacity / shard_amount;
283
284 let shards = (0..shard_amount)
285 .map(|_| RwLock::new(HashMap::with_capacity_and_hasher(cps, hasher.clone())))
286 .collect();
287
288 Self {
289 shift,
290 shards,
291 hasher,
292 }
293 }
294
295 /// Hash a given item to produce a usize.
296 /// Uses the provided or default HashBuilder.
297 pub fn hash_usize<T: Hash>(&self, item: &T) -> usize {
298 let mut hasher = self.hasher.build_hasher();
299
300 item.hash(&mut hasher);
301
302 hasher.finish() as usize
303 }
304
305 cfg_if! {
306 if #[cfg(feature = "raw-api")] {
307 /// Allows you to peek at the inner shards that store your data.
308 /// You should probably not use this unless you know what you are doing.
309 ///
310 /// Requires the `raw-api` feature to be enabled.
311 ///
312 /// # Examples
313 ///
314 /// ```
315 /// use dashmap::DashMap;
316 ///
317 /// let map = DashMap::<(), ()>::new();
318 /// println!("Amount of shards: {}", map.shards().len());
319 /// ```
320 pub fn shards(&self) -> &[RwLock<HashMap<K, V, S>>] {
321 &self.shards
322 }
323
324 /// Provides mutable access to the inner shards that store your data.
325 /// You should probably not use this unless you know what you are doing.
326 ///
327 /// Requires the `raw-api` feature to be enabled.
328 ///
329 /// # Examples
330 ///
331 /// ```
332 /// use dashmap::DashMap;
333 /// use dashmap::SharedValue;
334 ///
335 /// let mut map = DashMap::<i32, &'static str>::new();
336 /// let shard_ind = map.determine_map(&42);
337 /// map.shards_mut()[shard_ind].get_mut().insert(42, SharedValue::new("forty two"));
338 /// assert_eq!(*map.get(&42).unwrap(), "forty two");
339 /// ```
340 pub fn shards_mut(&mut self) -> &mut [RwLock<HashMap<K, V, S>>] {
341 &mut self.shards
342 }
343
344 /// Consumes this `DashMap` and returns the inner shards.
345 /// You should probably not use this unless you know what you are doing.
346 ///
347 /// Requires the `raw-api` feature to be enabled.
348 ///
349 /// See [`DashMap::shards()`] and [`DashMap::shards_mut()`] for more information.
350 pub fn into_shards(self) -> Box<[RwLock<HashMap<K, V, S>>]> {
351 self.shards
352 }
353 } else {
354 #[allow(dead_code)]
355 pub(crate) fn shards(&self) -> &[RwLock<HashMap<K, V, S>>] {
356 &self.shards
357 }
358
359 #[allow(dead_code)]
360 pub(crate) fn shards_mut(&mut self) -> &mut [RwLock<HashMap<K, V, S>>] {
361 &mut self.shards
362 }
363
364 #[allow(dead_code)]
365 pub(crate) fn into_shards(self) -> Box<[RwLock<HashMap<K, V, S>>]> {
366 self.shards
367 }
368 }
369 }
370
371 cfg_if! {
372 if #[cfg(feature = "raw-api")] {
373 /// Finds which shard a certain key is stored in.
374 /// You should probably not use this unless you know what you are doing.
375 /// Note that shard selection is dependent on the default or provided HashBuilder.
376 ///
377 /// Requires the `raw-api` feature to be enabled.
378 ///
379 /// # Examples
380 ///
381 /// ```
382 /// use dashmap::DashMap;
383 ///
384 /// let map = DashMap::new();
385 /// map.insert("coca-cola", 1.4);
386 /// println!("coca-cola is stored in shard: {}", map.determine_map("coca-cola"));
387 /// ```
388 pub fn determine_map<Q>(&self, key: &Q) -> usize
389 where
390 K: Borrow<Q>,
391 Q: Hash + Eq + ?Sized,
392 {
393 let hash = self.hash_usize(&key);
394 self.determine_shard(hash)
395 }
396 }
397 }
398
399 cfg_if! {
400 if #[cfg(feature = "raw-api")] {
401 /// Finds which shard a certain hash is stored in.
402 ///
403 /// Requires the `raw-api` feature to be enabled.
404 ///
405 /// # Examples
406 ///
407 /// ```
408 /// use dashmap::DashMap;
409 ///
410 /// let map: DashMap<i32, i32> = DashMap::new();
411 /// let key = "key";
412 /// let hash = map.hash_usize(&key);
413 /// println!("hash is stored in shard: {}", map.determine_shard(hash));
414 /// ```
415 pub fn determine_shard(&self, hash: usize) -> usize {
416 // Leave the high 7 bits for the HashBrown SIMD tag.
417 (hash << 7) >> self.shift
418 }
419 } else {
420
421 pub(crate) fn determine_shard(&self, hash: usize) -> usize {
422 // Leave the high 7 bits for the HashBrown SIMD tag.
423 (hash << 7) >> self.shift
424 }
425 }
426 }
427
428 /// Returns a reference to the map's [`BuildHasher`].
429 ///
430 /// # Examples
431 ///
432 /// ```rust
433 /// use dashmap::DashMap;
434 /// use std::collections::hash_map::RandomState;
435 ///
436 /// let hasher = RandomState::new();
437 /// let map: DashMap<i32, i32> = DashMap::new();
438 /// let hasher: &RandomState = map.hasher();
439 /// ```
440 ///
441 /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
442 pub fn hasher(&self) -> &S {
443 &self.hasher
444 }
445
446 /// Inserts a key and a value into the map. Returns the old value associated with the key if there was one.
447 ///
448 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
449 ///
450 /// # Examples
451 ///
452 /// ```
453 /// use dashmap::DashMap;
454 ///
455 /// let map = DashMap::new();
456 /// map.insert("I am the key!", "And I am the value!");
457 /// ```
458 pub fn insert(&self, key: K, value: V) -> Option<V> {
459 self._insert(key, value)
460 }
461
462 /// Removes an entry from the map, returning the key and value if they existed in the map.
463 ///
464 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// use dashmap::DashMap;
470 ///
471 /// let soccer_team = DashMap::new();
472 /// soccer_team.insert("Jack", "Goalie");
473 /// assert_eq!(soccer_team.remove("Jack").unwrap().1, "Goalie");
474 /// ```
475 pub fn remove<Q>(&self, key: &Q) -> Option<(K, V)>
476 where
477 K: Borrow<Q>,
478 Q: Hash + Eq + ?Sized,
479 {
480 self._remove(key)
481 }
482
483 /// Removes an entry from the map, returning the key and value
484 /// if the entry existed and the provided conditional function returned true.
485 ///
486 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
487 ///
488 /// ```
489 /// use dashmap::DashMap;
490 ///
491 /// let soccer_team = DashMap::new();
492 /// soccer_team.insert("Sam", "Forward");
493 /// soccer_team.remove_if("Sam", |_, position| position == &"Goalie");
494 /// assert!(soccer_team.contains_key("Sam"));
495 /// ```
496 /// ```
497 /// use dashmap::DashMap;
498 ///
499 /// let soccer_team = DashMap::new();
500 /// soccer_team.insert("Sam", "Forward");
501 /// soccer_team.remove_if("Sam", |_, position| position == &"Forward");
502 /// assert!(!soccer_team.contains_key("Sam"));
503 /// ```
504 pub fn remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)>
505 where
506 K: Borrow<Q>,
507 Q: Hash + Eq + ?Sized,
508 {
509 self._remove_if(key, f)
510 }
511
512 pub fn remove_if_mut<Q>(&self, key: &Q, f: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)>
513 where
514 K: Borrow<Q>,
515 Q: Hash + Eq + ?Sized,
516 {
517 self._remove_if_mut(key, f)
518 }
519
520 /// Creates an iterator over a DashMap yielding immutable references.
521 ///
522 /// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
523 ///
524 /// # Examples
525 ///
526 /// ```
527 /// use dashmap::DashMap;
528 ///
529 /// let words = DashMap::new();
530 /// words.insert("hello", "world");
531 /// assert_eq!(words.iter().count(), 1);
532 /// ```
533 pub fn iter(&'a self) -> Iter<'a, K, V, S, DashMap<K, V, S>> {
534 self._iter()
535 }
536
537 /// Iterator over a DashMap yielding mutable references.
538 ///
539 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
540 ///
541 /// # Examples
542 ///
543 /// ```
544 /// use dashmap::DashMap;
545 ///
546 /// let map = DashMap::new();
547 /// map.insert("Johnny", 21);
548 /// map.iter_mut().for_each(|mut r| *r += 1);
549 /// assert_eq!(*map.get("Johnny").unwrap(), 22);
550 /// ```
551 pub fn iter_mut(&'a self) -> IterMut<'a, K, V, S, DashMap<K, V, S>> {
552 self._iter_mut()
553 }
554
555 /// Get an immutable reference to an entry in the map
556 ///
557 /// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
558 ///
559 /// # Examples
560 ///
561 /// ```
562 /// use dashmap::DashMap;
563 ///
564 /// let youtubers = DashMap::new();
565 /// youtubers.insert("Bosnian Bill", 457000);
566 /// assert_eq!(*youtubers.get("Bosnian Bill").unwrap(), 457000);
567 /// ```
568 pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V, S>>
569 where
570 K: Borrow<Q>,
571 Q: Hash + Eq + ?Sized,
572 {
573 self._get(key)
574 }
575
576 /// Get a mutable reference to an entry in the map
577 ///
578 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
579 ///
580 /// # Examples
581 ///
582 /// ```
583 /// use dashmap::DashMap;
584 ///
585 /// let class = DashMap::new();
586 /// class.insert("Albin", 15);
587 /// *class.get_mut("Albin").unwrap() -= 1;
588 /// assert_eq!(*class.get("Albin").unwrap(), 14);
589 /// ```
590 pub fn get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V, S>>
591 where
592 K: Borrow<Q>,
593 Q: Hash + Eq + ?Sized,
594 {
595 self._get_mut(key)
596 }
597
598 /// Get an immutable reference to an entry in the map, if the shard is not locked.
599 /// If the shard is locked, the function will return [TryResult::Locked].
600 ///
601 /// # Examples
602 ///
603 /// ```
604 /// use dashmap::DashMap;
605 /// use dashmap::try_result::TryResult;
606 ///
607 /// let map = DashMap::new();
608 /// map.insert("Johnny", 21);
609 ///
610 /// assert_eq!(*map.try_get("Johnny").unwrap(), 21);
611 ///
612 /// let _result1_locking = map.get_mut("Johnny");
613 ///
614 /// let result2 = map.try_get("Johnny");
615 /// assert!(result2.is_locked());
616 /// ```
617 pub fn try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V, S>>
618 where
619 K: Borrow<Q>,
620 Q: Hash + Eq + ?Sized,
621 {
622 self._try_get(key)
623 }
624
625 /// Get a mutable reference to an entry in the map, if the shard is not locked.
626 /// If the shard is locked, the function will return [TryResult::Locked].
627 ///
628 /// # Examples
629 ///
630 /// ```
631 /// use dashmap::DashMap;
632 /// use dashmap::try_result::TryResult;
633 ///
634 /// let map = DashMap::new();
635 /// map.insert("Johnny", 21);
636 ///
637 /// *map.try_get_mut("Johnny").unwrap() += 1;
638 /// assert_eq!(*map.get("Johnny").unwrap(), 22);
639 ///
640 /// let _result1_locking = map.get("Johnny");
641 ///
642 /// let result2 = map.try_get_mut("Johnny");
643 /// assert!(result2.is_locked());
644 /// ```
645 pub fn try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V, S>>
646 where
647 K: Borrow<Q>,
648 Q: Hash + Eq + ?Sized,
649 {
650 self._try_get_mut(key)
651 }
652
653 /// Remove excess capacity to reduce memory usage.
654 ///
655 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
656 pub fn shrink_to_fit(&self) {
657 self._shrink_to_fit();
658 }
659
660 /// Retain elements that whose predicates return true
661 /// and discard elements whose predicates return false.
662 ///
663 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
664 ///
665 /// # Examples
666 ///
667 /// ```
668 /// use dashmap::DashMap;
669 ///
670 /// let people = DashMap::new();
671 /// people.insert("Albin", 15);
672 /// people.insert("Jones", 22);
673 /// people.insert("Charlie", 27);
674 /// people.retain(|_, v| *v > 20);
675 /// assert_eq!(people.len(), 2);
676 /// ```
677 pub fn retain(&self, f: impl FnMut(&K, &mut V) -> bool) {
678 self._retain(f);
679 }
680
681 /// Fetches the total number of key-value pairs stored in the map.
682 ///
683 /// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
684 ///
685 /// # Examples
686 ///
687 /// ```
688 /// use dashmap::DashMap;
689 ///
690 /// let people = DashMap::new();
691 /// people.insert("Albin", 15);
692 /// people.insert("Jones", 22);
693 /// people.insert("Charlie", 27);
694 /// assert_eq!(people.len(), 3);
695 /// ```
696 pub fn len(&self) -> usize {
697 self._len()
698 }
699
700 /// Checks if the map is empty or not.
701 ///
702 /// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
703 ///
704 /// # Examples
705 ///
706 /// ```
707 /// use dashmap::DashMap;
708 ///
709 /// let map = DashMap::<(), ()>::new();
710 /// assert!(map.is_empty());
711 /// ```
712 pub fn is_empty(&self) -> bool {
713 self._is_empty()
714 }
715
716 /// Removes all key-value pairs in the map.
717 ///
718 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
719 ///
720 /// # Examples
721 ///
722 /// ```
723 /// use dashmap::DashMap;
724 ///
725 /// let stats = DashMap::new();
726 /// stats.insert("Goals", 4);
727 /// assert!(!stats.is_empty());
728 /// stats.clear();
729 /// assert!(stats.is_empty());
730 /// ```
731 pub fn clear(&self) {
732 self._clear();
733 }
734
735 /// Returns how many key-value pairs the map can store without reallocating.
736 ///
737 /// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
738 pub fn capacity(&self) -> usize {
739 self._capacity()
740 }
741
742 /// Modify a specific value according to a function.
743 ///
744 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
745 ///
746 /// # Examples
747 ///
748 /// ```
749 /// use dashmap::DashMap;
750 ///
751 /// let stats = DashMap::new();
752 /// stats.insert("Goals", 4);
753 /// stats.alter("Goals", |_, v| v * 2);
754 /// assert_eq!(*stats.get("Goals").unwrap(), 8);
755 /// ```
756 ///
757 /// # Panics
758 ///
759 /// If the given closure panics, then `alter` will abort the process
760 pub fn alter<Q>(&self, key: &Q, f: impl FnOnce(&K, V) -> V)
761 where
762 K: Borrow<Q>,
763 Q: Hash + Eq + ?Sized,
764 {
765 self._alter(key, f);
766 }
767
768 /// Modify every value in the map according to a function.
769 ///
770 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
771 ///
772 /// # Examples
773 ///
774 /// ```
775 /// use dashmap::DashMap;
776 ///
777 /// let stats = DashMap::new();
778 /// stats.insert("Wins", 4);
779 /// stats.insert("Losses", 2);
780 /// stats.alter_all(|_, v| v + 1);
781 /// assert_eq!(*stats.get("Wins").unwrap(), 5);
782 /// assert_eq!(*stats.get("Losses").unwrap(), 3);
783 /// ```
784 ///
785 /// # Panics
786 ///
787 /// If the given closure panics, then `alter_all` will abort the process
788 pub fn alter_all(&self, f: impl FnMut(&K, V) -> V) {
789 self._alter_all(f);
790 }
791
792 /// Scoped access into an item of the map according to a function.
793 ///
794 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
795 ///
796 /// # Examples
797 ///
798 /// ```
799 /// use dashmap::DashMap;
800 ///
801 /// let warehouse = DashMap::new();
802 /// warehouse.insert(4267, ("Banana", 100));
803 /// warehouse.insert(2359, ("Pear", 120));
804 /// let fruit = warehouse.view(&4267, |_k, v| *v);
805 /// assert_eq!(fruit, Some(("Banana", 100)));
806 /// ```
807 ///
808 /// # Panics
809 ///
810 /// If the given closure panics, then `view` will abort the process
811 pub fn view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
812 where
813 K: Borrow<Q>,
814 Q: Hash + Eq + ?Sized,
815 {
816 self._view(key, f)
817 }
818
819 /// Checks if the map contains a specific key.
820 ///
821 /// **Locking behaviour:** May deadlock if called when holding a mutable reference into the map.
822 ///
823 /// # Examples
824 ///
825 /// ```
826 /// use dashmap::DashMap;
827 ///
828 /// let team_sizes = DashMap::new();
829 /// team_sizes.insert("Dakota Cherries", 23);
830 /// assert!(team_sizes.contains_key("Dakota Cherries"));
831 /// ```
832 pub fn contains_key<Q>(&self, key: &Q) -> bool
833 where
834 K: Borrow<Q>,
835 Q: Hash + Eq + ?Sized,
836 {
837 self._contains_key(key)
838 }
839
840 /// Advanced entry API that tries to mimic `std::collections::HashMap`.
841 /// See the documentation on `dashmap::mapref::entry` for more details.
842 ///
843 /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
844 pub fn entry(&'a self, key: K) -> Entry<'a, K, V, S> {
845 self._entry(key)
846 }
847
848 /// Advanced entry API that tries to mimic `std::collections::HashMap`.
849 /// See the documentation on `dashmap::mapref::entry` for more details.
850 ///
851 /// Returns None if the shard is currently locked.
852 pub fn try_entry(&'a self, key: K) -> Option<Entry<'a, K, V, S>> {
853 self._try_entry(key)
854 }
855
856 /// Advanced entry API that tries to mimic `std::collections::HashMap::try_reserve`.
857 /// Tries to reserve capacity for at least `shard * additional`
858 /// and may reserve more space to avoid frequent reallocations.
859 ///
860 /// # Errors
861 ///
862 /// If the capacity overflows, or the allocator reports a failure, then an error is returned.
863 // TODO: return std::collections::TryReserveError once std::collections::TryReserveErrorKind stabilises.
864 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
865 for shard in self.shards.iter() {
866 shard
867 .write()
868 .try_reserve(additional)
869 .map_err(|_| TryReserveError {})?;
870 }
871 Ok(())
872 }
873}
874
875impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
876 for DashMap<K, V, S>
877{
878 fn _shard_count(&self) -> usize {
879 self.shards.len()
880 }
881
882 unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap<K, V, S> {
883 debug_assert!(i < self.shards.len());
884
885 &*self.shards.get_unchecked(i).data_ptr()
886 }
887
888 unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap<K, V, S>> {
889 debug_assert!(i < self.shards.len());
890
891 self.shards.get_unchecked(i).read()
892 }
893
894 unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap<K, V, S>> {
895 debug_assert!(i < self.shards.len());
896
897 self.shards.get_unchecked(i).write()
898 }
899
900 unsafe fn _try_yield_read_shard(
901 &'a self,
902 i: usize,
903 ) -> Option<RwLockReadGuard<'a, HashMap<K, V, S>>> {
904 debug_assert!(i < self.shards.len());
905
906 self.shards.get_unchecked(i).try_read()
907 }
908
909 unsafe fn _try_yield_write_shard(
910 &'a self,
911 i: usize,
912 ) -> Option<RwLockWriteGuard<'a, HashMap<K, V, S>>> {
913 debug_assert!(i < self.shards.len());
914
915 self.shards.get_unchecked(i).try_write()
916 }
917
918 fn _insert(&self, key: K, value: V) -> Option<V> {
919 let hash = self.hash_usize(&key);
920
921 let idx = self.determine_shard(hash);
922
923 let mut shard = unsafe { self._yield_write_shard(idx) };
924
925 shard
926 .insert(key, SharedValue::new(value))
927 .map(|v| v.into_inner())
928 }
929
930 fn _remove<Q>(&self, key: &Q) -> Option<(K, V)>
931 where
932 K: Borrow<Q>,
933 Q: Hash + Eq + ?Sized,
934 {
935 let hash = self.hash_usize(&key);
936
937 let idx = self.determine_shard(hash);
938
939 let mut shard = unsafe { self._yield_write_shard(idx) };
940
941 shard.remove_entry(key).map(|(k, v)| (k, v.into_inner()))
942 }
943
944 fn _remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)>
945 where
946 K: Borrow<Q>,
947 Q: Hash + Eq + ?Sized,
948 {
949 let hash = self.hash_usize(&key);
950
951 let idx = self.determine_shard(hash);
952
953 let mut shard = unsafe { self._yield_write_shard(idx) };
954
955 if let Some((kptr, vptr)) = shard.get_key_value(key) {
956 unsafe {
957 let kptr: *const K = kptr;
958 let vptr: *mut V = vptr.as_ptr();
959
960 if f(&*kptr, &mut *vptr) {
961 shard.remove_entry(key).map(|(k, v)| (k, v.into_inner()))
962 } else {
963 None
964 }
965 }
966 } else {
967 None
968 }
969 }
970
971 fn _remove_if_mut<Q>(&self, key: &Q, f: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)>
972 where
973 K: Borrow<Q>,
974 Q: Hash + Eq + ?Sized,
975 {
976 let hash = self.hash_usize(&key);
977
978 let idx = self.determine_shard(hash);
979
980 let mut shard = unsafe { self._yield_write_shard(idx) };
981
982 if let Some((kptr, vptr)) = shard.get_key_value(key) {
983 unsafe {
984 let kptr: *const K = kptr;
985 let vptr: *mut V = vptr.as_ptr();
986
987 if f(&*kptr, &mut *vptr) {
988 shard.remove_entry(key).map(|(k, v)| (k, v.into_inner()))
989 } else {
990 None
991 }
992 }
993 } else {
994 None
995 }
996 }
997
998 fn _iter(&'a self) -> Iter<'a, K, V, S, DashMap<K, V, S>> {
999 Iter::new(self)
1000 }
1001
1002 fn _iter_mut(&'a self) -> IterMut<'a, K, V, S, DashMap<K, V, S>> {
1003 IterMut::new(self)
1004 }
1005
1006 fn _get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V, S>>
1007 where
1008 K: Borrow<Q>,
1009 Q: Hash + Eq + ?Sized,
1010 {
1011 let hash = self.hash_usize(&key);
1012
1013 let idx = self.determine_shard(hash);
1014
1015 let shard = unsafe { self._yield_read_shard(idx) };
1016
1017 if let Some((kptr, vptr)) = shard.get_key_value(key) {
1018 unsafe {
1019 let kptr: *const K = kptr;
1020 let vptr: *const V = vptr.get();
1021 Some(Ref::new(shard, kptr, vptr))
1022 }
1023 } else {
1024 None
1025 }
1026 }
1027
1028 fn _get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V, S>>
1029 where
1030 K: Borrow<Q>,
1031 Q: Hash + Eq + ?Sized,
1032 {
1033 let hash = self.hash_usize(&key);
1034
1035 let idx = self.determine_shard(hash);
1036
1037 let shard = unsafe { self._yield_write_shard(idx) };
1038
1039 if let Some((kptr, vptr)) = shard.get_key_value(key) {
1040 unsafe {
1041 let kptr: *const K = kptr;
1042 let vptr: *mut V = vptr.as_ptr();
1043 Some(RefMut::new(shard, kptr, vptr))
1044 }
1045 } else {
1046 None
1047 }
1048 }
1049
1050 fn _try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V, S>>
1051 where
1052 K: Borrow<Q>,
1053 Q: Hash + Eq + ?Sized,
1054 {
1055 let hash = self.hash_usize(&key);
1056
1057 let idx = self.determine_shard(hash);
1058
1059 let shard = match unsafe { self._try_yield_read_shard(idx) } {
1060 Some(shard) => shard,
1061 None => return TryResult::Locked,
1062 };
1063
1064 if let Some((kptr, vptr)) = shard.get_key_value(key) {
1065 unsafe {
1066 let kptr: *const K = kptr;
1067 let vptr: *const V = vptr.get();
1068 TryResult::Present(Ref::new(shard, kptr, vptr))
1069 }
1070 } else {
1071 TryResult::Absent
1072 }
1073 }
1074
1075 fn _try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V, S>>
1076 where
1077 K: Borrow<Q>,
1078 Q: Hash + Eq + ?Sized,
1079 {
1080 let hash = self.hash_usize(&key);
1081
1082 let idx = self.determine_shard(hash);
1083
1084 let shard = match unsafe { self._try_yield_write_shard(idx) } {
1085 Some(shard) => shard,
1086 None => return TryResult::Locked,
1087 };
1088
1089 if let Some((kptr, vptr)) = shard.get_key_value(key) {
1090 unsafe {
1091 let kptr: *const K = kptr;
1092 let vptr: *mut V = vptr.as_ptr();
1093 TryResult::Present(RefMut::new(shard, kptr, vptr))
1094 }
1095 } else {
1096 TryResult::Absent
1097 }
1098 }
1099
1100 fn _shrink_to_fit(&self) {
1101 self.shards.iter().for_each(|s| s.write().shrink_to_fit());
1102 }
1103
1104 fn _retain(&self, mut f: impl FnMut(&K, &mut V) -> bool) {
1105 self.shards
1106 .iter()
1107 .for_each(|s| s.write().retain(|k, v| f(k, v.get_mut())));
1108 }
1109
1110 fn _len(&self) -> usize {
1111 self.shards.iter().map(|s| s.read().len()).sum()
1112 }
1113
1114 fn _capacity(&self) -> usize {
1115 self.shards.iter().map(|s| s.read().capacity()).sum()
1116 }
1117
1118 fn _alter<Q>(&self, key: &Q, f: impl FnOnce(&K, V) -> V)
1119 where
1120 K: Borrow<Q>,
1121 Q: Hash + Eq + ?Sized,
1122 {
1123 if let Some(mut r) = self.get_mut(key) {
1124 util::map_in_place_2(r.pair_mut(), f);
1125 }
1126 }
1127
1128 fn _alter_all(&self, mut f: impl FnMut(&K, V) -> V) {
1129 self.shards.iter().for_each(|s| {
1130 s.write()
1131 .iter_mut()
1132 .for_each(|(k, v)| util::map_in_place_2((k, v.get_mut()), &mut f));
1133 });
1134 }
1135
1136 fn _view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
1137 where
1138 K: Borrow<Q>,
1139 Q: Hash + Eq + ?Sized,
1140 {
1141 self.get(key).map(|r| {
1142 let (k, v) = r.pair();
1143 f(k, v)
1144 })
1145 }
1146
1147 fn _entry(&'a self, key: K) -> Entry<'a, K, V, S> {
1148 let hash = self.hash_usize(&key);
1149
1150 let idx = self.determine_shard(hash);
1151
1152 let shard = unsafe { self._yield_write_shard(idx) };
1153
1154 if let Some((kptr, vptr)) = shard.get_key_value(&key) {
1155 unsafe {
1156 let kptr: *const K = kptr;
1157 let vptr: *mut V = vptr.as_ptr();
1158 Entry::Occupied(OccupiedEntry::new(shard, key, (kptr, vptr)))
1159 }
1160 } else {
1161 unsafe { Entry::Vacant(VacantEntry::new(shard, key)) }
1162 }
1163 }
1164
1165 fn _try_entry(&'a self, key: K) -> Option<Entry<'a, K, V, S>> {
1166 let hash = self.hash_usize(&key);
1167
1168 let idx = self.determine_shard(hash);
1169
1170 let shard = match unsafe { self._try_yield_write_shard(idx) } {
1171 Some(shard) => shard,
1172 None => return None,
1173 };
1174
1175 if let Some((kptr, vptr)) = shard.get_key_value(&key) {
1176 unsafe {
1177 let kptr: *const K = kptr;
1178 let vptr: *mut V = vptr.as_ptr();
1179
1180 Some(Entry::Occupied(OccupiedEntry::new(
1181 shard,
1182 key,
1183 (kptr, vptr),
1184 )))
1185 }
1186 } else {
1187 unsafe { Some(Entry::Vacant(VacantEntry::new(shard, key))) }
1188 }
1189 }
1190
1191 fn _hasher(&self) -> S {
1192 self.hasher.clone()
1193 }
1194}
1195
1196impl<K: Eq + Hash + fmt::Debug, V: fmt::Debug, S: BuildHasher + Clone> fmt::Debug
1197 for DashMap<K, V, S>
1198{
1199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1200 let mut pmap = f.debug_map();
1201
1202 for r in self {
1203 let (k, v) = r.pair();
1204
1205 pmap.entry(k, v);
1206 }
1207
1208 pmap.finish()
1209 }
1210}
1211
1212impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> Shl<(K, V)> for &'a DashMap<K, V, S> {
1213 type Output = Option<V>;
1214
1215 fn shl(self, pair: (K, V)) -> Self::Output {
1216 self.insert(pair.0, pair.1)
1217 }
1218}
1219
1220impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> Shr<&Q> for &'a DashMap<K, V, S>
1221where
1222 K: Borrow<Q>,
1223 Q: Hash + Eq + ?Sized,
1224{
1225 type Output = Ref<'a, K, V, S>;
1226
1227 fn shr(self, key: &Q) -> Self::Output {
1228 self.get(key).unwrap()
1229 }
1230}
1231
1232impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> BitOr<&Q> for &'a DashMap<K, V, S>
1233where
1234 K: Borrow<Q>,
1235 Q: Hash + Eq + ?Sized,
1236{
1237 type Output = RefMut<'a, K, V, S>;
1238
1239 fn bitor(self, key: &Q) -> Self::Output {
1240 self.get_mut(key).unwrap()
1241 }
1242}
1243
1244impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> Sub<&Q> for &'a DashMap<K, V, S>
1245where
1246 K: Borrow<Q>,
1247 Q: Hash + Eq + ?Sized,
1248{
1249 type Output = Option<(K, V)>;
1250
1251 fn sub(self, key: &Q) -> Self::Output {
1252 self.remove(key)
1253 }
1254}
1255
1256impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> BitAnd<&Q> for &'a DashMap<K, V, S>
1257where
1258 K: Borrow<Q>,
1259 Q: Hash + Eq + ?Sized,
1260{
1261 type Output = bool;
1262
1263 fn bitand(self, key: &Q) -> Self::Output {
1264 self.contains_key(key)
1265 }
1266}
1267
1268impl<K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for DashMap<K, V, S> {
1269 type Item = (K, V);
1270
1271 type IntoIter = OwningIter<K, V, S>;
1272
1273 fn into_iter(self) -> Self::IntoIter {
1274 OwningIter::new(self)
1275 }
1276}
1277
1278impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for &'a DashMap<K, V, S> {
1279 type Item = RefMulti<'a, K, V, S>;
1280
1281 type IntoIter = Iter<'a, K, V, S, DashMap<K, V, S>>;
1282
1283 fn into_iter(self) -> Self::IntoIter {
1284 self.iter()
1285 }
1286}
1287
1288impl<K: Eq + Hash, V, S: BuildHasher + Clone> Extend<(K, V)> for DashMap<K, V, S> {
1289 fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, intoiter: I) {
1290 for pair in intoiter.into_iter() {
1291 self.insert(pair.0, pair.1);
1292 }
1293 }
1294}
1295
1296impl<K: Eq + Hash, V, S: BuildHasher + Clone + Default> FromIterator<(K, V)> for DashMap<K, V, S> {
1297 fn from_iter<I: IntoIterator<Item = (K, V)>>(intoiter: I) -> Self {
1298 let mut map = DashMap::default();
1299
1300 map.extend(intoiter);
1301
1302 map
1303 }
1304}
1305
1306#[cfg(test)]
1307mod tests {
1308 use crate::DashMap;
1309 use std::collections::hash_map::RandomState;
1310
1311 #[test]
1312 fn test_basic() {
1313 let dm = DashMap::new();
1314
1315 dm.insert(0, 0);
1316
1317 assert_eq!(dm.get(&0).unwrap().value(), &0);
1318 }
1319
1320 #[test]
1321 fn test_default() {
1322 let dm: DashMap<u32, u32> = DashMap::default();
1323
1324 dm.insert(0, 0);
1325
1326 assert_eq!(dm.get(&0).unwrap().value(), &0);
1327 }
1328
1329 #[test]
1330 fn test_multiple_hashes() {
1331 let dm: DashMap<u32, u32> = DashMap::default();
1332
1333 for i in 0..100 {
1334 dm.insert(0, i);
1335
1336 dm.insert(i, i);
1337 }
1338
1339 for i in 1..100 {
1340 let r = dm.get(&i).unwrap();
1341
1342 assert_eq!(i, *r.value());
1343
1344 assert_eq!(i, *r.key());
1345 }
1346
1347 let r = dm.get(&0).unwrap();
1348
1349 assert_eq!(99, *r.value());
1350 }
1351
1352 #[test]
1353 fn test_more_complex_values() {
1354 #[derive(Hash, PartialEq, Debug, Clone)]
1355
1356 struct T0 {
1357 s: String,
1358 u: u8,
1359 }
1360
1361 let dm = DashMap::new();
1362
1363 let range = 0..10;
1364
1365 for i in range {
1366 let t = T0 {
1367 s: i.to_string(),
1368 u: i as u8,
1369 };
1370
1371 dm.insert(i, t.clone());
1372
1373 assert_eq!(&t, dm.get(&i).unwrap().value());
1374 }
1375 }
1376
1377 #[test]
1378 fn test_different_hashers_randomstate() {
1379 let dm_hm_default: DashMap<u32, u32, RandomState> =
1380 DashMap::with_hasher(RandomState::new());
1381
1382 for i in 0..10 {
1383 dm_hm_default.insert(i, i);
1384
1385 assert_eq!(i, *dm_hm_default.get(&i).unwrap().value());
1386 }
1387 }
1388
1389 #[test]
1390 fn test_map_view() {
1391 let dm = DashMap::new();
1392
1393 let vegetables: [String; 4] = [
1394 "Salad".to_string(),
1395 "Beans".to_string(),
1396 "Potato".to_string(),
1397 "Tomato".to_string(),
1398 ];
1399
1400 // Give it some values
1401 dm.insert(0, "Banana".to_string());
1402 dm.insert(4, "Pear".to_string());
1403 dm.insert(9, "Potato".to_string());
1404 dm.insert(12, "Chicken".to_string());
1405
1406 let potato_vegetableness = dm.view(&9, |_, v| vegetables.contains(v));
1407 assert_eq!(potato_vegetableness, Some(true));
1408
1409 let chicken_vegetableness = dm.view(&12, |_, v| vegetables.contains(v));
1410 assert_eq!(chicken_vegetableness, Some(false));
1411
1412 let not_in_map = dm.view(&30, |_k, _v| false);
1413 assert_eq!(not_in_map, None);
1414 }
1415
1416 #[test]
1417 fn test_try_get() {
1418 {
1419 let map = DashMap::new();
1420 map.insert("Johnny", 21);
1421
1422 assert_eq!(*map.try_get("Johnny").unwrap(), 21);
1423
1424 let _result1_locking = map.get_mut("Johnny");
1425
1426 let result2 = map.try_get("Johnny");
1427 assert!(result2.is_locked());
1428 }
1429
1430 {
1431 let map = DashMap::new();
1432 map.insert("Johnny", 21);
1433
1434 *map.try_get_mut("Johnny").unwrap() += 1;
1435 assert_eq!(*map.get("Johnny").unwrap(), 22);
1436
1437 let _result1_locking = map.get("Johnny");
1438
1439 let result2 = map.try_get_mut("Johnny");
1440 assert!(result2.is_locked());
1441 }
1442 }
1443
1444 #[test]
1445 fn test_try_reserve() {
1446 let mut map: DashMap<i32, i32> = DashMap::new();
1447 // DashMap is empty and doesn't allocate memory
1448 assert_eq!(map.capacity(), 0);
1449
1450 map.try_reserve(10).unwrap();
1451
1452 // And now map can hold at least 10 elements
1453 assert!(map.capacity() >= 10);
1454 }
1455
1456 #[test]
1457 fn test_try_reserve_errors() {
1458 let mut map: DashMap<i32, i32> = DashMap::new();
1459
1460 match map.try_reserve(usize::MAX) {
1461 Err(_) => {}
1462 _ => panic!("should have raised CapacityOverflow error"),
1463 }
1464 }
1465}