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}