dashmap/
lib.rs

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