Coverage Report

Created: 2025-09-27 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dashmap-6.1.0/src/lib.rs
Line
Count
Source
1
#![allow(clippy::type_complexity)]
2
3
#[cfg(feature = "arbitrary")]
4
mod arbitrary;
5
pub mod iter;
6
pub mod iter_set;
7
mod lock;
8
pub mod mapref;
9
mod read_only;
10
#[cfg(feature = "serde")]
11
mod serde;
12
mod set;
13
pub mod setref;
14
mod t;
15
pub mod try_result;
16
mod util;
17
18
#[cfg(feature = "rayon")]
19
pub mod rayon {
20
    pub mod map;
21
    pub mod read_only;
22
    pub mod set;
23
}
24
25
#[cfg(not(feature = "raw-api"))]
26
use crate::lock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
27
28
#[cfg(feature = "raw-api")]
29
pub use crate::lock::{RawRwLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
30
31
use cfg_if::cfg_if;
32
use core::borrow::Borrow;
33
use core::fmt;
34
use core::hash::{BuildHasher, Hash, Hasher};
35
use core::iter::FromIterator;
36
use core::ops::{BitAnd, BitOr, Shl, Shr, Sub};
37
use crossbeam_utils::CachePadded;
38
use iter::{Iter, IterMut, OwningIter};
39
pub use mapref::entry::{Entry, OccupiedEntry, VacantEntry};
40
use mapref::multiple::RefMulti;
41
use mapref::one::{Ref, RefMut};
42
use once_cell::sync::OnceCell;
43
pub use read_only::ReadOnlyView;
44
pub use set::DashSet;
45
use std::collections::hash_map::RandomState;
46
pub use t::Map;
47
use try_result::TryResult;
48
49
cfg_if! {
50
    if #[cfg(feature = "raw-api")] {
51
        pub use util::SharedValue;
52
    } else {
53
        use util::SharedValue;
54
    }
55
}
56
57
pub(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)]
65
pub struct TryReserveError {}
66
67
0
fn default_shard_amount() -> usize {
68
    static DEFAULT_SHARD_AMOUNT: OnceCell<usize> = OnceCell::new();
69
0
    *DEFAULT_SHARD_AMOUNT.get_or_init(|| {
70
0
        (std::thread::available_parallelism().map_or(1, usize::from) * 4).next_power_of_two()
71
0
    })
72
0
}
73
74
0
fn ncb(shard_amount: usize) -> usize {
75
0
    shard_amount.trailing_zeros() as usize
76
0
}
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.
89
pub struct DashMap<K, V, S = RandomState> {
90
    shift: usize,
91
    shards: Box<[CachePadded<RwLock<HashMap<K, V>>>]>,
92
    hasher: S,
93
}
94
95
impl<K: Eq + Hash + Clone, V: Clone, S: Clone> Clone for DashMap<K, V, S> {
96
0
    fn clone(&self) -> Self {
97
0
        let mut inner_shards = Vec::new();
98
99
0
        for shard in self.shards.iter() {
100
0
            let shard = shard.read();
101
0
102
0
            inner_shards.push(CachePadded::new(RwLock::new((*shard).clone())));
103
0
        }
104
105
0
        Self {
106
0
            shift: self.shift,
107
0
            shards: inner_shards.into_boxed_slice(),
108
0
            hasher: self.hasher.clone(),
109
0
        }
110
0
    }
111
}
112
113
impl<K, V, S> Default for DashMap<K, V, S>
114
where
115
    K: Eq + Hash,
116
    S: Default + BuildHasher + Clone,
117
{
118
0
    fn default() -> Self {
119
0
        Self::with_hasher(Default::default())
120
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as core::default::Default>::default
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as core::default::Default>::default
121
}
122
123
impl<'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
0
    pub fn new() -> Self {
135
0
        DashMap::with_hasher(RandomState::default())
136
0
    }
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
0
    pub fn with_capacity(capacity: usize) -> Self {
150
0
        DashMap::with_capacity_and_hasher(capacity, RandomState::default())
151
0
    }
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
0
    pub fn with_shard_amount(shard_amount: usize) -> Self {
168
0
        Self::with_capacity_and_hasher_and_shard_amount(0, RandomState::default(), shard_amount)
169
0
    }
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
0
    pub fn with_capacity_and_shard_amount(capacity: usize, shard_amount: usize) -> Self {
186
0
        Self::with_capacity_and_hasher_and_shard_amount(
187
0
            capacity,
188
0
            RandomState::default(),
189
0
            shard_amount,
190
        )
191
0
    }
192
}
193
194
impl<'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
0
    pub fn into_read_only(self) -> ReadOnlyView<K, V, S> {
197
0
        ReadOnlyView::new(self)
198
0
    }
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
0
    pub fn with_hasher(hasher: S) -> Self {
213
0
        Self::with_capacity_and_hasher(0, hasher)
214
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::with_hasher
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::with_hasher
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
0
    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
230
0
        Self::with_capacity_and_hasher_and_shard_amount(capacity, hasher, default_shard_amount())
231
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::with_capacity_and_hasher
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::with_capacity_and_hasher
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
0
    pub fn with_hasher_and_shard_amount(hasher: S, shard_amount: usize) -> Self {
250
0
        Self::with_capacity_and_hasher_and_shard_amount(0, hasher, shard_amount)
251
0
    }
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
0
    pub fn with_capacity_and_hasher_and_shard_amount(
270
0
        mut capacity: usize,
271
0
        hasher: S,
272
0
        shard_amount: usize,
273
0
    ) -> Self {
274
0
        assert!(shard_amount > 1);
275
0
        assert!(shard_amount.is_power_of_two());
276
277
0
        let shift = util::ptr_size_bits() - ncb(shard_amount);
278
279
0
        if capacity != 0 {
280
0
            capacity = (capacity + (shard_amount - 1)) & !(shard_amount - 1);
281
0
        }
282
283
0
        let cps = capacity / shard_amount;
284
285
0
        let shards = (0..shard_amount)
286
0
            .map(|_| CachePadded::new(RwLock::new(HashMap::with_capacity(cps))))
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::with_capacity_and_hasher_and_shard_amount::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::with_capacity_and_hasher_and_shard_amount::{closure#0}
287
0
            .collect();
288
289
0
        Self {
290
0
            shift,
291
0
            shards,
292
0
            hasher,
293
0
        }
294
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::with_capacity_and_hasher_and_shard_amount
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::with_capacity_and_hasher_and_shard_amount
295
296
    /// Hash a given item to produce a usize.
297
    /// Uses the provided or default HashBuilder.
298
0
    pub fn hash_usize<T: Hash>(&self, item: &T) -> usize {
299
0
        self.hash_u64(item) as usize
300
0
    }
301
302
0
    fn hash_u64<T: Hash>(&self, item: &T) -> u64 {
303
0
        let mut hasher = self.hasher.build_hasher();
304
305
0
        item.hash(&mut hasher);
306
307
0
        hasher.finish()
308
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<&usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<&usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<&usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<&usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<&usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::hash_u64::<usize>
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::hash_u64::<_>
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
0
            pub(crate) fn shards(&self) -> &[CachePadded<RwLock<HashMap<K, V>>>] {
370
0
                &self.shards
371
0
            }
372
373
            #[allow(dead_code)]
374
0
            pub(crate) fn shards_mut(&mut self) -> &mut [CachePadded<RwLock<HashMap<K, V>>>] {
375
0
                &mut self.shards
376
0
            }
377
378
            #[allow(dead_code)]
379
0
            pub(crate) fn into_shards(self) -> Box<[CachePadded<RwLock<HashMap<K, V>>>]> {
380
0
                self.shards
381
0
            }
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
0
            pub(crate) fn determine_shard(&self, hash: usize) -> usize {
436
                // Leave the high 7 bits for the HashBrown SIMD tag.
437
0
                (hash << 7) >> self.shift
438
0
            }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::determine_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::determine_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::determine_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::determine_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::determine_shard
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::determine_shard
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
0
    pub fn hasher(&self) -> &S {
457
0
        &self.hasher
458
0
    }
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
0
    pub fn insert(&self, key: K, value: V) -> Option<V> {
473
0
        self._insert(key, value)
474
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::insert
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
0
    pub fn remove<Q>(&self, key: &Q) -> Option<(K, V)>
490
0
    where
491
0
        K: Borrow<Q>,
492
0
        Q: Hash + Eq + ?Sized,
493
    {
494
0
        self._remove(key)
495
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::remove::<_>
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
0
    pub fn remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)>
519
0
    where
520
0
        K: Borrow<Q>,
521
0
        Q: Hash + Eq + ?Sized,
522
    {
523
0
        self._remove_if(key, f)
524
0
    }
525
526
0
    pub fn remove_if_mut<Q>(&self, key: &Q, f: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)>
527
0
    where
528
0
        K: Borrow<Q>,
529
0
        Q: Hash + Eq + ?Sized,
530
    {
531
0
        self._remove_if_mut(key, f)
532
0
    }
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
0
    pub fn iter(&'a self) -> Iter<'a, K, V, S, DashMap<K, V, S>> {
548
0
        self._iter()
549
0
    }
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
0
    pub fn iter_mut(&'a self) -> IterMut<'a, K, V, S, DashMap<K, V, S>> {
566
0
        self._iter_mut()
567
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::iter_mut
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::iter_mut
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
0
    pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V>>
583
0
    where
584
0
        K: Borrow<Q>,
585
0
        Q: Hash + Eq + ?Sized,
586
    {
587
0
        self._get(key)
588
0
    }
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
0
    pub fn get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V>>
605
0
    where
606
0
        K: Borrow<Q>,
607
0
        Q: Hash + Eq + ?Sized,
608
    {
609
0
        self._get_mut(key)
610
0
    }
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
0
    pub fn try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V>>
632
0
    where
633
0
        K: Borrow<Q>,
634
0
        Q: Hash + Eq + ?Sized,
635
    {
636
0
        self._try_get(key)
637
0
    }
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
0
    pub fn try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V>>
660
0
    where
661
0
        K: Borrow<Q>,
662
0
        Q: Hash + Eq + ?Sized,
663
    {
664
0
        self._try_get_mut(key)
665
0
    }
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
0
    pub fn shrink_to_fit(&self) {
684
0
        self._shrink_to_fit();
685
0
    }
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
0
    pub fn retain(&self, f: impl FnMut(&K, &mut V) -> bool) {
705
0
        self._retain(f);
706
0
    }
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
0
    pub fn len(&self) -> usize {
724
0
        self._len()
725
0
    }
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
0
    pub fn is_empty(&self) -> bool {
740
0
        self._is_empty()
741
0
    }
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
0
    pub fn clear(&self) {
759
0
        self._clear();
760
0
    }
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
0
    pub fn capacity(&self) -> usize {
766
0
        self._capacity()
767
0
    }
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
0
    pub fn alter<Q>(&self, key: &Q, f: impl FnOnce(&K, V) -> V)
788
0
    where
789
0
        K: Borrow<Q>,
790
0
        Q: Hash + Eq + ?Sized,
791
    {
792
0
        self._alter(key, f);
793
0
    }
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
0
    pub fn alter_all(&self, f: impl FnMut(&K, V) -> V) {
816
0
        self._alter_all(f);
817
0
    }
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
0
    pub fn view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
839
0
    where
840
0
        K: Borrow<Q>,
841
0
        Q: Hash + Eq + ?Sized,
842
    {
843
0
        self._view(key, f)
844
0
    }
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
0
    pub fn contains_key<Q>(&self, key: &Q) -> bool
860
0
    where
861
0
        K: Borrow<Q>,
862
0
        Q: Hash + Eq + ?Sized,
863
    {
864
0
        self._contains_key(key)
865
0
    }
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
0
    pub fn entry(&'a self, key: K) -> Entry<'a, K, V> {
872
0
        self._entry(key)
873
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::entry
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::entry
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::entry
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::entry
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::entry
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
0
    pub fn try_entry(&'a self, key: K) -> Option<Entry<'a, K, V>> {
880
0
        self._try_entry(key)
881
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::try_entry
Unexecuted instantiation: <dashmap::DashMap<_, _, _>>::try_entry
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
0
    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
892
0
        for shard in self.shards.iter() {
893
0
            shard
894
0
                .write()
895
0
                .try_reserve(additional, |(k, _v)| {
896
0
                    let mut hasher = self.hasher.build_hasher();
897
0
                    k.hash(&mut hasher);
898
0
                    hasher.finish()
899
0
                })
900
0
                .map_err(|_| TryReserveError {})?;
901
        }
902
0
        Ok(())
903
0
    }
904
}
905
906
impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
907
    for DashMap<K, V, S>
908
{
909
0
    fn _shard_count(&self) -> usize {
910
0
        self.shards.len()
911
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_shard_count
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_shard_count
912
913
0
    unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap<K, V> {
914
0
        debug_assert!(i < self.shards.len());
915
916
0
        &*self.shards.get_unchecked(i).data_ptr()
917
0
    }
918
919
0
    unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap<K, V>> {
920
0
        debug_assert!(i < self.shards.len());
921
922
0
        self.shards.get_unchecked(i).read()
923
0
    }
924
925
0
    unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap<K, V>> {
926
0
        debug_assert!(i < self.shards.len());
927
928
0
        self.shards.get_unchecked(i).write()
929
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_yield_write_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_yield_write_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_yield_write_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_yield_write_shard
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_yield_write_shard
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_yield_write_shard
930
931
0
    unsafe fn _try_yield_read_shard(
932
0
        &'a self,
933
0
        i: usize,
934
0
    ) -> Option<RwLockReadGuard<'a, HashMap<K, V>>> {
935
0
        debug_assert!(i < self.shards.len());
936
937
0
        self.shards.get_unchecked(i).try_read()
938
0
    }
939
940
0
    unsafe fn _try_yield_write_shard(
941
0
        &'a self,
942
0
        i: usize,
943
0
    ) -> Option<RwLockWriteGuard<'a, HashMap<K, V>>> {
944
0
        debug_assert!(i < self.shards.len());
945
946
0
        self.shards.get_unchecked(i).try_write()
947
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_try_yield_write_shard
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_try_yield_write_shard
948
949
0
    fn _insert(&self, key: K, value: V) -> Option<V> {
950
0
        match self.entry(key) {
951
0
            Entry::Occupied(mut o) => Some(o.insert(value)),
952
0
            Entry::Vacant(v) => {
953
0
                v.insert(value);
954
0
                None
955
            }
956
        }
957
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_insert
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_insert
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_insert
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_insert
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_insert
958
959
0
    fn _remove<Q>(&self, key: &Q) -> Option<(K, V)>
960
0
    where
961
0
        K: Borrow<Q>,
962
0
        Q: Hash + Eq + ?Sized,
963
    {
964
0
        let hash = self.hash_u64(&key);
965
966
0
        let idx = self.determine_shard(hash as usize);
967
968
0
        let mut shard = unsafe { self._yield_write_shard(idx) };
969
970
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_remove::<_>::{closure#0}
971
0
            let ((k, v), _) = unsafe { shard.remove(bucket) };
972
0
            Some((k, v.into_inner()))
973
        } else {
974
0
            None
975
        }
976
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_remove::<usize>
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_remove::<_>
977
978
0
    fn _remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)>
979
0
    where
980
0
        K: Borrow<Q>,
981
0
        Q: Hash + Eq + ?Sized,
982
    {
983
0
        let hash = self.hash_u64(&key);
984
985
0
        let idx = self.determine_shard(hash as usize);
986
987
0
        let mut shard = unsafe { self._yield_write_shard(idx) };
988
989
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
990
0
            let (k, v) = unsafe { bucket.as_ref() };
991
0
            if f(k, v.get()) {
992
0
                let ((k, v), _) = unsafe { shard.remove(bucket) };
993
0
                Some((k, v.into_inner()))
994
            } else {
995
0
                None
996
            }
997
        } else {
998
0
            None
999
        }
1000
0
    }
1001
1002
0
    fn _remove_if_mut<Q>(&self, key: &Q, f: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)>
1003
0
    where
1004
0
        K: Borrow<Q>,
1005
0
        Q: Hash + Eq + ?Sized,
1006
    {
1007
0
        let hash = self.hash_u64(&key);
1008
1009
0
        let idx = self.determine_shard(hash as usize);
1010
1011
0
        let mut shard = unsafe { self._yield_write_shard(idx) };
1012
1013
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1014
0
            let (k, v) = unsafe { bucket.as_mut() };
1015
0
            if f(k, v.get_mut()) {
1016
0
                let ((k, v), _) = unsafe { shard.remove(bucket) };
1017
0
                Some((k, v.into_inner()))
1018
            } else {
1019
0
                None
1020
            }
1021
        } else {
1022
0
            None
1023
        }
1024
0
    }
1025
1026
0
    fn _iter(&'a self) -> Iter<'a, K, V, S, DashMap<K, V, S>> {
1027
0
        Iter::new(self)
1028
0
    }
1029
1030
0
    fn _iter_mut(&'a self) -> IterMut<'a, K, V, S, DashMap<K, V, S>> {
1031
0
        IterMut::new(self)
1032
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_iter_mut
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_iter_mut
1033
1034
0
    fn _get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V>>
1035
0
    where
1036
0
        K: Borrow<Q>,
1037
0
        Q: Hash + Eq + ?Sized,
1038
    {
1039
0
        let hash = self.hash_u64(&key);
1040
1041
0
        let idx = self.determine_shard(hash as usize);
1042
1043
0
        let shard = unsafe { self._yield_read_shard(idx) };
1044
1045
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1046
            unsafe {
1047
0
                let (k, v) = bucket.as_ref();
1048
0
                Some(Ref::new(shard, k, v.as_ptr()))
1049
            }
1050
        } else {
1051
0
            None
1052
        }
1053
0
    }
1054
1055
0
    fn _get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V>>
1056
0
    where
1057
0
        K: Borrow<Q>,
1058
0
        Q: Hash + Eq + ?Sized,
1059
    {
1060
0
        let hash = self.hash_u64(&key);
1061
1062
0
        let idx = self.determine_shard(hash as usize);
1063
1064
0
        let shard = unsafe { self._yield_write_shard(idx) };
1065
1066
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1067
            unsafe {
1068
0
                let (k, v) = bucket.as_ref();
1069
0
                Some(RefMut::new(shard, k, v.as_ptr()))
1070
            }
1071
        } else {
1072
0
            None
1073
        }
1074
0
    }
1075
1076
0
    fn _try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V>>
1077
0
    where
1078
0
        K: Borrow<Q>,
1079
0
        Q: Hash + Eq + ?Sized,
1080
    {
1081
0
        let hash = self.hash_u64(&key);
1082
1083
0
        let idx = self.determine_shard(hash as usize);
1084
1085
0
        let shard = match unsafe { self._try_yield_read_shard(idx) } {
1086
0
            Some(shard) => shard,
1087
0
            None => return TryResult::Locked,
1088
        };
1089
1090
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1091
            unsafe {
1092
0
                let (k, v) = bucket.as_ref();
1093
0
                TryResult::Present(Ref::new(shard, k, v.as_ptr()))
1094
            }
1095
        } else {
1096
0
            TryResult::Absent
1097
        }
1098
0
    }
1099
1100
0
    fn _try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V>>
1101
0
    where
1102
0
        K: Borrow<Q>,
1103
0
        Q: Hash + Eq + ?Sized,
1104
    {
1105
0
        let hash = self.hash_u64(&key);
1106
1107
0
        let idx = self.determine_shard(hash as usize);
1108
1109
0
        let shard = match unsafe { self._try_yield_write_shard(idx) } {
1110
0
            Some(shard) => shard,
1111
0
            None => return TryResult::Locked,
1112
        };
1113
1114
0
        if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1115
            unsafe {
1116
0
                let (k, v) = bucket.as_ref();
1117
0
                TryResult::Present(RefMut::new(shard, k, v.as_ptr()))
1118
            }
1119
        } else {
1120
0
            TryResult::Absent
1121
        }
1122
0
    }
1123
1124
0
    fn _shrink_to_fit(&self) {
1125
0
        self.shards.iter().for_each(|s| {
1126
0
            let mut shard = s.write();
1127
0
            let size = shard.len();
1128
0
            shard.shrink_to(size, |(k, _v)| {
1129
0
                let mut hasher = self.hasher.build_hasher();
1130
0
                k.hash(&mut hasher);
1131
0
                hasher.finish()
1132
0
            })
1133
0
        });
1134
0
    }
1135
1136
0
    fn _retain(&self, mut f: impl FnMut(&K, &mut V) -> bool) {
1137
0
        self.shards.iter().for_each(|s| {
1138
            unsafe {
1139
0
                let mut shard = s.write();
1140
                // Here we only use `iter` as a temporary, preventing use-after-free
1141
0
                for bucket in shard.iter() {
1142
0
                    let (k, v) = bucket.as_mut();
1143
0
                    if !f(&*k, v.get_mut()) {
1144
0
                        shard.erase(bucket);
1145
0
                    }
1146
                }
1147
            }
1148
0
        });
1149
0
    }
1150
1151
0
    fn _len(&self) -> usize {
1152
0
        self.shards.iter().map(|s| s.read().len()).sum()
1153
0
    }
1154
1155
0
    fn _capacity(&self) -> usize {
1156
0
        self.shards.iter().map(|s| s.read().capacity()).sum()
1157
0
    }
1158
1159
0
    fn _alter<Q>(&self, key: &Q, f: impl FnOnce(&K, V) -> V)
1160
0
    where
1161
0
        K: Borrow<Q>,
1162
0
        Q: Hash + Eq + ?Sized,
1163
    {
1164
0
        if let Some(mut r) = self.get_mut(key) {
1165
0
            util::map_in_place_2(r.pair_mut(), f);
1166
0
        }
1167
0
    }
1168
1169
0
    fn _alter_all(&self, mut f: impl FnMut(&K, V) -> V) {
1170
0
        self.iter_mut()
1171
0
            .for_each(|mut m| util::map_in_place_2(m.pair_mut(), &mut f));
1172
0
    }
1173
1174
0
    fn _view<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
1175
0
    where
1176
0
        K: Borrow<Q>,
1177
0
        Q: Hash + Eq + ?Sized,
1178
    {
1179
0
        self.get(key).map(|r| {
1180
0
            let (k, v) = r.pair();
1181
0
            f(k, v)
1182
0
        })
1183
0
    }
1184
1185
0
    fn _entry(&'a self, key: K) -> Entry<'a, K, V> {
1186
0
        let hash = self.hash_u64(&key);
1187
1188
0
        let idx = self.determine_shard(hash as usize);
1189
1190
0
        let mut shard = unsafe { self._yield_write_shard(idx) };
1191
1192
0
        match shard.find_or_find_insert_slot(
1193
0
            hash,
1194
0
            |(k, _v)| k == &key,
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_entry::{closure#0}
1195
0
            |(k, _v)| {
1196
0
                let mut hasher = self.hasher.build_hasher();
1197
0
                k.hash(&mut hasher);
1198
0
                hasher.finish()
1199
0
            },
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry::{closure#1}
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_entry::{closure#1}
1200
        ) {
1201
0
            Ok(elem) => Entry::Occupied(unsafe { OccupiedEntry::new(shard, key, elem) }),
1202
0
            Err(slot) => Entry::Vacant(unsafe { VacantEntry::new(shard, key, hash, slot) }),
1203
        }
1204
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_entry
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_entry
1205
1206
0
    fn _try_entry(&'a self, key: K) -> Option<Entry<'a, K, V>> {
1207
0
        let hash = self.hash_u64(&key);
1208
1209
0
        let idx = self.determine_shard(hash as usize);
1210
1211
0
        let mut shard = match unsafe { self._try_yield_write_shard(idx) } {
1212
0
            Some(shard) => shard,
1213
0
            None => return None,
1214
        };
1215
1216
0
        match shard.find_or_find_insert_slot(
1217
0
            hash,
1218
0
            |(k, _v)| k == &key,
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_try_entry::{closure#0}
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_try_entry::{closure#0}
1219
0
            |(k, _v)| {
1220
0
                let mut hasher = self.hasher.build_hasher();
1221
0
                k.hash(&mut hasher);
1222
0
                hasher.finish()
1223
0
            },
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_try_entry::{closure#1}
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_try_entry::{closure#1}
1224
        ) {
1225
0
            Ok(elem) => Some(Entry::Occupied(unsafe {
1226
0
                OccupiedEntry::new(shard, key, elem)
1227
0
            })),
1228
0
            Err(slot) => Some(Entry::Vacant(unsafe {
1229
0
                VacantEntry::new(shard, key, hash, slot)
1230
0
            })),
1231
        }
1232
0
    }
Unexecuted instantiation: <dashmap::DashMap<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>> as dashmap::t::Map<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>, std::hash::random::RandomState>>::_try_entry
Unexecuted instantiation: <dashmap::DashMap<_, _, _> as dashmap::t::Map<_, _, _>>::_try_entry
1233
1234
0
    fn _hasher(&self) -> S {
1235
0
        self.hasher.clone()
1236
0
    }
1237
}
1238
1239
impl<K: Eq + Hash + fmt::Debug, V: fmt::Debug, S: BuildHasher + Clone> fmt::Debug
1240
    for DashMap<K, V, S>
1241
{
1242
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1243
0
        let mut pmap = f.debug_map();
1244
1245
0
        for r in self {
1246
0
            let (k, v) = r.pair();
1247
0
1248
0
            pmap.entry(k, v);
1249
0
        }
1250
1251
0
        pmap.finish()
1252
0
    }
1253
}
1254
1255
impl<'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
0
    fn shl(self, pair: (K, V)) -> Self::Output {
1259
0
        self.insert(pair.0, pair.1)
1260
0
    }
1261
}
1262
1263
impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> Shr<&Q> for &'a DashMap<K, V, S>
1264
where
1265
    K: Borrow<Q>,
1266
    Q: Hash + Eq + ?Sized,
1267
{
1268
    type Output = Ref<'a, K, V>;
1269
1270
0
    fn shr(self, key: &Q) -> Self::Output {
1271
0
        self.get(key).unwrap()
1272
0
    }
1273
}
1274
1275
impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> BitOr<&Q> for &'a DashMap<K, V, S>
1276
where
1277
    K: Borrow<Q>,
1278
    Q: Hash + Eq + ?Sized,
1279
{
1280
    type Output = RefMut<'a, K, V>;
1281
1282
0
    fn bitor(self, key: &Q) -> Self::Output {
1283
0
        self.get_mut(key).unwrap()
1284
0
    }
1285
}
1286
1287
impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> Sub<&Q> for &'a DashMap<K, V, S>
1288
where
1289
    K: Borrow<Q>,
1290
    Q: Hash + Eq + ?Sized,
1291
{
1292
    type Output = Option<(K, V)>;
1293
1294
0
    fn sub(self, key: &Q) -> Self::Output {
1295
0
        self.remove(key)
1296
0
    }
1297
}
1298
1299
impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone, Q> BitAnd<&Q> for &'a DashMap<K, V, S>
1300
where
1301
    K: Borrow<Q>,
1302
    Q: Hash + Eq + ?Sized,
1303
{
1304
    type Output = bool;
1305
1306
0
    fn bitand(self, key: &Q) -> Self::Output {
1307
0
        self.contains_key(key)
1308
0
    }
1309
}
1310
1311
impl<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
0
    fn into_iter(self) -> Self::IntoIter {
1317
0
        OwningIter::new(self)
1318
0
    }
1319
}
1320
1321
impl<'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
0
    fn into_iter(self) -> Self::IntoIter {
1327
0
        self.iter()
1328
0
    }
1329
}
1330
1331
impl<K: Eq + Hash, V, S: BuildHasher + Clone> Extend<(K, V)> for DashMap<K, V, S> {
1332
0
    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, intoiter: I) {
1333
0
        for pair in intoiter.into_iter() {
1334
0
            self.insert(pair.0, pair.1);
1335
0
        }
1336
0
    }
1337
}
1338
1339
impl<K: Eq + Hash, V, S: BuildHasher + Clone + Default> FromIterator<(K, V)> for DashMap<K, V, S> {
1340
0
    fn from_iter<I: IntoIterator<Item = (K, V)>>(intoiter: I) -> Self {
1341
0
        let mut map = DashMap::default();
1342
1343
0
        map.extend(intoiter);
1344
1345
0
        map
1346
0
    }
1347
}
1348
1349
#[cfg(feature = "typesize")]
1350
impl<K, V, S> typesize::TypeSize for DashMap<K, V, S>
1351
where
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)]
1389
mod 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
}