mirror of https://github.com/xacrimon/dashmap
Address major issues (#202)
This commit is contained in:
parent
82c2323bc6
commit
fcaa55511a
10
Cargo.toml
10
Cargo.toml
|
@ -13,16 +13,14 @@ keywords = ["atomic", "concurrent", "hashmap"]
|
|||
categories = ["concurrency", "algorithms", "data-structures"]
|
||||
|
||||
[features]
|
||||
default = ["send_guard"]
|
||||
raw-api = []
|
||||
send_guard = ["parking_lot/send_guard"]
|
||||
|
||||
[dependencies]
|
||||
parking_lot = "0.12.0"
|
||||
hashbrown = "0.11.2"
|
||||
lock_api = "0.4.7"
|
||||
hashbrown = "0.12.0"
|
||||
serde = { version = "1.0.136", optional = true, features = ["derive"] }
|
||||
cfg-if = "1.0.0"
|
||||
rayon = { version = "1.5.1", optional = true }
|
||||
rayon = { version = "1.5.2", optional = true }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["rayon", "raw-api", "serde", "send_guard"]
|
||||
features = ["rayon", "raw-api", "serde"]
|
||||
|
|
|
@ -30,8 +30,6 @@ If you have any suggestions or tips do not hesitate to open an issue or a PR.
|
|||
|
||||
- `rayon` - Enables rayon support.
|
||||
|
||||
- `send_guard` - Enables the `send_guard` feature of `parking_lot`, making `Ref*` guards `Send`. This is on by default.
|
||||
|
||||
## Contributing
|
||||
|
||||
DashMap gladly accepts contributions!
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
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 parking_lot::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use std::collections::hash_map::RandomState;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
pub mod iter;
|
||||
pub mod iter_set;
|
||||
mod lock;
|
||||
pub mod mapref;
|
||||
mod read_only;
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -18,6 +19,12 @@ pub mod rayon {
|
|||
pub mod set;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "raw-api"))]
|
||||
use crate::lock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
#[cfg(feature = "raw-api")]
|
||||
pub use crate::lock::{RawRwLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use core::borrow::Borrow;
|
||||
use core::fmt;
|
||||
|
@ -28,7 +35,6 @@ use iter::{Iter, IterMut, OwningIter};
|
|||
use mapref::entry::{Entry, OccupiedEntry, VacantEntry};
|
||||
use mapref::multiple::RefMulti;
|
||||
use mapref::one::{Ref, RefMut};
|
||||
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
pub use read_only::ReadOnlyView;
|
||||
pub use set::DashSet;
|
||||
use std::collections::hash_map::RandomState;
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
use lock_api::GuardSend;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
const EXCLUSIVE_BIT: u32 = 1 << 31;
|
||||
|
||||
pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
|
||||
pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;
|
||||
pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>;
|
||||
|
||||
pub struct RawRwLock {
|
||||
data: AtomicU32,
|
||||
}
|
||||
|
||||
unsafe impl lock_api::RawRwLock for RawRwLock {
|
||||
type GuardMarker = GuardSend;
|
||||
|
||||
#[allow(clippy::declare_interior_mutable_const)]
|
||||
const INIT: Self = RawRwLock {
|
||||
data: AtomicU32::new(0),
|
||||
};
|
||||
|
||||
fn lock_shared(&self) {
|
||||
while !self.try_lock_shared() {}
|
||||
}
|
||||
|
||||
fn try_lock_shared(&self) -> bool {
|
||||
let x = self.data.load(Ordering::SeqCst);
|
||||
if x & EXCLUSIVE_BIT != 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let y = x + 1;
|
||||
self.data
|
||||
.compare_exchange(x, y, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
unsafe fn unlock_shared(&self) {
|
||||
self.data.fetch_sub(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn lock_exclusive(&self) {
|
||||
while !self.try_lock_exclusive() {}
|
||||
}
|
||||
|
||||
fn try_lock_exclusive(&self) -> bool {
|
||||
self.data
|
||||
.compare_exchange(0, EXCLUSIVE_BIT, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
unsafe fn unlock_exclusive(&self) {
|
||||
self.data.store(0, Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn is_locked(&self) -> bool {
|
||||
self.data.load(Ordering::SeqCst) != 0
|
||||
}
|
||||
|
||||
fn is_locked_exclusive(&self) -> bool {
|
||||
self.data.load(Ordering::SeqCst) & EXCLUSIVE_BIT != 0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl lock_api::RawRwLockDowngrade for RawRwLock {
|
||||
unsafe fn downgrade(&self) {
|
||||
self.data.store(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
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::mem;
|
||||
use core::ptr;
|
||||
use parking_lot::RwLockWriteGuard;
|
||||
use std::collections::hash_map::RandomState;
|
||||
|
||||
pub enum Entry<'a, K, V, S = RandomState> {
|
||||
|
@ -89,12 +89,8 @@ pub struct VacantEntry<'a, K, V, S = RandomState> {
|
|||
key: K,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, V: Send, S: BuildHasher> Send for VacantEntry<'a, K, V, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, V: Send + Sync, S: BuildHasher> Sync
|
||||
for VacantEntry<'a, K, V, S>
|
||||
{
|
||||
}
|
||||
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> {}
|
||||
|
||||
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 {
|
||||
|
@ -136,12 +132,8 @@ pub struct OccupiedEntry<'a, K, V, S = RandomState> {
|
|||
key: K,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, V: Send, S: BuildHasher> Send for OccupiedEntry<'a, K, V, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, V: Send + Sync, S: BuildHasher> Sync
|
||||
for OccupiedEntry<'a, K, V, S>
|
||||
{
|
||||
}
|
||||
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> {}
|
||||
|
||||
impl<'a, K: Eq + Hash, V, S: BuildHasher> OccupiedEntry<'a, K, V, S> {
|
||||
pub(crate) unsafe fn new(
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::lock::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use crate::HashMap;
|
||||
use core::hash::BuildHasher;
|
||||
use core::hash::Hash;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use std::collections::hash_map::RandomState;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -12,12 +12,8 @@ pub struct RefMulti<'a, K, V, S = RandomState> {
|
|||
v: *const V,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, V: Send, S: BuildHasher> Send for RefMulti<'a, K, V, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, V: Send + Sync, S: BuildHasher> Sync
|
||||
for RefMulti<'a, K, V, S>
|
||||
{
|
||||
}
|
||||
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> {}
|
||||
|
||||
impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMulti<'a, K, V, S> {
|
||||
pub(crate) unsafe fn new(
|
||||
|
@ -59,12 +55,8 @@ pub struct RefMutMulti<'a, K, V, S = RandomState> {
|
|||
v: *mut V,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, V: Send, S: BuildHasher> Send for RefMutMulti<'a, K, V, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, V: Send + Sync, S: BuildHasher> Sync
|
||||
for RefMutMulti<'a, K, V, S>
|
||||
{
|
||||
}
|
||||
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> {}
|
||||
|
||||
impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMutMulti<'a, K, V, S> {
|
||||
pub(crate) unsafe fn new(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::lock::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use crate::HashMap;
|
||||
use core::hash::{BuildHasher, Hash};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use std::collections::hash_map::RandomState;
|
||||
|
||||
pub struct Ref<'a, K, V, S = RandomState> {
|
||||
|
@ -10,12 +10,8 @@ pub struct Ref<'a, K, V, S = RandomState> {
|
|||
v: *const V,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, V: Send, S: BuildHasher> Send for Ref<'a, K, V, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, V: Send + Sync, S: BuildHasher> Sync
|
||||
for Ref<'a, K, V, S>
|
||||
{
|
||||
}
|
||||
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> {}
|
||||
|
||||
impl<'a, K: Eq + Hash, V, S: BuildHasher> Ref<'a, K, V, S> {
|
||||
pub(crate) unsafe fn new(
|
||||
|
@ -57,12 +53,8 @@ pub struct RefMut<'a, K, V, S = RandomState> {
|
|||
v: *mut V,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, V: Send, S: BuildHasher> Send for RefMut<'a, K, V, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, V: Send + Sync, S: BuildHasher> Sync
|
||||
for RefMut<'a, K, V, S>
|
||||
{
|
||||
}
|
||||
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> {}
|
||||
|
||||
impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMut<'a, K, V, S> {
|
||||
pub(crate) unsafe fn new(
|
||||
|
@ -94,13 +86,7 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> RefMut<'a, K, V, S> {
|
|||
}
|
||||
|
||||
pub fn downgrade(self) -> Ref<'a, K, V, S> {
|
||||
unsafe {
|
||||
Ref::new(
|
||||
parking_lot::RwLockWriteGuard::downgrade(self.guard),
|
||||
self.k,
|
||||
self.v,
|
||||
)
|
||||
}
|
||||
unsafe { Ref::new(RwLockWriteGuard::downgrade(self.guard), self.k, self.v) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::lock::RwLock;
|
||||
use crate::mapref::multiple::{RefMulti, RefMutMulti};
|
||||
use crate::util;
|
||||
use crate::{DashMap, HashMap};
|
||||
use core::hash::{BuildHasher, Hash};
|
||||
use parking_lot::RwLock;
|
||||
use rayon::iter::plumbing::UnindexedConsumer;
|
||||
use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
|
||||
use std::collections::hash_map::RandomState;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::iter_set::{Iter, OwningIter};
|
||||
#[cfg(feature = "raw-api")]
|
||||
use crate::lock::RwLock;
|
||||
use crate::setref::one::Ref;
|
||||
use crate::DashMap;
|
||||
#[cfg(feature = "raw-api")]
|
||||
|
@ -8,8 +10,6 @@ use core::borrow::Borrow;
|
|||
use core::fmt;
|
||||
use core::hash::{BuildHasher, Hash};
|
||||
use core::iter::FromIterator;
|
||||
#[cfg(feature = "raw-api")]
|
||||
use parking_lot::RwLock;
|
||||
use std::collections::hash_map::RandomState;
|
||||
|
||||
/// DashSet is a thin wrapper around [`DashMap`] using `()` as the value type. It uses
|
||||
|
|
|
@ -6,10 +6,6 @@ pub struct Ref<'a, K, S = RandomState> {
|
|||
inner: mapref::one::Ref<'a, K, (), S>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send, S: BuildHasher> Send for Ref<'a, K, S> {}
|
||||
|
||||
unsafe impl<'a, K: Eq + Hash + Send + Sync, S: BuildHasher> Sync for Ref<'a, K, S> {}
|
||||
|
||||
impl<'a, K: Eq + Hash, S: BuildHasher> Ref<'a, K, S> {
|
||||
pub(crate) fn new(inner: mapref::one::Ref<'a, K, (), S>) -> Self {
|
||||
Self { inner }
|
||||
|
|
2
src/t.rs
2
src/t.rs
|
@ -1,13 +1,13 @@
|
|||
//! Central map trait to ease modifications and extensions down the road.
|
||||
|
||||
use crate::iter::{Iter, IterMut};
|
||||
use crate::lock::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use crate::mapref::entry::Entry;
|
||||
use crate::mapref::one::{Ref, RefMut};
|
||||
use crate::try_result::TryResult;
|
||||
use crate::HashMap;
|
||||
use core::borrow::Borrow;
|
||||
use core::hash::{BuildHasher, Hash};
|
||||
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
/// Implementation detail that is exposed due to generic constraints in public types.
|
||||
pub trait Map<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + Clone + BuildHasher> {
|
||||
|
|
Loading…
Reference in New Issue