mirror of https://github.com/xacrimon/dashmap
Merge 0f95f5932e
into 626b98dab3
This commit is contained in:
commit
c43436e655
|
@ -91,9 +91,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"
|
||||
|
|
|
@ -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 }
|
||||
|
|
71
src/iter.rs
71
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<K: Eq + Hash, V, S: BuildHasher + Clone> OwningIter<K, V, S> {
|
|||
}
|
||||
}
|
||||
|
||||
type GuardOwningIter<K, V> = hash_map::IntoIter<K, SharedValue<V>>;
|
||||
type GuardOwningIter<K, V> = hashbrown::raw::RawIntoIter<(K, SharedValue<V>)>;
|
||||
|
||||
impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for OwningIter<K, V, S> {
|
||||
type Item = (K, V);
|
||||
|
@ -59,9 +58,7 @@ impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for OwningIter<K, V, S> {
|
|||
//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<RwLockReadGuard<'a, HashMap<K, V, S>>>,
|
||||
hash_map::Iter<'a, K, SharedValue<V>>,
|
||||
type GuardIter<'a, K, V> = (
|
||||
Arc<RwLockReadGuard<'a, HashMap<K, V>>>,
|
||||
hashbrown::raw::RawIter<(K, SharedValue<V>)>,
|
||||
);
|
||||
|
||||
type GuardIterMut<'a, K, V, S> = (
|
||||
Arc<RwLockWriteGuard<'a, HashMap<K, V, S>>>,
|
||||
hash_map::IterMut<'a, K, SharedValue<V>>,
|
||||
type GuardIterMut<'a, K, V> = (
|
||||
Arc<RwLockWriteGuard<'a, HashMap<K, V>>>,
|
||||
hashbrown::raw::RawIter<(K, SharedValue<V>)>,
|
||||
);
|
||||
|
||||
/// 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<K, V, S>> {
|
||||
map: &'a M,
|
||||
shard_i: usize,
|
||||
current: Option<GuardIter<'a, K, V, S>>,
|
||||
current: Option<GuardIter<'a, K, V>>,
|
||||
marker: PhantomData<S>,
|
||||
}
|
||||
|
||||
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<Self::Item> {
|
||||
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<K, V, S> = 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<K, V, S>> {
|
||||
map: &'a M,
|
||||
shard_i: usize,
|
||||
current: Option<GuardIterMut<'a, K, V, S>>,
|
||||
current: Option<GuardIterMut<'a, K, V>>,
|
||||
marker: PhantomData<S>,
|
||||
}
|
||||
|
||||
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<Self::Item> {
|
||||
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 guard = unsafe { self.map._yield_write_shard(self.shard_i) };
|
||||
|
||||
let sref: &mut HashMap<K, V, S> = unsafe { util::change_lifetime_mut(&mut *guard) };
|
||||
|
||||
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);
|
||||
|
|
|
@ -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::Item> {
|
||||
self.inner.next().map(RefMulti::new)
|
||||
|
|
274
src/lib.rs
274
src/lib.rs
|
@ -53,7 +53,7 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type HashMap<K, V, S> = hashbrown::HashMap<K, SharedValue<V>, S>;
|
||||
pub(crate) type HashMap<K, V> = hashbrown::raw::RawTable<(K, SharedValue<V>)>;
|
||||
|
||||
// Temporary reimplementation of [`std::collections::TryReserveError`]
|
||||
// util [`std::collections::TryReserveError`] stabilises.
|
||||
|
@ -79,7 +79,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<HashMap<K, V, S>>`.
|
||||
/// DashMap tries to be very simple to use and to be a direct replacement for `RwLock<HashMap<K, V>>`.
|
||||
/// To accomplish this, all methods take `&self` instead of modifying methods taking `&mut self`.
|
||||
/// This allows you to put a DashMap in an `Arc<T>` and share it between threads while being able to modify it.
|
||||
///
|
||||
|
@ -87,7 +87,7 @@ fn ncb(shard_amount: usize) -> usize {
|
|||
/// This means that it is safe to ignore it across multiple threads.
|
||||
pub struct DashMap<K, V, S = RandomState> {
|
||||
shift: usize,
|
||||
shards: Box<[RwLock<HashMap<K, V, S>>]>,
|
||||
shards: Box<[RwLock<HashMap<K, V>>]>,
|
||||
hasher: S,
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
let cps = capacity / shard_amount;
|
||||
|
||||
let shards = (0..shard_amount)
|
||||
.map(|_| RwLock::new(HashMap::with_capacity_and_hasher(cps, hasher.clone())))
|
||||
.map(|_| RwLock::new(HashMap::with_capacity(cps)))
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
|
@ -295,11 +295,15 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// Hash a given item to produce a usize.
|
||||
/// Uses the provided or default HashBuilder.
|
||||
pub fn hash_usize<T: Hash>(&self, item: &T) -> usize {
|
||||
self.hash_u64(item) as usize
|
||||
}
|
||||
|
||||
fn hash_u64<T: Hash>(&self, item: &T) -> u64 {
|
||||
let mut hasher = self.hasher.build_hasher();
|
||||
|
||||
item.hash(&mut hasher);
|
||||
|
||||
hasher.finish() as usize
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
@ -317,7 +321,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// let map = DashMap::<(), ()>::new();
|
||||
/// println!("Amount of shards: {}", map.shards().len());
|
||||
/// ```
|
||||
pub fn shards(&self) -> &[RwLock<HashMap<K, V, S>>] {
|
||||
pub fn shards(&self) -> &[RwLock<HashMap<K, V>>] {
|
||||
&self.shards
|
||||
}
|
||||
|
||||
|
@ -337,7 +341,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// map.shards_mut()[shard_ind].get_mut().insert(42, SharedValue::new("forty two"));
|
||||
/// assert_eq!(*map.get(&42).unwrap(), "forty two");
|
||||
/// ```
|
||||
pub fn shards_mut(&mut self) -> &mut [RwLock<HashMap<K, V, S>>] {
|
||||
pub fn shards_mut(&mut self) -> &mut [RwLock<HashMap<K, V>>] {
|
||||
&mut self.shards
|
||||
}
|
||||
|
||||
|
@ -347,22 +351,22 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// Requires the `raw-api` feature to be enabled.
|
||||
///
|
||||
/// See [`DashMap::shards()`] and [`DashMap::shards_mut()`] for more information.
|
||||
pub fn into_shards(self) -> Box<[RwLock<HashMap<K, V, S>>]> {
|
||||
pub fn into_shards(self) -> Box<[RwLock<HashMap<K, V>>]> {
|
||||
self.shards
|
||||
}
|
||||
} else {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn shards(&self) -> &[RwLock<HashMap<K, V, S>>] {
|
||||
pub(crate) fn shards(&self) -> &[RwLock<HashMap<K, V>>] {
|
||||
&self.shards
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn shards_mut(&mut self) -> &mut [RwLock<HashMap<K, V, S>>] {
|
||||
pub(crate) fn shards_mut(&mut self) -> &mut [RwLock<HashMap<K, V>>] {
|
||||
&mut self.shards
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn into_shards(self) -> Box<[RwLock<HashMap<K, V, S>>]> {
|
||||
pub(crate) fn into_shards(self) -> Box<[RwLock<HashMap<K, V>>]> {
|
||||
self.shards
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +569,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// youtubers.insert("Bosnian Bill", 457000);
|
||||
/// assert_eq!(*youtubers.get("Bosnian Bill").unwrap(), 457000);
|
||||
/// ```
|
||||
pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V, S>>
|
||||
pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized,
|
||||
|
@ -587,7 +591,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// *class.get_mut("Albin").unwrap() -= 1;
|
||||
/// assert_eq!(*class.get("Albin").unwrap(), 14);
|
||||
/// ```
|
||||
pub fn get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V, S>>
|
||||
pub fn get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized,
|
||||
|
@ -614,7 +618,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// let result2 = map.try_get("Johnny");
|
||||
/// assert!(result2.is_locked());
|
||||
/// ```
|
||||
pub fn try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V, S>>
|
||||
pub fn try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized,
|
||||
|
@ -642,7 +646,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// let result2 = map.try_get_mut("Johnny");
|
||||
/// assert!(result2.is_locked());
|
||||
/// ```
|
||||
pub fn try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V, S>>
|
||||
pub fn try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized,
|
||||
|
@ -841,7 +845,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// 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)
|
||||
}
|
||||
|
||||
|
@ -849,7 +853,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
/// 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<Entry<'a, K, V, S>> {
|
||||
pub fn try_entry(&'a self, key: K) -> Option<Entry<'a, K, V>> {
|
||||
self._try_entry(key)
|
||||
}
|
||||
|
||||
|
@ -865,7 +869,11 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
|
|||
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(())
|
||||
|
@ -879,19 +887,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<K, V, S> {
|
||||
unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap<K, V> {
|
||||
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<K, V, S>> {
|
||||
unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap<K, V>> {
|
||||
debug_assert!(i < self.shards.len());
|
||||
|
||||
self.shards.get_unchecked(i).read()
|
||||
}
|
||||
|
||||
unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap<K, V, S>> {
|
||||
unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap<K, V>> {
|
||||
debug_assert!(i < self.shards.len());
|
||||
|
||||
self.shards.get_unchecked(i).write()
|
||||
|
@ -900,7 +908,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<RwLockReadGuard<'a, HashMap<K, V, S>>> {
|
||||
) -> Option<RwLockReadGuard<'a, HashMap<K, V>>> {
|
||||
debug_assert!(i < self.shards.len());
|
||||
|
||||
self.shards.get_unchecked(i).try_read()
|
||||
|
@ -909,22 +917,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<RwLockWriteGuard<'a, HashMap<K, V, S>>> {
|
||||
) -> Option<RwLockWriteGuard<'a, HashMap<K, V>>> {
|
||||
debug_assert!(i < self.shards.len());
|
||||
|
||||
self.shards.get_unchecked(i).try_write()
|
||||
}
|
||||
|
||||
fn _insert(&self, key: K, value: V) -> Option<V> {
|
||||
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<Q>(&self, key: &Q) -> Option<(K, V)>
|
||||
|
@ -932,13 +938,18 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
|
|||
K: Borrow<Q>,
|
||||
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<Q>(&self, key: &Q, f: impl FnOnce(&K, &V) -> bool) -> Option<(K, V)>
|
||||
|
@ -946,22 +957,19 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
|
|||
K: Borrow<Q>,
|
||||
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
|
||||
|
@ -973,22 +981,19 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
|
|||
K: Borrow<Q>,
|
||||
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
|
||||
|
@ -1003,94 +1008,90 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
|
|||
IterMut::new(self)
|
||||
}
|
||||
|
||||
fn _get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V, S>>
|
||||
fn _get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
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<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V, S>>
|
||||
fn _get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
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<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V, S>>
|
||||
fn _try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
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<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V, S>>
|
||||
fn _try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
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
|
||||
|
@ -1098,13 +1099,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 {
|
||||
|
@ -1126,11 +1142,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<Q, R>(&self, key: &Q, f: impl FnOnce(&K, &V) -> R) -> Option<R>
|
||||
|
@ -1144,47 +1157,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<Entry<'a, K, V, S>> {
|
||||
let hash = self.hash_usize(&key);
|
||||
fn _try_entry(&'a self, key: K) -> Option<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 = 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)
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1222,7 +1240,7 @@ where
|
|||
K: Borrow<Q>,
|
||||
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()
|
||||
|
@ -1234,7 +1252,7 @@ where
|
|||
K: Borrow<Q>,
|
||||
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()
|
||||
|
@ -1276,7 +1294,7 @@ impl<K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for DashMap<K, V, S>
|
|||
}
|
||||
|
||||
impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for &'a DashMap<K, V, S> {
|
||||
type Item = RefMulti<'a, K, V, S>;
|
||||
type Item = RefMulti<'a, K, V>;
|
||||
|
||||
type IntoIter = Iter<'a, K, V, S, DashMap<K, V, S>>;
|
||||
|
||||
|
|
|
@ -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<E>(
|
||||
self,
|
||||
value: impl FnOnce() -> Result<V, E>,
|
||||
) -> Result<RefMut<'a, K, V, S>, E> {
|
||||
) -> Result<RefMut<'a, K, V>, 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<K, V, S>>,
|
||||
pub struct VacantEntry<'a, K, V> {
|
||||
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
|
||||
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<K, V, S>>, 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<K, V>>,
|
||||
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);
|
||||
let occupied = self.shard.insert_in_slot(
|
||||
self.hash,
|
||||
self.slot,
|
||||
(self.key, SharedValue::new(value)),
|
||||
);
|
||||
|
||||
self.shard.insert(self.key, SharedValue::new(value));
|
||||
let (k, v) = occupied.as_ref();
|
||||
|
||||
let (k, v) = self.shard.get_key_value(&c).unwrap();
|
||||
|
||||
let k = util::change_lifetime_const(k);
|
||||
|
||||
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<K, V, S>>,
|
||||
elem: (*const K, *mut V),
|
||||
pub struct OccupiedEntry<'a, K, V> {
|
||||
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
|
||||
bucket: hashbrown::raw::Bucket<(K, SharedValue<V>)>,
|
||||
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<K, V, S>>,
|
||||
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
|
||||
key: K,
|
||||
elem: (*const K, *mut V),
|
||||
bucket: hashbrown::raw::Bucket<(K, SharedValue<V>)>,
|
||||
) -> 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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RwLockReadGuard<'a, HashMap<K, V, S>>>,
|
||||
pub struct RefMulti<'a, K, V> {
|
||||
_guard: Arc<RwLockReadGuard<'a, HashMap<K, V>>>,
|
||||
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<RwLockReadGuard<'a, HashMap<K, V, S>>>,
|
||||
guard: Arc<RwLockReadGuard<'a, HashMap<K, V>>>,
|
||||
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<RwLockWriteGuard<'a, HashMap<K, V, S>>>,
|
||||
pub struct RefMutMulti<'a, K, V> {
|
||||
_guard: Arc<RwLockWriteGuard<'a, HashMap<K, V>>>,
|
||||
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<RwLockWriteGuard<'a, HashMap<K, V, S>>>,
|
||||
guard: Arc<RwLockWriteGuard<'a, HashMap<K, V>>>,
|
||||
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()
|
||||
}
|
||||
|
|
|
@ -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<K, V, S>>,
|
||||
pub struct Ref<'a, K, V> {
|
||||
_guard: RwLockReadGuard<'a, HashMap<K, V>>,
|
||||
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<K, V, S>>,
|
||||
guard: RwLockReadGuard<'a, HashMap<K, V>>,
|
||||
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<F, T>(self, f: F) -> MappedRef<'a, K, V, T, S>
|
||||
pub fn map<F, T>(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<F, T>(self, f: F) -> Result<MappedRef<'a, K, V, T, S>, Self>
|
||||
pub fn try_map<F, T>(self, f: F) -> Result<MappedRef<'a, K, V, T>, 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<K, V, S>>,
|
||||
pub struct RefMut<'a, K, V> {
|
||||
guard: RwLockWriteGuard<'a, HashMap<K, V>>,
|
||||
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<K, V, S>>,
|
||||
guard: RwLockWriteGuard<'a, HashMap<K, V>>,
|
||||
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<F, T>(self, f: F) -> MappedRefMut<'a, K, V, T, S>
|
||||
pub fn map<F, T>(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<F, T>(self, f: F) -> Result<MappedRefMut<'a, K, V, T, S>, Self>
|
||||
pub fn try_map<F, T>(self, f: F) -> Result<MappedRefMut<'a, K, V, T>, 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<K, V, S>>,
|
||||
pub struct MappedRef<'a, K, V, T> {
|
||||
_guard: RwLockReadGuard<'a, HashMap<K, V>>,
|
||||
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<F, T2>(self, f: F) -> MappedRef<'a, K, V, T2, S>
|
||||
pub fn map<F, T2>(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<F, T2>(self, f: F) -> Result<MappedRef<'a, K, V, T2, S>, Self>
|
||||
pub fn try_map<F, T2>(self, f: F) -> Result<MappedRef<'a, K, V, T2>, 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>, TDeref: ?Sized> AsRef<TDeref>
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MappedRefMut<'a, K, V, T, S = RandomState> {
|
||||
_guard: RwLockWriteGuard<'a, HashMap<K, V, S>>,
|
||||
pub struct MappedRefMut<'a, K, V, T> {
|
||||
_guard: RwLockWriteGuard<'a, HashMap<K, V>>,
|
||||
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<F, T2>(self, f: F) -> MappedRefMut<'a, K, V, T2, S>
|
||||
pub fn map<F, T2>(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<F, T2>(self, f: F) -> Result<MappedRefMut<'a, K, V, T2, S>, Self>
|
||||
pub fn try_map<F, T2>(self, f: F) -> Result<MappedRefMut<'a, K, V, T2>, 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()
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use crate::lock::RwLock;
|
||||
use crate::mapref::multiple::{RefMulti, RefMutMulti};
|
||||
use crate::util;
|
||||
use crate::{DashMap, HashMap};
|
||||
use core::hash::{BuildHasher, Hash};
|
||||
use rayon::iter::plumbing::UnindexedConsumer;
|
||||
use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
|
||||
use std::collections::hash_map::RandomState;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl<K, V, S> ParallelExtend<(K, V)> for DashMap<K, V, S>
|
||||
|
@ -69,7 +67,7 @@ where
|
|||
V: Send,
|
||||
S: Send + Clone + BuildHasher,
|
||||
{
|
||||
type Iter = OwningIter<K, V, S>;
|
||||
type Iter = OwningIter<K, V>;
|
||||
type Item = (K, V);
|
||||
|
||||
fn into_par_iter(self) -> Self::Iter {
|
||||
|
@ -79,15 +77,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct OwningIter<K, V, S = RandomState> {
|
||||
pub(super) shards: Box<[RwLock<HashMap<K, V, S>>]>,
|
||||
pub struct OwningIter<K, V> {
|
||||
pub(super) shards: Box<[RwLock<HashMap<K, V>>]>,
|
||||
}
|
||||
|
||||
impl<K, V, S> ParallelIterator for OwningIter<K, V, S>
|
||||
impl<K, V> ParallelIterator for OwningIter<K, V>
|
||||
where
|
||||
K: Send + Eq + Hash,
|
||||
V: Send,
|
||||
S: Send + Clone + BuildHasher,
|
||||
{
|
||||
type Item = (K, V);
|
||||
|
||||
|
@ -114,8 +111,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 {
|
||||
|
@ -124,17 +121,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'a, K, V, S = RandomState> {
|
||||
pub(super) shards: &'a [RwLock<HashMap<K, V, S>>],
|
||||
pub struct Iter<'a, K, V> {
|
||||
pub(super) shards: &'a [RwLock<HashMap<K, V>>],
|
||||
}
|
||||
|
||||
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<C>(self, consumer: C) -> C::Result
|
||||
where
|
||||
|
@ -142,14 +138,12 @@ where
|
|||
{
|
||||
self.shards
|
||||
.into_par_iter()
|
||||
.flat_map_iter(|shard| {
|
||||
let guard = shard.read();
|
||||
let sref: &'a HashMap<K, V, S> = 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)
|
||||
|
@ -157,14 +151,13 @@ where
|
|||
}
|
||||
|
||||
// This impl also enables `IntoParallelRefMutIterator::par_iter_mut`
|
||||
impl<'a, K, V, S> IntoParallelIterator for &'a mut DashMap<K, V, S>
|
||||
impl<'a, K, V> IntoParallelIterator for &'a mut DashMap<K, V>
|
||||
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 {
|
||||
|
@ -177,27 +170,25 @@ impl<K, V, S> DashMap<K, V, S>
|
|||
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 [RwLock<HashMap<K, V, S>>],
|
||||
pub struct IterMut<'a, K, V> {
|
||||
shards: &'a [RwLock<HashMap<K, V>>],
|
||||
}
|
||||
|
||||
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<C>(self, consumer: C) -> C::Result
|
||||
where
|
||||
|
@ -205,15 +196,12 @@ where
|
|||
{
|
||||
self.shards
|
||||
.into_par_iter()
|
||||
.flat_map_iter(|shard| {
|
||||
let mut guard = shard.write();
|
||||
let sref: &'a mut HashMap<K, V, S> =
|
||||
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)
|
||||
|
|
|
@ -10,7 +10,7 @@ where
|
|||
V: Send,
|
||||
S: Send + Clone + BuildHasher,
|
||||
{
|
||||
type Iter = super::map::OwningIter<K, V, S>;
|
||||
type Iter = super::map::OwningIter<K, V>;
|
||||
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 {
|
||||
|
|
|
@ -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<K, S> ParallelExtend<K> for DashSet<K, S>
|
||||
where
|
||||
|
@ -56,7 +55,7 @@ where
|
|||
K: Send + Eq + Hash,
|
||||
S: Send + Clone + BuildHasher,
|
||||
{
|
||||
type Iter = OwningIter<K, S>;
|
||||
type Iter = OwningIter<K>;
|
||||
type Item = K;
|
||||
|
||||
fn into_par_iter(self) -> Self::Iter {
|
||||
|
@ -66,14 +65,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct OwningIter<K, S = RandomState> {
|
||||
inner: super::map::OwningIter<K, (), S>,
|
||||
pub struct OwningIter<K> {
|
||||
inner: super::map::OwningIter<K, ()>,
|
||||
}
|
||||
|
||||
impl<K, S> ParallelIterator for OwningIter<K, S>
|
||||
impl<K> ParallelIterator for OwningIter<K>
|
||||
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<C>(self, consumer: C) -> C::Result
|
||||
where
|
||||
|
|
|
@ -61,13 +61,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
|
|||
K: Borrow<Q>,
|
||||
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.
|
||||
|
@ -76,13 +70,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
|
|||
K: Borrow<Q>,
|
||||
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.
|
||||
|
@ -91,37 +79,39 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
|
|||
K: Borrow<Q>,
|
||||
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<Item = &'a HashMap<K, V, S>> + '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<Item = (&'a K, &'a V)> + '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<Item = &'a K> + '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<Item = &'a V> + 'a {
|
||||
self.shard_read_iter()
|
||||
.flat_map(|shard| shard.values())
|
||||
.map(|v| v.get())
|
||||
self.iter().map(|(_k, v)| v)
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
@ -139,12 +129,12 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S>
|
|||
/// let map = DashMap::<(), ()>::new().into_read_only();
|
||||
/// println!("Amount of shards: {}", map.shards().len());
|
||||
/// ```
|
||||
pub fn shards(&self) -> &[RwLock<HashMap<K, V, S>>] {
|
||||
pub fn shards(&self) -> &[RwLock<HashMap<K, V>>] {
|
||||
&self.map.shards
|
||||
}
|
||||
} else {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn shards(&self) -> &[RwLock<HashMap<K, V, S>>] {
|
||||
pub(crate) fn shards(&self) -> &[RwLock<HashMap<K, V>>] {
|
||||
&self.map.shards
|
||||
}
|
||||
}
|
||||
|
|
28
src/serde.rs
28
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! {}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ impl<'a, K: 'a + Eq + Hash, S: BuildHasher + Clone> DashSet<K, S> {
|
|||
/// let set = DashSet::<()>::new();
|
||||
/// println!("Amount of shards: {}", set.shards().len());
|
||||
/// ```
|
||||
pub fn shards(&self) -> &[RwLock<HashMap<K, (), S>>] {
|
||||
pub fn shards(&self) -> &[RwLock<HashMap<K, ()>>] {
|
||||
self.inner.shards()
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ impl<'a, K: 'a + Eq + Hash, S: BuildHasher + Clone> DashSet<K, S> {
|
|||
/// youtubers.insert("Bosnian Bill");
|
||||
/// assert_eq!(*youtubers.get("Bosnian Bill").unwrap(), "Bosnian Bill");
|
||||
/// ```
|
||||
pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, S>>
|
||||
pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
22
src/t.rs
22
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<K, V, S>;
|
||||
unsafe fn _get_read_shard(&'a self, i: usize) -> &'a HashMap<K, V>;
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The index must not be out of bounds.
|
||||
unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap<K, V, S>>;
|
||||
unsafe fn _yield_read_shard(&'a self, i: usize) -> RwLockReadGuard<'a, HashMap<K, V>>;
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The index must not be out of bounds.
|
||||
unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap<K, V, S>>;
|
||||
unsafe fn _yield_write_shard(&'a self, i: usize) -> RwLockWriteGuard<'a, HashMap<K, V>>;
|
||||
|
||||
/// # 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<RwLockReadGuard<'a, HashMap<K, V, S>>>;
|
||||
) -> Option<RwLockReadGuard<'a, HashMap<K, V>>>;
|
||||
|
||||
/// # 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<RwLockWriteGuard<'a, HashMap<K, V, S>>>;
|
||||
) -> Option<RwLockWriteGuard<'a, HashMap<K, V>>>;
|
||||
|
||||
fn _insert(&self, key: K, value: V) -> Option<V>;
|
||||
|
||||
|
@ -69,22 +69,22 @@ pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> {
|
|||
where
|
||||
Self: Sized;
|
||||
|
||||
fn _get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V, S>>
|
||||
fn _get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized;
|
||||
|
||||
fn _get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V, S>>
|
||||
fn _get_mut<Q>(&'a self, key: &Q) -> Option<RefMut<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized;
|
||||
|
||||
fn _try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V, S>>
|
||||
fn _try_get<Q>(&'a self, key: &Q) -> TryResult<Ref<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
Q: Hash + Eq + ?Sized;
|
||||
|
||||
fn _try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V, S>>
|
||||
fn _try_get_mut<Q>(&'a self, key: &Q) -> TryResult<RefMut<'a, K, V>>
|
||||
where
|
||||
K: Borrow<Q>,
|
||||
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>,
|
||||
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<Entry<'a, K, V, S>>;
|
||||
fn _try_entry(&'a self, key: K) -> Option<Entry<'a, K, V>>;
|
||||
|
||||
fn _hasher(&self) -> S;
|
||||
|
||||
|
|
16
src/util.rs
16
src/util.rs
|
@ -18,22 +18,6 @@ pub fn map_in_place_2<T, U, F: FnOnce(U, T) -> 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
|
||||
|
|
Loading…
Reference in New Issue