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