diff --git a/Cargo.lock b/Cargo.lock index a3e6ece4..8f0591a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,9 +92,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "hermit-abi" diff --git a/Cargo.toml b/Cargo.toml index 2ec648eb..c2d3edfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ inline = ["hashbrown/inline-more"] [dependencies] lock_api = "0.4.10" parking_lot_core = "0.9.8" -hashbrown = { version = "0.14.0", default-features = false } +hashbrown = { version = "0.14.0", default-features = false, features = ["raw"] } serde = { version = "1.0.188", optional = true, features = ["derive"] } cfg-if = "1.0.0" rayon = { version = "1.7.0", optional = true } diff --git a/src/iter.rs b/src/iter.rs index ce50e739..d069441e 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,13 +1,12 @@ use super::mapref::multiple::{RefMulti, RefMutMulti}; -use super::util; use crate::lock::{RwLockReadGuard, RwLockWriteGuard}; use crate::t::Map; use crate::util::SharedValue; use crate::{DashMap, HashMap}; use core::hash::{BuildHasher, Hash}; use core::mem; -use hashbrown::hash_map; use std::collections::hash_map::RandomState; +use std::marker::PhantomData; use std::sync::Arc; /// Iterator over a DashMap yielding key value pairs. @@ -39,7 +38,7 @@ impl OwningIter { } } -type GuardOwningIter = hash_map::IntoIter>; +type GuardOwningIter = hashbrown::raw::RawIntoIter<(K, SharedValue)>; impl Iterator for OwningIter { type Item = (K, V); @@ -59,9 +58,7 @@ impl Iterator for OwningIter { //let guard = unsafe { self.map._yield_read_shard(self.shard_i) }; let mut shard_wl = unsafe { self.map._yield_write_shard(self.shard_i) }; - let hasher = self.map._hasher(); - - let map = mem::replace(&mut *shard_wl, HashMap::with_hasher(hasher)); + let map = mem::take(&mut *shard_wl); drop(shard_wl); @@ -91,14 +88,14 @@ where { } -type GuardIter<'a, K, V, S> = ( - Arc>>, - hash_map::Iter<'a, K, SharedValue>, +type GuardIter<'a, K, V> = ( + Arc>>, + hashbrown::raw::RawIter<(K, SharedValue)>, ); -type GuardIterMut<'a, K, V, S> = ( - Arc>>, - hash_map::IterMut<'a, K, SharedValue>, +type GuardIterMut<'a, K, V> = ( + Arc>>, + hashbrown::raw::RawIter<(K, SharedValue)>, ); /// Iterator over a DashMap yielding immutable references. @@ -115,7 +112,8 @@ type GuardIterMut<'a, K, V, S> = ( pub struct Iter<'a, K, V, S = RandomState, M = DashMap> { map: &'a M, shard_i: usize, - current: Option>, + current: Option>, + marker: PhantomData, } impl<'i, K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for Iter<'i, K, V, S> { @@ -148,6 +146,7 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter map, shard_i: 0, current: None, + marker: PhantomData, } } } @@ -155,15 +154,17 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iterator for Iter<'a, K, V, S, M> { - type Item = RefMulti<'a, K, V, S>; + type Item = RefMulti<'a, K, V>; fn next(&mut self) -> Option { loop { if let Some(current) = self.current.as_mut() { - if let Some((k, v)) = current.1.next() { - let guard = current.0.clone(); - - return unsafe { Some(RefMulti::new(guard, k, v.get())) }; + if let Some(b) = current.1.next() { + return unsafe { + let (k, v) = b.as_ref(); + let guard = current.0.clone(); + Some(RefMulti::new(guard, k, v.get())) + }; } } @@ -173,9 +174,7 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter let guard = unsafe { self.map._yield_read_shard(self.shard_i) }; - let sref: &HashMap = unsafe { util::change_lifetime_const(&*guard) }; - - let iter = sref.iter(); + let iter = unsafe { guard.iter() }; self.current = Some((Arc::new(guard), iter)); @@ -199,7 +198,8 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter pub struct IterMut<'a, K, V, S = RandomState, M = DashMap> { map: &'a M, shard_i: usize, - current: Option>, + current: Option>, + marker: PhantomData, } unsafe impl<'a, 'i, K, V, S, M> Send for IterMut<'i, K, V, S, M> @@ -228,6 +228,7 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> map, shard_i: 0, current: None, + marker: PhantomData, } } } @@ -235,21 +236,17 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iterator for IterMut<'a, K, V, S, M> { - type Item = RefMutMulti<'a, K, V, S>; + type Item = RefMutMulti<'a, K, V>; fn next(&mut self) -> Option { loop { if let Some(current) = self.current.as_mut() { - if let Some((k, v)) = current.1.next() { - let guard = current.0.clone(); - - unsafe { - let k = util::change_lifetime_const(k); - - let v = &mut *v.as_ptr(); - - return Some(RefMutMulti::new(guard, k, v)); - } + if let Some(b) = current.1.next() { + return unsafe { + let (k, v) = b.as_mut(); + let guard = current.0.clone(); + Some(RefMutMulti::new(guard, k, v.get_mut())) + }; } } @@ -257,11 +254,9 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter return None; } - let mut guard = unsafe { self.map._yield_write_shard(self.shard_i) }; - - let sref: &mut HashMap = unsafe { util::change_lifetime_mut(&mut *guard) }; + let guard = unsafe { self.map._yield_write_shard(self.shard_i) }; - let iter = sref.iter_mut(); + let iter = unsafe { guard.iter() }; self.current = Some((Arc::new(guard), iter)); @@ -285,7 +280,7 @@ mod tests { let mut c = 0; for shard in map.shards() { - c += shard.write().iter_mut().count(); + c += unsafe { shard.write().iter().count() }; } assert_eq!(c, 1); diff --git a/src/iter_set.rs b/src/iter_set.rs index 619a5b50..98b930c3 100644 --- a/src/iter_set.rs +++ b/src/iter_set.rs @@ -63,7 +63,7 @@ impl<'a, K: Eq + Hash, S: 'a + BuildHasher + Clone, M: Map<'a, K, (), S>> Iter<' impl<'a, K: Eq + Hash, S: 'a + BuildHasher + Clone, M: Map<'a, K, (), S>> Iterator for Iter<'a, K, S, M> { - type Item = RefMulti<'a, K, S>; + type Item = RefMulti<'a, K>; fn next(&mut self) -> Option { self.inner.next().map(RefMulti::new) diff --git a/src/lib.rs b/src/lib.rs index 85e48681..ef2e6b56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,7 +54,7 @@ cfg_if! { } } -pub(crate) type HashMap = hashbrown::HashMap, S>; +pub(crate) type HashMap = hashbrown::raw::RawTable<(K, SharedValue)>; // Temporary reimplementation of [`std::collections::TryReserveError`] // util [`std::collections::TryReserveError`] stabilises. @@ -80,7 +80,7 @@ fn ncb(shard_amount: usize) -> usize { /// DashMap tries to implement an easy to use API similar to `std::collections::HashMap` /// with some slight changes to handle concurrency. /// -/// DashMap tries to be very simple to use and to be a direct replacement for `RwLock>`. +/// DashMap tries to be very simple to use and to be a direct replacement for `RwLock>`. /// To accomplish this, all methods take `&self` instead of modifying methods taking `&mut self`. /// This allows you to put a DashMap in an `Arc` and share it between threads while being able to modify it. /// @@ -88,7 +88,7 @@ fn ncb(shard_amount: usize) -> usize { /// This means that it is safe to ignore it across multiple threads. pub struct DashMap { shift: usize, - shards: Box<[CachePadded>>]>, + shards: Box<[CachePadded>>]>, hasher: S, } @@ -283,12 +283,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { let cps = capacity / shard_amount; let shards = (0..shard_amount) - .map(|_| { - CachePadded::new(RwLock::new(HashMap::with_capacity_and_hasher( - cps, - hasher.clone(), - ))) - }) + .map(|_| CachePadded::new(RwLock::new(HashMap::with_capacity(cps)))) .collect(); Self { @@ -301,11 +296,15 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// Hash a given item to produce a usize. /// Uses the provided or default HashBuilder. pub fn hash_usize(&self, item: &T) -> usize { + self.hash_u64(item) as usize + } + + fn hash_u64(&self, item: &T) -> u64 { let mut hasher = self.hasher.build_hasher(); item.hash(&mut hasher); - hasher.finish() as usize + hasher.finish() } cfg_if! { @@ -323,7 +322,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// let map = DashMap::<(), ()>::new(); /// println!("Amount of shards: {}", map.shards().len()); /// ``` - pub fn shards(&self) -> &[CachePadded>>] { + pub fn shards(&self) -> &[CachePadded>>] { &self.shards } @@ -337,13 +336,22 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// ``` /// use dashmap::DashMap; /// use dashmap::SharedValue; + /// use std::hash::{Hash, Hasher, BuildHasher}; /// /// let mut map = DashMap::::new(); /// let shard_ind = map.determine_map(&42); - /// map.shards_mut()[shard_ind].get_mut().insert(42, SharedValue::new("forty two")); + /// let mut factory = map.hasher().clone(); + /// let hasher = |tuple: &(i32, SharedValue<&'static str>)| { + /// let mut hasher = factory.build_hasher(); + /// tuple.0.hash(&mut hasher); + /// hasher.finish() + /// }; + /// let data = (42, SharedValue::new("forty two")); + /// let hash = hasher(&data); + /// map.shards_mut()[shard_ind].get_mut().insert(hash, data, hasher); /// assert_eq!(*map.get(&42).unwrap(), "forty two"); /// ``` - pub fn shards_mut(&mut self) -> &mut [CachePadded>>] { + pub fn shards_mut(&mut self) -> &mut [CachePadded>>] { &mut self.shards } @@ -353,22 +361,22 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// Requires the `raw-api` feature to be enabled. /// /// See [`DashMap::shards()`] and [`DashMap::shards_mut()`] for more information. - pub fn into_shards(self) -> Box<[CachePadded>>]> { + pub fn into_shards(self) -> Box<[CachePadded>>]> { self.shards } } else { #[allow(dead_code)] - pub(crate) fn shards(&self) -> &[CachePadded>>] { + pub(crate) fn shards(&self) -> &[CachePadded>>] { &self.shards } #[allow(dead_code)] - pub(crate) fn shards_mut(&mut self) -> &mut [CachePadded>>] { + pub(crate) fn shards_mut(&mut self) -> &mut [CachePadded>>] { &mut self.shards } #[allow(dead_code)] - pub(crate) fn into_shards(self) -> Box<[CachePadded>>]> { + pub(crate) fn into_shards(self) -> Box<[CachePadded>>]> { self.shards } } @@ -571,7 +579,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// youtubers.insert("Bosnian Bill", 457000); /// assert_eq!(*youtubers.get("Bosnian Bill").unwrap(), 457000); /// ``` - pub fn get(&'a self, key: &Q) -> Option> + pub fn get(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized, @@ -593,7 +601,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// *class.get_mut("Albin").unwrap() -= 1; /// assert_eq!(*class.get("Albin").unwrap(), 14); /// ``` - pub fn get_mut(&'a self, key: &Q) -> Option> + pub fn get_mut(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized, @@ -620,7 +628,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// let result2 = map.try_get("Johnny"); /// assert!(result2.is_locked()); /// ``` - pub fn try_get(&'a self, key: &Q) -> TryResult> + pub fn try_get(&'a self, key: &Q) -> TryResult> where K: Borrow, Q: Hash + Eq + ?Sized, @@ -648,7 +656,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// let result2 = map.try_get_mut("Johnny"); /// assert!(result2.is_locked()); /// ``` - pub fn try_get_mut(&'a self, key: &Q) -> TryResult> + pub fn try_get_mut(&'a self, key: &Q) -> TryResult> where K: Borrow, Q: Hash + Eq + ?Sized, @@ -847,7 +855,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// See the documentation on `dashmap::mapref::entry` for more details. /// /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map. - pub fn entry(&'a self, key: K) -> Entry<'a, K, V, S> { + pub fn entry(&'a self, key: K) -> Entry<'a, K, V> { self._entry(key) } @@ -855,7 +863,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { /// See the documentation on `dashmap::mapref::entry` for more details. /// /// Returns None if the shard is currently locked. - pub fn try_entry(&'a self, key: K) -> Option> { + pub fn try_entry(&'a self, key: K) -> Option> { self._try_entry(key) } @@ -871,7 +879,11 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap { for shard in self.shards.iter() { shard .write() - .try_reserve(additional) + .try_reserve(additional, |(k, _v)| { + let mut hasher = self.hasher.build_hasher(); + k.hash(&mut hasher); + hasher.finish() + }) .map_err(|_| TryReserveError {})?; } Ok(()) @@ -885,19 +897,19 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> self.shards.len() } - unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap { + unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap { debug_assert!(i < self.shards.len()); &*self.shards.get_unchecked(i).data_ptr() } - unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap> { + unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap> { debug_assert!(i < self.shards.len()); self.shards.get_unchecked(i).read() } - unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap> { + unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap> { debug_assert!(i < self.shards.len()); self.shards.get_unchecked(i).write() @@ -906,7 +918,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> unsafe fn _try_yield_read_shard( &'a self, i: usize, - ) -> Option>> { + ) -> Option>> { debug_assert!(i < self.shards.len()); self.shards.get_unchecked(i).try_read() @@ -915,22 +927,20 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> unsafe fn _try_yield_write_shard( &'a self, i: usize, - ) -> Option>> { + ) -> Option>> { debug_assert!(i < self.shards.len()); self.shards.get_unchecked(i).try_write() } fn _insert(&self, key: K, value: V) -> Option { - let hash = self.hash_usize(&key); - - let idx = self.determine_shard(hash); - - let mut shard = unsafe { self._yield_write_shard(idx) }; - - shard - .insert(key, SharedValue::new(value)) - .map(|v| v.into_inner()) + match self.entry(key) { + Entry::Occupied(mut o) => Some(o.insert(value)), + Entry::Vacant(v) => { + v.insert(value); + None + } + } } fn _remove(&self, key: &Q) -> Option<(K, V)> @@ -938,13 +948,18 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; - shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { + let ((k, v), _) = unsafe { shard.remove(bucket) }; + Some((k, v.into_inner())) + } else { + None + } } fn _remove_if(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)> @@ -952,22 +967,19 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { - unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - - if f(&*kptr, &mut *vptr) { - shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) - } else { - None - } + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { + let (k, v) = unsafe { bucket.as_ref() }; + if f(k, v.get()) { + let ((k, v), _) = unsafe { shard.remove(bucket) }; + Some((k, v.into_inner())) + } else { + None } } else { None @@ -979,22 +991,19 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let mut shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { - unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - - if f(&*kptr, &mut *vptr) { - shard.remove_entry(key).map(|(k, v)| (k, v.into_inner())) - } else { - None - } + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { + let (k, v) = unsafe { bucket.as_mut() }; + if f(k, v.get_mut()) { + let ((k, v), _) = unsafe { shard.remove(bucket) }; + Some((k, v.into_inner())) + } else { + None } } else { None @@ -1009,94 +1018,90 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> IterMut::new(self) } - fn _get(&'a self, key: &Q) -> Option> + fn _get(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = unsafe { self._yield_read_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { unsafe { - let kptr: *const K = kptr; - let vptr: *const V = vptr.get(); - Some(Ref::new(shard, kptr, vptr)) + let (k, v) = bucket.as_ref(); + Some(Ref::new(shard, k, v.as_ptr())) } } else { None } } - fn _get_mut(&'a self, key: &Q) -> Option> + fn _get_mut(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - Some(RefMut::new(shard, kptr, vptr)) + let (k, v) = bucket.as_ref(); + Some(RefMut::new(shard, k, v.as_ptr())) } } else { None } } - fn _try_get(&'a self, key: &Q) -> TryResult> + fn _try_get(&'a self, key: &Q) -> TryResult> where K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = match unsafe { self._try_yield_read_shard(idx) } { Some(shard) => shard, None => return TryResult::Locked, }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { unsafe { - let kptr: *const K = kptr; - let vptr: *const V = vptr.get(); - TryResult::Present(Ref::new(shard, kptr, vptr)) + let (k, v) = bucket.as_ref(); + TryResult::Present(Ref::new(shard, k, v.as_ptr())) } } else { TryResult::Absent } } - fn _try_get_mut(&'a self, key: &Q) -> TryResult> + fn _try_get_mut(&'a self, key: &Q) -> TryResult> where K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.hash_usize(&key); + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); let shard = match unsafe { self._try_yield_write_shard(idx) } { Some(shard) => shard, None => return TryResult::Locked, }; - if let Some((kptr, vptr)) = shard.get_key_value(key) { + if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) { unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - TryResult::Present(RefMut::new(shard, kptr, vptr)) + let (k, v) = bucket.as_ref(); + TryResult::Present(RefMut::new(shard, k, v.as_ptr())) } } else { TryResult::Absent @@ -1104,13 +1109,28 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _shrink_to_fit(&self) { - self.shards.iter().for_each(|s| s.write().shrink_to_fit()); + self.shards.iter().for_each(|s| { + s.write().shrink_to(self.len(), |(k, _v)| { + let mut hasher = self.hasher.build_hasher(); + k.hash(&mut hasher); + hasher.finish() + }) + }); } fn _retain(&self, mut f: impl FnMut(&K, &mut V) -> bool) { - self.shards - .iter() - .for_each(|s| s.write().retain(|k, v| f(k, v.get_mut()))); + self.shards.iter().for_each(|s| { + unsafe { + let mut shard = s.write(); + // Here we only use `iter` as a temporary, preventing use-after-free + for bucket in shard.iter() { + let (k, v) = bucket.as_mut(); + if !f(&*k, v.get_mut()) { + shard.erase(bucket); + } + } + } + }); } fn _len(&self) -> usize { @@ -1132,11 +1152,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> } fn _alter_all(&self, mut f: impl FnMut(&K, V) -> V) { - self.shards.iter().for_each(|s| { - s.write() - .iter_mut() - .for_each(|(k, v)| util::map_in_place_2((k, v.get_mut()), &mut f)); - }); + self.iter_mut() + .for_each(|mut m| util::map_in_place_2(m.pair_mut(), &mut f)); } fn _view(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option @@ -1150,47 +1167,52 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S> }) } - fn _entry(&'a self, key: K) -> Entry<'a, K, V, S> { - let hash = self.hash_usize(&key); + fn _entry(&'a self, key: K) -> Entry<'a, K, V> { + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); - let shard = unsafe { self._yield_write_shard(idx) }; + let mut shard = unsafe { self._yield_write_shard(idx) }; - if let Some((kptr, vptr)) = shard.get_key_value(&key) { - unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - Entry::Occupied(OccupiedEntry::new(shard, key, (kptr, vptr))) - } - } else { - unsafe { Entry::Vacant(VacantEntry::new(shard, key)) } + match shard.find_or_find_insert_slot( + hash, + |(k, _v)| k == &key, + |(k, _v)| { + let mut hasher = self.hasher.build_hasher(); + k.hash(&mut hasher); + hasher.finish() + }, + ) { + Ok(elem) => Entry::Occupied(unsafe { OccupiedEntry::new(shard, key, elem) }), + Err(slot) => Entry::Vacant(unsafe { VacantEntry::new(shard, key, hash, slot) }), } } - fn _try_entry(&'a self, key: K) -> Option> { - let hash = self.hash_usize(&key); + fn _try_entry(&'a self, key: K) -> Option> { + let hash = self.hash_u64(&key); - let idx = self.determine_shard(hash); + let idx = self.determine_shard(hash as usize); - let shard = match unsafe { self._try_yield_write_shard(idx) } { + let mut shard = match unsafe { self._try_yield_write_shard(idx) } { Some(shard) => shard, None => return None, }; - if let Some((kptr, vptr)) = shard.get_key_value(&key) { - unsafe { - let kptr: *const K = kptr; - let vptr: *mut V = vptr.as_ptr(); - - Some(Entry::Occupied(OccupiedEntry::new( - shard, - key, - (kptr, vptr), - ))) - } - } else { - unsafe { Some(Entry::Vacant(VacantEntry::new(shard, key))) } + match shard.find_or_find_insert_slot( + hash, + |(k, _v)| k == &key, + |(k, _v)| { + let mut hasher = self.hasher.build_hasher(); + k.hash(&mut hasher); + hasher.finish() + }, + ) { + Ok(elem) => Some(Entry::Occupied(unsafe { + OccupiedEntry::new(shard, key, elem) + })), + Err(slot) => Some(Entry::Vacant(unsafe { + VacantEntry::new(shard, key, hash, slot) + })), } } @@ -1228,7 +1250,7 @@ where K: Borrow, Q: Hash + Eq + ?Sized, { - type Output = Ref<'a, K, V, S>; + type Output = Ref<'a, K, V>; fn shr(self, key: &Q) -> Self::Output { self.get(key).unwrap() @@ -1240,7 +1262,7 @@ where K: Borrow, Q: Hash + Eq + ?Sized, { - type Output = RefMut<'a, K, V, S>; + type Output = RefMut<'a, K, V>; fn bitor(self, key: &Q) -> Self::Output { self.get_mut(key).unwrap() @@ -1282,7 +1304,7 @@ impl IntoIterator for DashMap } impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for &'a DashMap { - type Item = RefMulti<'a, K, V, S>; + type Item = RefMulti<'a, K, V>; type IntoIter = Iter<'a, K, V, S, DashMap>; diff --git a/src/mapref/entry.rs b/src/mapref/entry.rs index e9e6b913..f4cc6819 100644 --- a/src/mapref/entry.rs +++ b/src/mapref/entry.rs @@ -1,19 +1,16 @@ use super::one::RefMut; use crate::lock::RwLockWriteGuard; -use crate::util; use crate::util::SharedValue; use crate::HashMap; -use core::hash::{BuildHasher, Hash}; +use core::hash::Hash; use core::mem; -use core::ptr; -use std::collections::hash_map::RandomState; -pub enum Entry<'a, K, V, S = RandomState> { - Occupied(OccupiedEntry<'a, K, V, S>), - Vacant(VacantEntry<'a, K, V, S>), +pub enum Entry<'a, K, V> { + Occupied(OccupiedEntry<'a, K, V>), + Vacant(VacantEntry<'a, K, V>), } -impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> Entry<'a, K, V> { /// Apply a function to the stored value if it exists. pub fn and_modify(self, f: impl FnOnce(&mut V)) -> Self { match self { @@ -45,7 +42,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { /// Return a mutable reference to the element if it exists, /// otherwise insert the default and return a mutable reference to that. - pub fn or_default(self) -> RefMut<'a, K, V, S> + pub fn or_default(self) -> RefMut<'a, K, V> where V: Default, { @@ -57,7 +54,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { /// Return a mutable reference to the element if it exists, /// otherwise a provided value and return a mutable reference to that. - pub fn or_insert(self, value: V) -> RefMut<'a, K, V, S> { + pub fn or_insert(self, value: V) -> RefMut<'a, K, V> { match self { Entry::Occupied(entry) => entry.into_ref(), Entry::Vacant(entry) => entry.insert(value), @@ -66,7 +63,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { /// Return a mutable reference to the element if it exists, /// otherwise insert the result of a provided function and return a mutable reference to that. - pub fn or_insert_with(self, value: impl FnOnce() -> V) -> RefMut<'a, K, V, S> { + pub fn or_insert_with(self, value: impl FnOnce() -> V) -> RefMut<'a, K, V> { match self { Entry::Occupied(entry) => entry.into_ref(), Entry::Vacant(entry) => entry.insert(value()), @@ -76,7 +73,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { pub fn or_try_insert_with( self, value: impl FnOnce() -> Result, - ) -> Result, E> { + ) -> Result, E> { match self { Entry::Occupied(entry) => Ok(entry.into_ref()), Entry::Vacant(entry) => Ok(entry.insert(value()?)), @@ -84,7 +81,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { } /// Sets the value of the entry, and returns a reference to the inserted value. - pub fn insert(self, value: V) -> RefMut<'a, K, V, S> { + pub fn insert(self, value: V) -> RefMut<'a, K, V> { match self { Entry::Occupied(mut entry) => { entry.insert(value); @@ -100,7 +97,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { /// consider [`insert`] as it doesn't need to clone the key. /// /// [`insert`]: Entry::insert - pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S> + pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> where K: Clone, { @@ -114,52 +111,58 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> { } } -pub struct VacantEntry<'a, K, V, S = RandomState> { - shard: RwLockWriteGuard<'a, HashMap>, +pub struct VacantEntry<'a, K, V> { + shard: RwLockWriteGuard<'a, HashMap>, key: K, + hash: u64, + slot: hashbrown::raw::InsertSlot, } -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Send for VacantEntry<'a, K, V, S> {} -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Sync for VacantEntry<'a, K, V, S> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for VacantEntry<'a, K, V> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for VacantEntry<'a, K, V> {} -impl<'a, K: Eq + Hash, V, S: BuildHasher> VacantEntry<'a, K, V, S> { - pub(crate) unsafe fn new(shard: RwLockWriteGuard<'a, HashMap>, key: K) -> Self { - Self { shard, key } +impl<'a, K: Eq + Hash, V> VacantEntry<'a, K, V> { + pub(crate) unsafe fn new( + shard: RwLockWriteGuard<'a, HashMap>, + key: K, + hash: u64, + slot: hashbrown::raw::InsertSlot, + ) -> Self { + Self { + shard, + key, + hash, + slot, + } } - pub fn insert(mut self, value: V) -> RefMut<'a, K, V, S> { + pub fn insert(mut self, value: V) -> RefMut<'a, K, V> { unsafe { - let c: K = ptr::read(&self.key); - - self.shard.insert(self.key, SharedValue::new(value)); - - let (k, v) = self.shard.get_key_value(&c).unwrap(); + let occupied = self.shard.insert_in_slot( + self.hash, + self.slot, + (self.key, SharedValue::new(value)), + ); - let k = util::change_lifetime_const(k); + let (k, v) = occupied.as_ref(); - let v = &mut *v.as_ptr(); - - let r = RefMut::new(self.shard, k, v); - - mem::forget(c); - - r + RefMut::new(self.shard, k, v.as_ptr()) } } /// Sets the value of the entry with the VacantEntry’s key, and returns an OccupiedEntry. - pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V, S> + pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V> where K: Clone, { unsafe { - self.shard.insert(self.key.clone(), SharedValue::new(value)); + let bucket = self.shard.insert_in_slot( + self.hash, + self.slot, + (self.key.clone(), SharedValue::new(value)), + ); - let (k, v) = self.shard.get_key_value(&self.key).unwrap(); - - let kptr: *const K = k; - let vptr: *mut V = v.as_ptr(); - OccupiedEntry::new(self.shard, self.key, (kptr, vptr)) + OccupiedEntry::new(self.shard, self.key, bucket) } } @@ -172,38 +175,41 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> VacantEntry<'a, K, V, S> { } } -pub struct OccupiedEntry<'a, K, V, S = RandomState> { - shard: RwLockWriteGuard<'a, HashMap>, - elem: (*const K, *mut V), +pub struct OccupiedEntry<'a, K, V> { + shard: RwLockWriteGuard<'a, HashMap>, + bucket: hashbrown::raw::Bucket<(K, SharedValue)>, key: K, } -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Send for OccupiedEntry<'a, K, V, S> {} -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Sync for OccupiedEntry<'a, K, V, S> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for OccupiedEntry<'a, K, V> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for OccupiedEntry<'a, K, V> {} -impl<'a, K: Eq + Hash, V, S: BuildHasher> OccupiedEntry<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> OccupiedEntry<'a, K, V> { pub(crate) unsafe fn new( - shard: RwLockWriteGuard<'a, HashMap>, + shard: RwLockWriteGuard<'a, HashMap>, key: K, - elem: (*const K, *mut V), + bucket: hashbrown::raw::Bucket<(K, SharedValue)>, ) -> Self { - Self { shard, elem, key } + Self { shard, bucket, key } } pub fn get(&self) -> &V { - unsafe { &*self.elem.1 } + unsafe { self.bucket.as_ref().1.get() } } pub fn get_mut(&mut self) -> &mut V { - unsafe { &mut *self.elem.1 } + unsafe { self.bucket.as_mut().1.get_mut() } } pub fn insert(&mut self, value: V) -> V { mem::replace(self.get_mut(), value) } - pub fn into_ref(self) -> RefMut<'a, K, V, S> { - unsafe { RefMut::new(self.shard, self.elem.0, self.elem.1) } + pub fn into_ref(self) -> RefMut<'a, K, V> { + unsafe { + let (k, v) = self.bucket.as_ref(); + RefMut::new(self.shard, k, v.as_ptr()) + } } pub fn into_key(self) -> K { @@ -211,25 +217,24 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> OccupiedEntry<'a, K, V, S> { } pub fn key(&self) -> &K { - unsafe { &*self.elem.0 } + unsafe { &self.bucket.as_ref().0 } } pub fn remove(mut self) -> V { - let key = unsafe { &*self.elem.0 }; - self.shard.remove(key).unwrap().into_inner() + let ((_k, v), _) = unsafe { self.shard.remove(self.bucket) }; + v.into_inner() } pub fn remove_entry(mut self) -> (K, V) { - let key = unsafe { &*self.elem.0 }; - let (k, v) = self.shard.remove_entry(key).unwrap(); + let ((k, v), _) = unsafe { self.shard.remove(self.bucket) }; (k, v.into_inner()) } - pub fn replace_entry(mut self, value: V) -> (K, V) { - let nk = self.key; - let key = unsafe { &*self.elem.0 }; - let (k, v) = self.shard.remove_entry(key).unwrap(); - self.shard.insert(nk, SharedValue::new(value)); + pub fn replace_entry(self, value: V) -> (K, V) { + let (k, v) = mem::replace( + unsafe { self.bucket.as_mut() }, + (self.key, SharedValue::new(value)), + ); (k, v.into_inner()) } } diff --git a/src/mapref/multiple.rs b/src/mapref/multiple.rs index 53a8a7e5..1a721b0d 100644 --- a/src/mapref/multiple.rs +++ b/src/mapref/multiple.rs @@ -1,23 +1,21 @@ use crate::lock::{RwLockReadGuard, RwLockWriteGuard}; use crate::HashMap; -use core::hash::BuildHasher; use core::hash::Hash; use core::ops::{Deref, DerefMut}; -use std::collections::hash_map::RandomState; use std::sync::Arc; -pub struct RefMulti<'a, K, V, S = RandomState> { - _guard: Arc>>, +pub struct RefMulti<'a, K, V> { + _guard: Arc>>, k: *const K, v: *const V, } -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Send for RefMulti<'a, K, V, S> {} -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Sync for RefMulti<'a, K, V, S> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for RefMulti<'a, K, V> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for RefMulti<'a, K, V> {} -impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMulti<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> RefMulti<'a, K, V> { pub(crate) unsafe fn new( - guard: Arc>>, + guard: Arc>>, k: *const K, v: *const V, ) -> Self { @@ -41,7 +39,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMulti<'a, K, V, S> { } } -impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for RefMulti<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> Deref for RefMulti<'a, K, V> { type Target = V; fn deref(&self) -> &V { @@ -49,18 +47,18 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for RefMulti<'a, K, V, S> { } } -pub struct RefMutMulti<'a, K, V, S = RandomState> { - _guard: Arc>>, +pub struct RefMutMulti<'a, K, V> { + _guard: Arc>>, k: *const K, v: *mut V, } -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Send for RefMutMulti<'a, K, V, S> {} -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Sync for RefMutMulti<'a, K, V, S> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for RefMutMulti<'a, K, V> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for RefMutMulti<'a, K, V> {} -impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMutMulti<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> RefMutMulti<'a, K, V> { pub(crate) unsafe fn new( - guard: Arc>>, + guard: Arc>>, k: *const K, v: *mut V, ) -> Self { @@ -92,7 +90,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMutMulti<'a, K, V, S> { } } -impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for RefMutMulti<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> Deref for RefMutMulti<'a, K, V> { type Target = V; fn deref(&self) -> &V { @@ -100,7 +98,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for RefMutMulti<'a, K, V, S> { } } -impl<'a, K: Eq + Hash, V, S: BuildHasher> DerefMut for RefMutMulti<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> DerefMut for RefMutMulti<'a, K, V> { fn deref_mut(&mut self) -> &mut V { self.value_mut() } diff --git a/src/mapref/one.rs b/src/mapref/one.rs index fd385309..01393632 100644 --- a/src/mapref/one.rs +++ b/src/mapref/one.rs @@ -1,22 +1,21 @@ use crate::lock::{RwLockReadGuard, RwLockWriteGuard}; use crate::HashMap; -use core::hash::{BuildHasher, Hash}; +use core::hash::Hash; use core::ops::{Deref, DerefMut}; -use std::collections::hash_map::RandomState; use std::fmt::{Debug, Formatter}; -pub struct Ref<'a, K, V, S = RandomState> { - _guard: RwLockReadGuard<'a, HashMap>, +pub struct Ref<'a, K, V> { + _guard: RwLockReadGuard<'a, HashMap>, k: *const K, v: *const V, } -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Send for Ref<'a, K, V, S> {} -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Sync for Ref<'a, K, V, S> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for Ref<'a, K, V> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for Ref<'a, K, V> {} -impl<'a, K: Eq + Hash, V, S: BuildHasher> Ref<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> Ref<'a, K, V> { pub(crate) unsafe fn new( - guard: RwLockReadGuard<'a, HashMap>, + guard: RwLockReadGuard<'a, HashMap>, k: *const K, v: *const V, ) -> Self { @@ -39,7 +38,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Ref<'a, K, V, S> { unsafe { (&*self.k, &*self.v) } } - pub fn map(self, f: F) -> MappedRef<'a, K, V, T, S> + pub fn map(self, f: F) -> MappedRef<'a, K, V, T> where F: FnOnce(&V) -> &T, { @@ -50,7 +49,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Ref<'a, K, V, S> { } } - pub fn try_map(self, f: F) -> Result, Self> + pub fn try_map(self, f: F) -> Result, Self> where F: FnOnce(&V) -> Option<&T>, { @@ -66,7 +65,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Ref<'a, K, V, S> { } } -impl<'a, K: Eq + Hash + Debug, V: Debug, S: BuildHasher> Debug for Ref<'a, K, V, S> { +impl<'a, K: Eq + Hash + Debug, V: Debug> Debug for Ref<'a, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("Ref") .field("k", &self.k) @@ -75,7 +74,7 @@ impl<'a, K: Eq + Hash + Debug, V: Debug, S: BuildHasher> Debug for Ref<'a, K, V, } } -impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for Ref<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> Deref for Ref<'a, K, V> { type Target = V; fn deref(&self) -> &V { @@ -83,18 +82,18 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for Ref<'a, K, V, S> { } } -pub struct RefMut<'a, K, V, S = RandomState> { - guard: RwLockWriteGuard<'a, HashMap>, +pub struct RefMut<'a, K, V> { + guard: RwLockWriteGuard<'a, HashMap>, k: *const K, v: *mut V, } -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Send for RefMut<'a, K, V, S> {} -unsafe impl<'a, K: Eq + Hash + Sync, V: Sync, S: BuildHasher> Sync for RefMut<'a, K, V, S> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for RefMut<'a, K, V> {} +unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for RefMut<'a, K, V> {} -impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMut<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> RefMut<'a, K, V> { pub(crate) unsafe fn new( - guard: RwLockWriteGuard<'a, HashMap>, + guard: RwLockWriteGuard<'a, HashMap>, k: *const K, v: *mut V, ) -> Self { @@ -121,11 +120,11 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMut<'a, K, V, S> { unsafe { (&*self.k, &mut *self.v) } } - pub fn downgrade(self) -> Ref<'a, K, V, S> { + pub fn downgrade(self) -> Ref<'a, K, V> { unsafe { Ref::new(RwLockWriteGuard::downgrade(self.guard), self.k, self.v) } } - pub fn map(self, f: F) -> MappedRefMut<'a, K, V, T, S> + pub fn map(self, f: F) -> MappedRefMut<'a, K, V, T> where F: FnOnce(&mut V) -> &mut T, { @@ -136,7 +135,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMut<'a, K, V, S> { } } - pub fn try_map(self, f: F) -> Result, Self> + pub fn try_map(self, f: F) -> Result, Self> where F: FnOnce(&mut V) -> Option<&mut T>, { @@ -154,7 +153,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMut<'a, K, V, S> { } } -impl<'a, K: Eq + Hash + Debug, V: Debug, S: BuildHasher> Debug for RefMut<'a, K, V, S> { +impl<'a, K: Eq + Hash + Debug, V: Debug> Debug for RefMut<'a, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("RefMut") .field("k", &self.k) @@ -163,7 +162,7 @@ impl<'a, K: Eq + Hash + Debug, V: Debug, S: BuildHasher> Debug for RefMut<'a, K, } } -impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for RefMut<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> Deref for RefMut<'a, K, V> { type Target = V; fn deref(&self) -> &V { @@ -171,19 +170,19 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Deref for RefMut<'a, K, V, S> { } } -impl<'a, K: Eq + Hash, V, S: BuildHasher> DerefMut for RefMut<'a, K, V, S> { +impl<'a, K: Eq + Hash, V> DerefMut for RefMut<'a, K, V> { fn deref_mut(&mut self) -> &mut V { self.value_mut() } } -pub struct MappedRef<'a, K, V, T, S = RandomState> { - _guard: RwLockReadGuard<'a, HashMap>, +pub struct MappedRef<'a, K, V, T> { + _guard: RwLockReadGuard<'a, HashMap>, k: *const K, v: *const T, } -impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRef<'a, K, V, T, S> { +impl<'a, K: Eq + Hash, V, T> MappedRef<'a, K, V, T> { pub fn key(&self) -> &K { self.pair().0 } @@ -196,7 +195,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRef<'a, K, V, T, S> { unsafe { (&*self.k, &*self.v) } } - pub fn map(self, f: F) -> MappedRef<'a, K, V, T2, S> + pub fn map(self, f: F) -> MappedRef<'a, K, V, T2> where F: FnOnce(&T) -> &T2, { @@ -207,7 +206,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRef<'a, K, V, T, S> { } } - pub fn try_map(self, f: F) -> Result, Self> + pub fn try_map(self, f: F) -> Result, Self> where F: FnOnce(&T) -> Option<&T2>, { @@ -224,7 +223,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRef<'a, K, V, T, S> { } } -impl<'a, K: Eq + Hash + Debug, V, T: Debug, S: BuildHasher> Debug for MappedRef<'a, K, V, T, S> { +impl<'a, K: Eq + Hash + Debug, V, T: Debug> Debug for MappedRef<'a, K, V, T> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MappedRef") .field("k", &self.k) @@ -233,7 +232,7 @@ impl<'a, K: Eq + Hash + Debug, V, T: Debug, S: BuildHasher> Debug for MappedRef< } } -impl<'a, K: Eq + Hash, V, T, S: BuildHasher> Deref for MappedRef<'a, K, V, T, S> { +impl<'a, K: Eq + Hash, V, T> Deref for MappedRef<'a, K, V, T> { type Target = T; fn deref(&self) -> &T { @@ -255,13 +254,13 @@ impl<'a, K: Eq + Hash, V, T: AsRef, TDeref: ?Sized> AsRef } } -pub struct MappedRefMut<'a, K, V, T, S = RandomState> { - _guard: RwLockWriteGuard<'a, HashMap>, +pub struct MappedRefMut<'a, K, V, T> { + _guard: RwLockWriteGuard<'a, HashMap>, k: *const K, v: *mut T, } -impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRefMut<'a, K, V, T, S> { +impl<'a, K: Eq + Hash, V, T> MappedRefMut<'a, K, V, T> { pub fn key(&self) -> &K { self.pair().0 } @@ -282,7 +281,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRefMut<'a, K, V, T, S> { unsafe { (&*self.k, &mut *self.v) } } - pub fn map(self, f: F) -> MappedRefMut<'a, K, V, T2, S> + pub fn map(self, f: F) -> MappedRefMut<'a, K, V, T2> where F: FnOnce(&mut T) -> &mut T2, { @@ -293,7 +292,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRefMut<'a, K, V, T, S> { } } - pub fn try_map(self, f: F) -> Result, Self> + pub fn try_map(self, f: F) -> Result, Self> where F: FnOnce(&mut T) -> Option<&mut T2>, { @@ -311,7 +310,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> MappedRefMut<'a, K, V, T, S> { } } -impl<'a, K: Eq + Hash + Debug, V, T: Debug, S: BuildHasher> Debug for MappedRefMut<'a, K, V, T, S> { +impl<'a, K: Eq + Hash + Debug, V, T: Debug> Debug for MappedRefMut<'a, K, V, T> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MappedRefMut") .field("k", &self.k) @@ -320,7 +319,7 @@ impl<'a, K: Eq + Hash + Debug, V, T: Debug, S: BuildHasher> Debug for MappedRefM } } -impl<'a, K: Eq + Hash, V, T, S: BuildHasher> Deref for MappedRefMut<'a, K, V, T, S> { +impl<'a, K: Eq + Hash, V, T> Deref for MappedRefMut<'a, K, V, T> { type Target = T; fn deref(&self) -> &T { @@ -328,7 +327,7 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> Deref for MappedRefMut<'a, K, V, T, } } -impl<'a, K: Eq + Hash, V, T, S: BuildHasher> DerefMut for MappedRefMut<'a, K, V, T, S> { +impl<'a, K: Eq + Hash, V, T> DerefMut for MappedRefMut<'a, K, V, T> { fn deref_mut(&mut self) -> &mut T { self.value_mut() } diff --git a/src/rayon/map.rs b/src/rayon/map.rs index b5cff953..92d0f690 100644 --- a/src/rayon/map.rs +++ b/src/rayon/map.rs @@ -1,12 +1,10 @@ use crate::lock::RwLock; use crate::mapref::multiple::{RefMulti, RefMutMulti}; -use crate::util; use crate::{DashMap, HashMap}; use core::hash::{BuildHasher, Hash}; use crossbeam_utils::CachePadded; use rayon::iter::plumbing::UnindexedConsumer; use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; -use std::collections::hash_map::RandomState; use std::sync::Arc; impl ParallelExtend<(K, V)> for DashMap @@ -70,7 +68,7 @@ where V: Send, S: Send + Clone + BuildHasher, { - type Iter = OwningIter; + type Iter = OwningIter; type Item = (K, V); fn into_par_iter(self) -> Self::Iter { @@ -80,15 +78,14 @@ where } } -pub struct OwningIter { - pub(super) shards: Box<[CachePadded>>]>, +pub struct OwningIter { + pub(super) shards: Box<[CachePadded>>]>, } -impl ParallelIterator for OwningIter +impl ParallelIterator for OwningIter where K: Send + Eq + Hash, V: Send, - S: Send + Clone + BuildHasher, { type Item = (K, V); @@ -116,8 +113,8 @@ where V: Send + Sync, S: Send + Sync + Clone + BuildHasher, { - type Iter = Iter<'a, K, V, S>; - type Item = RefMulti<'a, K, V, S>; + type Iter = Iter<'a, K, V>; + type Item = RefMulti<'a, K, V>; fn into_par_iter(self) -> Self::Iter { Iter { @@ -126,17 +123,16 @@ where } } -pub struct Iter<'a, K, V, S = RandomState> { - pub(super) shards: &'a [CachePadded>>], +pub struct Iter<'a, K, V> { + pub(super) shards: &'a [CachePadded>>], } -impl<'a, K, V, S> ParallelIterator for Iter<'a, K, V, S> +impl<'a, K, V> ParallelIterator for Iter<'a, K, V> where K: Send + Sync + Eq + Hash, V: Send + Sync, - S: Send + Sync + Clone + BuildHasher, { - type Item = RefMulti<'a, K, V, S>; + type Item = RefMulti<'a, K, V>; fn drive_unindexed(self, consumer: C) -> C::Result where @@ -144,14 +140,12 @@ where { self.shards .into_par_iter() - .flat_map_iter(|shard| { - let guard = shard.read(); - let sref: &'a HashMap = unsafe { util::change_lifetime_const(&*guard) }; - - let guard = Arc::new(guard); - sref.iter().map(move |(k, v)| { + .flat_map_iter(|shard| unsafe { + let guard = Arc::new(shard.read()); + guard.iter().map(move |b| { let guard = Arc::clone(&guard); - unsafe { RefMulti::new(guard, k, v.get()) } + let (k, v) = b.as_ref(); + RefMulti::new(guard, k, v.get()) }) }) .drive_unindexed(consumer) @@ -159,14 +153,13 @@ where } // This impl also enables `IntoParallelRefMutIterator::par_iter_mut` -impl<'a, K, V, S> IntoParallelIterator for &'a mut DashMap +impl<'a, K, V> IntoParallelIterator for &'a mut DashMap where K: Send + Sync + Eq + Hash, V: Send + Sync, - S: Send + Sync + Clone + BuildHasher, { - type Iter = IterMut<'a, K, V, S>; - type Item = RefMutMulti<'a, K, V, S>; + type Iter = IterMut<'a, K, V>; + type Item = RefMutMulti<'a, K, V>; fn into_par_iter(self) -> Self::Iter { IterMut { @@ -179,27 +172,25 @@ impl DashMap where K: Send + Sync + Eq + Hash, V: Send + Sync, - S: Send + Sync + Clone + BuildHasher, { // Unlike `IntoParallelRefMutIterator::par_iter_mut`, we only _need_ `&self`. - pub fn par_iter_mut(&self) -> IterMut<'_, K, V, S> { + pub fn par_iter_mut(&self) -> IterMut<'_, K, V> { IterMut { shards: &self.shards, } } } -pub struct IterMut<'a, K, V, S = RandomState> { - shards: &'a [CachePadded>>], +pub struct IterMut<'a, K, V> { + shards: &'a [CachePadded>>], } -impl<'a, K, V, S> ParallelIterator for IterMut<'a, K, V, S> +impl<'a, K, V> ParallelIterator for IterMut<'a, K, V> where K: Send + Sync + Eq + Hash, V: Send + Sync, - S: Send + Sync + Clone + BuildHasher, { - type Item = RefMutMulti<'a, K, V, S>; + type Item = RefMutMulti<'a, K, V>; fn drive_unindexed(self, consumer: C) -> C::Result where @@ -207,15 +198,12 @@ where { self.shards .into_par_iter() - .flat_map_iter(|shard| { - let mut guard = shard.write(); - let sref: &'a mut HashMap = - unsafe { util::change_lifetime_mut(&mut *guard) }; - - let guard = Arc::new(guard); - sref.iter_mut().map(move |(k, v)| { + .flat_map_iter(|shard| unsafe { + let guard = Arc::new(shard.write()); + guard.iter().map(move |b| { let guard = Arc::clone(&guard); - unsafe { RefMutMulti::new(guard, k, v.get_mut()) } + let (k, v) = b.as_mut(); + RefMutMulti::new(guard, k, v.get_mut()) }) }) .drive_unindexed(consumer) diff --git a/src/rayon/read_only.rs b/src/rayon/read_only.rs index a11448ce..d37bb875 100644 --- a/src/rayon/read_only.rs +++ b/src/rayon/read_only.rs @@ -10,7 +10,7 @@ where V: Send, S: Send + Clone + BuildHasher, { - type Iter = super::map::OwningIter; + type Iter = super::map::OwningIter; type Item = (K, V); fn into_par_iter(self) -> Self::Iter { @@ -27,8 +27,8 @@ where V: Send + Sync, S: Send + Sync + Clone + BuildHasher, { - type Iter = Iter<'a, K, V, S>; - type Item = RefMulti<'a, K, V, S>; + type Iter = Iter<'a, K, V>; + type Item = RefMulti<'a, K, V>; fn into_par_iter(self) -> Self::Iter { Iter { diff --git a/src/rayon/set.rs b/src/rayon/set.rs index 11c06ccb..c92e2cd9 100644 --- a/src/rayon/set.rs +++ b/src/rayon/set.rs @@ -3,7 +3,6 @@ use crate::DashSet; use core::hash::{BuildHasher, Hash}; use rayon::iter::plumbing::UnindexedConsumer; use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; -use std::collections::hash_map::RandomState; impl ParallelExtend for DashSet where @@ -56,7 +55,7 @@ where K: Send + Eq + Hash, S: Send + Clone + BuildHasher, { - type Iter = OwningIter; + type Iter = OwningIter; type Item = K; fn into_par_iter(self) -> Self::Iter { @@ -66,14 +65,13 @@ where } } -pub struct OwningIter { - inner: super::map::OwningIter, +pub struct OwningIter { + inner: super::map::OwningIter, } -impl ParallelIterator for OwningIter +impl ParallelIterator for OwningIter where K: Send + Eq + Hash, - S: Send + Clone + BuildHasher, { type Item = K; @@ -91,8 +89,8 @@ where K: Send + Sync + Eq + Hash, S: Send + Sync + Clone + BuildHasher, { - type Iter = Iter<'a, K, S>; - type Item = RefMulti<'a, K, S>; + type Iter = Iter<'a, K>; + type Item = RefMulti<'a, K>; fn into_par_iter(self) -> Self::Iter { Iter { @@ -101,16 +99,15 @@ where } } -pub struct Iter<'a, K, S = RandomState> { - inner: super::map::Iter<'a, K, (), S>, +pub struct Iter<'a, K> { + inner: super::map::Iter<'a, K, ()>, } -impl<'a, K, S> ParallelIterator for Iter<'a, K, S> +impl<'a, K> ParallelIterator for Iter<'a, K> where K: Send + Sync + Eq + Hash, - S: Send + Sync + Clone + BuildHasher, { - type Item = RefMulti<'a, K, S>; + type Item = RefMulti<'a, K>; fn drive_unindexed(self, consumer: C) -> C::Result where diff --git a/src/read_only.rs b/src/read_only.rs index b147bb11..dae46fca 100644 --- a/src/read_only.rs +++ b/src/read_only.rs @@ -62,13 +62,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_usize(&key); - - let idx = self.map.determine_shard(hash); - - let shard = unsafe { self.map._get_read_shard(idx) }; - - shard.contains_key(key) + self.get(key).is_some() } /// Returns a reference to the value corresponding to the key. @@ -77,13 +71,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_usize(&key); - - let idx = self.map.determine_shard(hash); - - let shard = unsafe { self.map._get_read_shard(idx) }; - - shard.get(key).map(|v| v.get()) + self.get_key_value(key).map(|(_k, v)| v) } /// Returns the key-value pair corresponding to the supplied key. @@ -92,37 +80,39 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView K: Borrow, Q: Hash + Eq + ?Sized, { - let hash = self.map.hash_usize(&key); + let hash = self.map.hash_u64(&key); - let idx = self.map.determine_shard(hash); + let idx = self.map.determine_shard(hash as usize); let shard = unsafe { self.map._get_read_shard(idx) }; - shard.get_key_value(key).map(|(k, v)| (k, v.get())) - } - - fn shard_read_iter(&'a self) -> impl Iterator> + 'a { - (0..self.map._shard_count()) - .map(move |shard_i| unsafe { self.map._get_read_shard(shard_i) }) + shard.find(hash, |(k, _v)| key == k.borrow()).map(|b| { + let (k, v) = unsafe { b.as_ref() }; + (k, v.get()) + }) } /// An iterator visiting all key-value pairs in arbitrary order. The iterator element type is `(&'a K, &'a V)`. pub fn iter(&'a self) -> impl Iterator + 'a { - self.shard_read_iter() - .flat_map(|shard| shard.iter()) - .map(|(k, v)| (k, v.get())) + unsafe { + (0..self.map._shard_count()) + .map(move |shard_i| self.map._get_read_shard(shard_i)) + .flat_map(|shard| shard.iter()) + .map(|b| { + let (k, v) = b.as_ref(); + (k, v.get()) + }) + } } /// An iterator visiting all keys in arbitrary order. The iterator element type is `&'a K`. pub fn keys(&'a self) -> impl Iterator + 'a { - self.shard_read_iter().flat_map(|shard| shard.keys()) + self.iter().map(|(k, _v)| k) } /// An iterator visiting all values in arbitrary order. The iterator element type is `&'a V`. pub fn values(&'a self) -> impl Iterator + 'a { - self.shard_read_iter() - .flat_map(|shard| shard.values()) - .map(|v| v.get()) + self.iter().map(|(_k, v)| v) } cfg_if! { @@ -140,12 +130,12 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView /// let map = DashMap::<(), ()>::new().into_read_only(); /// println!("Amount of shards: {}", map.shards().len()); /// ``` - pub fn shards(&self) -> &[CachePadded>>] { + pub fn shards(&self) -> &[CachePadded>>] { &self.map.shards } } else { #[allow(dead_code)] - pub(crate) fn shards(&self) -> &[CachePadded>>] { + pub(crate) fn shards(&self) -> &[CachePadded>>] { &self.map.shards } } diff --git a/src/serde.rs b/src/serde.rs index 6abeb069..27a7c421 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -169,47 +169,35 @@ macro_rules! serialize_impl { } // Map -impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize - for mapref::multiple::RefMulti<'a, K, V, S> -{ +impl<'a, K: Eq + Hash, V: Serialize> Serialize for mapref::multiple::RefMulti<'a, K, V> { serialize_impl! {} } -impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize - for mapref::multiple::RefMutMulti<'a, K, V, S> -{ +impl<'a, K: Eq + Hash, V: Serialize> Serialize for mapref::multiple::RefMutMulti<'a, K, V> { serialize_impl! {} } -impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize for mapref::one::Ref<'a, K, V, S> { +impl<'a, K: Eq + Hash, V: Serialize> Serialize for mapref::one::Ref<'a, K, V> { serialize_impl! {} } -impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize - for mapref::one::RefMut<'a, K, V, S> -{ +impl<'a, K: Eq + Hash, V: Serialize> Serialize for mapref::one::RefMut<'a, K, V> { serialize_impl! {} } -impl<'a, K: Eq + Hash, V, T: Serialize, S: BuildHasher> Serialize - for mapref::one::MappedRef<'a, K, V, T, S> -{ +impl<'a, K: Eq + Hash, V, T: Serialize> Serialize for mapref::one::MappedRef<'a, K, V, T> { serialize_impl! {} } -impl<'a, K: Eq + Hash, V, T: Serialize, S: BuildHasher> Serialize - for mapref::one::MappedRefMut<'a, K, V, T, S> -{ +impl<'a, K: Eq + Hash, V, T: Serialize> Serialize for mapref::one::MappedRefMut<'a, K, V, T> { serialize_impl! {} } // Set -impl<'a, V: Hash + Eq + Serialize, S: BuildHasher> Serialize - for setref::multiple::RefMulti<'a, V, S> -{ +impl<'a, V: Hash + Eq + Serialize> Serialize for setref::multiple::RefMulti<'a, V> { serialize_impl! {} } -impl<'a, V: Hash + Eq + Serialize, S: BuildHasher> Serialize for setref::one::Ref<'a, V, S> { +impl<'a, V: Hash + Eq + Serialize> Serialize for setref::one::Ref<'a, V> { serialize_impl! {} } diff --git a/src/set.rs b/src/set.rs index c61e930f..14110084 100644 --- a/src/set.rs +++ b/src/set.rs @@ -138,7 +138,7 @@ impl<'a, K: 'a + Eq + Hash, S: BuildHasher + Clone> DashSet { /// let set = DashSet::<()>::new(); /// println!("Amount of shards: {}", set.shards().len()); /// ``` - pub fn shards(&self) -> &[CachePadded>>] { + pub fn shards(&self) -> &[CachePadded>>] { self.inner.shards() } } @@ -282,7 +282,7 @@ impl<'a, K: 'a + Eq + Hash, S: BuildHasher + Clone> DashSet { /// youtubers.insert("Bosnian Bill"); /// assert_eq!(*youtubers.get("Bosnian Bill").unwrap(), "Bosnian Bill"); /// ``` - pub fn get(&'a self, key: &Q) -> Option> + pub fn get(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized, diff --git a/src/setref/multiple.rs b/src/setref/multiple.rs index 21e7ed4a..4806c346 100644 --- a/src/setref/multiple.rs +++ b/src/setref/multiple.rs @@ -1,13 +1,13 @@ use crate::mapref; -use core::hash::{BuildHasher, Hash}; +use core::hash::Hash; use core::ops::Deref; -use std::collections::hash_map::RandomState; -pub struct RefMulti<'a, K, S = RandomState> { - inner: mapref::multiple::RefMulti<'a, K, (), S>, + +pub struct RefMulti<'a, K> { + inner: mapref::multiple::RefMulti<'a, K, ()>, } -impl<'a, K: Eq + Hash, S: BuildHasher> RefMulti<'a, K, S> { - pub(crate) fn new(inner: mapref::multiple::RefMulti<'a, K, (), S>) -> Self { +impl<'a, K: Eq + Hash> RefMulti<'a, K> { + pub(crate) fn new(inner: mapref::multiple::RefMulti<'a, K, ()>) -> Self { Self { inner } } @@ -16,7 +16,7 @@ impl<'a, K: Eq + Hash, S: BuildHasher> RefMulti<'a, K, S> { } } -impl<'a, K: Eq + Hash, S: BuildHasher> Deref for RefMulti<'a, K, S> { +impl<'a, K: Eq + Hash> Deref for RefMulti<'a, K> { type Target = K; fn deref(&self) -> &K { diff --git a/src/setref/one.rs b/src/setref/one.rs index 0787187d..5f6d71da 100644 --- a/src/setref/one.rs +++ b/src/setref/one.rs @@ -1,13 +1,13 @@ use crate::mapref; -use core::hash::{BuildHasher, Hash}; +use core::hash::Hash; use core::ops::Deref; -use std::collections::hash_map::RandomState; -pub struct Ref<'a, K, S = RandomState> { - inner: mapref::one::Ref<'a, K, (), S>, + +pub struct Ref<'a, K> { + inner: mapref::one::Ref<'a, K, ()>, } -impl<'a, K: Eq + Hash, S: BuildHasher> Ref<'a, K, S> { - pub(crate) fn new(inner: mapref::one::Ref<'a, K, (), S>) -> Self { +impl<'a, K: Eq + Hash> Ref<'a, K> { + pub(crate) fn new(inner: mapref::one::Ref<'a, K, ()>) -> Self { Self { inner } } @@ -16,7 +16,7 @@ impl<'a, K: Eq + Hash, S: BuildHasher> Ref<'a, K, S> { } } -impl<'a, K: Eq + Hash, S: BuildHasher> Deref for Ref<'a, K, S> { +impl<'a, K: Eq + Hash> Deref for Ref<'a, K> { type Target = K; fn deref(&self) -> &K { diff --git a/src/t.rs b/src/t.rs index 5e1fedcc..26c5d127 100644 --- a/src/t.rs +++ b/src/t.rs @@ -16,17 +16,17 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> { /// # Safety /// /// The index must not be out of bounds. - unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap; + unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap; /// # Safety /// /// The index must not be out of bounds. - unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap>; + unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap>; /// # Safety /// /// The index must not be out of bounds. - unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap>; + unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap>; /// # Safety /// @@ -34,7 +34,7 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> { unsafe fn _try_yield_read_shard( &'a self, i: usize, - ) -> Option>>; + ) -> Option>>; /// # Safety /// @@ -42,7 +42,7 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> { unsafe fn _try_yield_write_shard( &'a self, i: usize, - ) -> Option>>; + ) -> Option>>; fn _insert(&self, key: K, value: V) -> Option; @@ -69,22 +69,22 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> { where Self: Sized; - fn _get(&'a self, key: &Q) -> Option> + fn _get(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized; - fn _get_mut(&'a self, key: &Q) -> Option> + fn _get_mut(&'a self, key: &Q) -> Option> where K: Borrow, Q: Hash + Eq + ?Sized; - fn _try_get(&'a self, key: &Q) -> TryResult> + fn _try_get(&'a self, key: &Q) -> TryResult> where K: Borrow, Q: Hash + Eq + ?Sized; - fn _try_get_mut(&'a self, key: &Q) -> TryResult> + fn _try_get_mut(&'a self, key: &Q) -> TryResult> where K: Borrow, Q: Hash + Eq + ?Sized; @@ -109,9 +109,9 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> { K: Borrow, Q: Hash + Eq + ?Sized; - fn _entry(&'a self, key: K) -> Entry<'a, K, V, S>; + fn _entry(&'a self, key: K) -> Entry<'a, K, V>; - fn _try_entry(&'a self, key: K) -> Option>; + fn _try_entry(&'a self, key: K) -> Option>; fn _hasher(&self) -> S; diff --git a/src/util.rs b/src/util.rs index 09ffc850..c5eb903e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -22,22 +22,6 @@ pub fn map_in_place_2 T>((k, v): (U, &mut T), f: F) { } } -/// # Safety -/// -/// Requires that you ensure the reference does not become invalid. -/// The object has to outlive the reference. -pub unsafe fn change_lifetime_const<'a, 'b, T>(x: &'a T) -> &'b T { - &*(x as *const T) -} - -/// # Safety -/// -/// Requires that you ensure the reference does not become invalid. -/// The object has to outlive the reference. -pub unsafe fn change_lifetime_mut<'a, 'b, T>(x: &'a mut T) -> &'b mut T { - &mut *(x as *mut T) -} - /// A simple wrapper around `T` /// /// This is to prevent UB when using `HashMap::get_key_value`, because