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