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}