Compare commits

...

17 Commits

Author SHA1 Message Date
Joel Wejdenstål 626b98dab3
v5.5.3 2023-08-29 23:13:21 +02:00
Joel 1e7efe5843
bump msrv to 1.65 (#279) 2023-08-29 23:12:11 +02:00
Joel Wejdenstål eff796d46b
v5.5.2 2023-08-29 13:17:51 +02:00
Joel Wejdenstål febc45dc62
Revert "Only hash keys once, taking advantage of hashbrown raw entry api (#259)"
This reverts commit 3448b6f070.
2023-08-29 13:17:03 +02:00
Joel Wejdenstål dfb7b9af33
v5.5.1 2023-08-22 02:06:11 +02:00
Joel Wejdenstål 3b26d70d2f
commit lockfile 2023-08-22 02:05:50 +02:00
Joel Wejdenstål 71a1dc6cd8
rename toolchain file 2023-08-22 02:01:56 +02:00
Joel Wejdenstål 8364d3e48e
fix lint 2023-08-22 02:00:33 +02:00
Arthur Silva 3448b6f070
Only hash keys once, taking advantage of hashbrown raw entry api (#259) 2023-08-22 01:57:35 +02:00
Joel Wejdenstål ea4ea24a63
v5.5.0 2023-07-11 06:11:45 +02:00
Joel 018f0a1671
assert that the shard count is not 1 (#273)
* assert that the shard count is not 1

* lint
2023-07-11 05:39:27 +02:00
Joel Wejdenstål 6616a8d28c
fmt 2023-07-11 05:30:00 +02:00
Tobias Kahlert 3b418466ed
Entry insert (#226)
* added Entry::insert_entry

* added Entry::insert
2023-07-11 05:29:24 +02:00
Amin Yahyaabadi 079faeb02b
feat: implement Display and AsRef for MappedRef (#261) 2023-07-11 05:24:05 +02:00
Jan dcc97f8ddb
Implement `Serialize` for reference types (#264) 2023-07-11 05:21:26 +02:00
Joel 4c7568cce6
add support for arbitrary (#272) 2023-07-11 05:20:05 +02:00
Joel d36311e634
update deps & toolchain to stable-1.64 (#271) 2023-07-11 04:56:54 +02:00
15 changed files with 510 additions and 22 deletions

View File

@ -4,7 +4,7 @@ on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: style
@ -13,7 +13,7 @@ jobs:
run: cargo clippy --all-targets --all-features -- -D warnings
test:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
strategy:
matrix:
target: [

1
.gitignore vendored
View File

@ -1,3 +1,2 @@
/target
**/*.rs.bk
Cargo.lock

311
Cargo.lock generated Normal file
View File

@ -0,0 +1,311 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arbitrary"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if",
]
[[package]]
name = "dashmap"
version = "5.5.3"
dependencies = [
"arbitrary",
"cfg-if",
"hashbrown",
"lock_api",
"once_cell",
"parking_lot_core",
"rayon",
"serde",
]
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "hermit-abi"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "lock_api"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "memoffset"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "parking_lot_core"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "syn"
version = "2.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

View File

@ -1,9 +1,9 @@
[package]
name = "dashmap"
version = "5.4.0"
version = "5.5.3"
authors = ["Acrimon <joel.wejdenstal@gmail.com>"]
edition = "2018"
rust-version = "1.59"
rust-version = "1.65"
license = "MIT"
repository = "https://github.com/xacrimon/dashmap"
homepage = "https://github.com/xacrimon/dashmap"
@ -18,13 +18,14 @@ raw-api = []
inline = ["hashbrown/inline-more"]
[dependencies]
lock_api = "0.4.8"
parking_lot_core = "0.9.3"
hashbrown = { version = "0.12.3", default-features = false }
serde = { version = "1.0.144", optional = true, features = ["derive"] }
lock_api = "0.4.10"
parking_lot_core = "0.9.8"
hashbrown = { version = "0.14.0", default-features = false }
serde = { version = "1.0.188", optional = true, features = ["derive"] }
cfg-if = "1.0.0"
rayon = { version = "1.5.3", optional = true }
once_cell = "1.13.1"
rayon = { version = "1.7.0", optional = true }
once_cell = "1.18.0"
arbitrary = { version = "1.3.0", optional = true }
[package.metadata.docs.rs]
features = ["rayon", "raw-api", "serde"]

View File

@ -20,7 +20,7 @@ If you have any suggestions or tips do not hesitate to open an issue or a PR.
[![downloads](https://img.shields.io/crates/d/dashmap)](https://crates.io/crates/dashmap)
[![minimum rustc version](https://img.shields.io/badge/rustc-1.59-orange.svg)](https://crates.io/crates/dashmap)
[![minimum rustc version](https://img.shields.io/badge/rustc-1.65-orange.svg)](https://crates.io/crates/dashmap)
## Cargo features
@ -32,6 +32,8 @@ If you have any suggestions or tips do not hesitate to open an issue or a PR.
- `inline` - Enables `inline-more` feature from the `hashbrown` crate. Can lead to better performance, but with the cost of longer compile-time.
- `arbitrary` - Enables support for the `arbitrary` crate.
## Contributing
DashMap gladly accepts contributions!

View File

@ -1,4 +0,0 @@
[toolchain]
channel = "1.59"
components = [ "rustfmt", "clippy" ]
profile = "minimal"

4
rust-toolchain.toml Normal file
View File

@ -0,0 +1,4 @@
[toolchain]
channel = "1.65"
components = ["rustfmt", "clippy"]
profile = "minimal"

13
src/arbitrary.rs Normal file
View File

@ -0,0 +1,13 @@
use arbitrary::{Arbitrary, Unstructured};
use core::hash::BuildHasher;
impl<'a, K, V, S> Arbitrary<'a> for crate::DashMap<K, V, S>
where
K: Eq + std::hash::Hash + Arbitrary<'a>,
V: Arbitrary<'a>,
S: Default + BuildHasher + Clone,
{
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary_iter()?.collect()
}
}

View File

@ -118,7 +118,7 @@ pub struct Iter<'a, K, V, S = RandomState, M = DashMap<K, V, S>> {
current: Option<GuardIter<'a, K, V, S>>,
}
impl<'a, 'i, K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for Iter<'i, K, V, S> {
impl<'i, K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for Iter<'i, K, V, S> {
fn clone(&self) -> Self {
Iter::new(self.map)
}

View File

@ -1,5 +1,7 @@
#![allow(clippy::type_complexity)]
#[cfg(feature = "arbitrary")]
mod arbitrary;
pub mod iter;
pub mod iter_set;
mod lock;
@ -268,7 +270,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
hasher: S,
shard_amount: usize,
) -> Self {
assert!(shard_amount > 0);
assert!(shard_amount > 1);
assert!(shard_amount.is_power_of_two());
let shift = util::ptr_size_bits() - ncb(shard_amount);
@ -1263,7 +1265,7 @@ where
}
}
impl<'a, K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for DashMap<K, V, S> {
impl<K: Eq + Hash, V, S: BuildHasher + Clone> IntoIterator for DashMap<K, V, S> {
type Item = (K, V);
type IntoIter = OwningIter<K, V, S>;

View File

@ -82,6 +82,36 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> Entry<'a, K, V, S> {
Entry::Vacant(entry) => Ok(entry.insert(value()?)),
}
}
/// 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> {
match self {
Entry::Occupied(mut entry) => {
entry.insert(value);
entry.into_ref()
}
Entry::Vacant(entry) => entry.insert(value),
}
}
/// Sets the value of the entry, and returns an OccupiedEntry.
///
/// If you are not interested in the occupied entry,
/// 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>
where
K: Clone,
{
match self {
Entry::Occupied(mut entry) => {
entry.insert(value);
entry
}
Entry::Vacant(entry) => entry.insert_entry(value),
}
}
}
pub struct VacantEntry<'a, K, V, S = RandomState> {
@ -117,6 +147,22 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> VacantEntry<'a, K, V, S> {
}
}
/// Sets the value of the entry with the VacantEntrys key, and returns an OccupiedEntry.
pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V, S>
where
K: Clone,
{
unsafe {
self.shard.insert(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))
}
}
pub fn into_key(self) -> K {
self.key
}
@ -187,3 +233,46 @@ impl<'a, K: Eq + Hash, V, S: BuildHasher> OccupiedEntry<'a, K, V, S> {
(k, v.into_inner())
}
}
#[cfg(test)]
mod tests {
use crate::DashMap;
use super::*;
#[test]
fn test_insert_entry_into_vacant() {
let map: DashMap<u32, u32> = DashMap::new();
let entry = map.entry(1);
assert!(matches!(entry, Entry::Vacant(_)));
let entry = entry.insert_entry(2);
assert_eq!(*entry.get(), 2);
drop(entry);
assert_eq!(*map.get(&1).unwrap(), 2);
}
#[test]
fn test_insert_entry_into_occupied() {
let map: DashMap<u32, u32> = DashMap::new();
map.insert(1, 1000);
let entry = map.entry(1);
assert!(matches!(&entry, Entry::Occupied(entry) if *entry.get() == 1000));
let entry = entry.insert_entry(2);
assert_eq!(*entry.get(), 2);
drop(entry);
assert_eq!(*map.get(&1).unwrap(), 2);
}
}

View File

@ -241,6 +241,20 @@ impl<'a, K: Eq + Hash, V, T, S: BuildHasher> Deref for MappedRef<'a, K, V, T, S>
}
}
impl<'a, K: Eq + Hash, V, T: std::fmt::Display> std::fmt::Display for MappedRef<'a, K, V, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.value(), f)
}
}
impl<'a, K: Eq + Hash, V, T: AsRef<TDeref>, TDeref: ?Sized> AsRef<TDeref>
for MappedRef<'a, K, V, T>
{
fn as_ref(&self) -> &TDeref {
self.value().as_ref()
}
}
pub struct MappedRefMut<'a, K, V, T, S = RandomState> {
_guard: RwLockWriteGuard<'a, HashMap<K, V, S>>,
k: *const K,

View File

@ -173,7 +173,7 @@ where
}
}
impl<'a, K, V, S> DashMap<K, V, S>
impl<K, V, S> DashMap<K, V, S>
where
K: Send + Sync + Eq + Hash,
V: Send + Sync,

View File

@ -1,4 +1,4 @@
use crate::{DashMap, DashSet};
use crate::{mapref, setref, DashMap, DashSet};
use core::fmt;
use core::hash::{BuildHasher, Hash};
use core::marker::PhantomData;
@ -156,3 +156,60 @@ where
seq.end()
}
}
macro_rules! serialize_impl {
() => {
fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where
Ser: serde::Serializer,
{
std::ops::Deref::deref(self).serialize(serializer)
}
};
}
// Map
impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize
for mapref::multiple::RefMulti<'a, K, V, S>
{
serialize_impl! {}
}
impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize
for mapref::multiple::RefMutMulti<'a, K, V, S>
{
serialize_impl! {}
}
impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize for mapref::one::Ref<'a, K, V, S> {
serialize_impl! {}
}
impl<'a, K: Eq + Hash, V: Serialize, S: BuildHasher> Serialize
for mapref::one::RefMut<'a, K, V, S>
{
serialize_impl! {}
}
impl<'a, K: Eq + Hash, V, T: Serialize, S: BuildHasher> Serialize
for mapref::one::MappedRef<'a, K, V, T, S>
{
serialize_impl! {}
}
impl<'a, K: Eq + Hash, V, T: Serialize, S: BuildHasher> Serialize
for mapref::one::MappedRefMut<'a, K, V, T, S>
{
serialize_impl! {}
}
// Set
impl<'a, V: Hash + Eq + Serialize, S: BuildHasher> Serialize
for setref::multiple::RefMulti<'a, V, S>
{
serialize_impl! {}
}
impl<'a, V: Hash + Eq + Serialize, S: BuildHasher> Serialize for setref::one::Ref<'a, V, S> {
serialize_impl! {}
}

View File

@ -385,7 +385,7 @@ impl<'a, K: 'a + Eq + Hash, S: BuildHasher + Clone> DashSet<K, S> {
}
}
impl<'a, K: Eq + Hash, S: BuildHasher + Clone> IntoIterator for DashSet<K, S> {
impl<K: Eq + Hash, S: BuildHasher + Clone> IntoIterator for DashSet<K, S> {
type Item = K;
type IntoIter = OwningIter<K, S>;