Skip to content

Commit 54710a6

Browse files
committed
Merge branch 'hashbrown-0.15' (324)
2 parents 7fb4eb4 + 46005cb commit 54710a6

File tree

7 files changed

+74
-120
lines changed

7 files changed

+74
-120
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ inline = ["hashbrown/inline-more"]
2121
[dependencies]
2222
lock_api = "0.4.10"
2323
parking_lot_core = "0.9.8"
24-
hashbrown = { version = "0.14.0", default-features = false, features = ["raw"] }
24+
hashbrown = { version = "0.15.1", default-features = false }
2525
serde = { version = "1.0.188", optional = true, features = ["derive"] }
2626
cfg-if = "1.0.0"
2727
rayon = { version = "1.7.0", optional = true }

src/iter.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use hashbrown::hash_table;
2+
13
use super::mapref::multiple::{RefMulti, RefMutMulti};
24
use crate::lock::{RwLockReadGuardDetached, RwLockWriteGuardDetached};
35
use crate::t::Map;
@@ -37,7 +39,7 @@ impl<K: Eq + Hash, V, S: BuildHasher + Clone> OwningIter<K, V, S> {
3739
}
3840
}
3941

40-
type GuardOwningIter<K, V> = hashbrown::raw::RawIntoIter<(K, V)>;
42+
type GuardOwningIter<K, V> = hash_table::IntoIter<(K, V)>;
4143

4244
impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for OwningIter<K, V, S> {
4345
type Item = (K, V);
@@ -71,12 +73,12 @@ impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for OwningIter<K, V, S> {
7173

7274
type GuardIter<'a, K, V> = (
7375
Arc<RwLockReadGuardDetached<'a>>,
74-
hashbrown::raw::RawIter<(K, V)>,
76+
hash_table::Iter<'a, (K, V)>,
7577
);
7678

7779
type GuardIterMut<'a, K, V> = (
7880
Arc<RwLockWriteGuardDetached<'a>>,
79-
hashbrown::raw::RawIter<(K, V)>,
81+
hash_table::IterMut<'a, (K, V)>,
8082
);
8183

8284
/// Iterator over a DashMap yielding immutable references.
@@ -124,9 +126,8 @@ impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V,
124126
fn next(&mut self) -> Option<Self::Item> {
125127
loop {
126128
if let Some(current) = self.current.as_mut() {
127-
if let Some(b) = current.1.next() {
129+
if let Some((k, v)) = current.1.next() {
128130
return unsafe {
129-
let (k, v) = b.as_ref();
130131
let guard = current.0.clone();
131132
Some(RefMulti::new(guard, k, v))
132133
};
@@ -142,7 +143,7 @@ impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V,
142143
// and with any refs produced by the iterator
143144
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(guard) };
144145

145-
let iter = unsafe { shard.iter() };
146+
let iter = shard.iter();
146147

147148
self.current = Some((Arc::new(guard), iter));
148149

@@ -191,9 +192,8 @@ impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V,
191192
fn next(&mut self) -> Option<Self::Item> {
192193
loop {
193194
if let Some(current) = self.current.as_mut() {
194-
if let Some(b) = current.1.next() {
195+
if let Some((k, v)) = current.1.next() {
195196
return unsafe {
196-
let (k, v) = b.as_mut();
197197
let guard = current.0.clone();
198198
Some(RefMutMulti::new(guard, k, v))
199199
};
@@ -210,7 +210,7 @@ impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V,
210210
// and with any refs produced by the iterator
211211
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(guard) };
212212

213-
let iter = unsafe { shard.iter() };
213+
let iter = shard.iter_mut();
214214

215215
self.current = Some((Arc::new(guard), iter));
216216

@@ -234,7 +234,7 @@ mod tests {
234234
let mut c = 0;
235235

236236
for shard in map.shards() {
237-
c += unsafe { shard.write().iter().count() };
237+
c += shard.write().iter().count();
238238
}
239239

240240
assert_eq!(c, 1);

src/lib.rs

Lines changed: 36 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use core::hash::{BuildHasher, Hash, Hasher};
3535
use core::iter::FromIterator;
3636
use core::ops::{BitAnd, BitOr, Shl, Shr, Sub};
3737
use crossbeam_utils::CachePadded;
38+
use hashbrown::hash_table;
3839
use iter::{Iter, IterMut, OwningIter};
3940
use lock::{RwLockReadGuardDetached, RwLockWriteGuardDetached};
4041
pub use mapref::entry::{Entry, OccupiedEntry, VacantEntry};
@@ -47,7 +48,7 @@ use std::collections::hash_map::RandomState;
4748
pub use t::Map;
4849
use try_result::TryResult;
4950

50-
pub(crate) type HashMap<K, V> = hashbrown::raw::RawTable<(K, V)>;
51+
pub(crate) type HashMap<K, V> = hash_table::HashTable<(K, V)>;
5152

5253
// Temporary reimplementation of [`std::collections::TryReserveError`]
5354
// util [`std::collections::TryReserveError`] stabilises.
@@ -336,7 +337,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
336337
/// };
337338
/// let data = (42, "forty two");
338339
/// let hash = hasher(&data);
339-
/// map.shards_mut()[shard_ind].get_mut().insert(hash, data, hasher);
340+
/// map.shards_mut()[shard_ind].get_mut().insert_unique(hash, data, hasher);
340341
/// assert_eq!(*map.get(&42).unwrap(), "forty two");
341342
/// ```
342343
pub fn shards_mut(&mut self) -> &mut [CachePadded<RwLock<HashMap<K, V>>>] {
@@ -955,8 +956,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
955956

956957
let mut shard = unsafe { self._yield_write_shard(idx) };
957958

958-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
959-
let ((k, v), _) = unsafe { shard.remove(bucket) };
959+
if let Ok(entry) = shard.find_entry(hash, |(k, _v)| key == k.borrow()) {
960+
let ((k, v), _) = entry.remove();
960961
Some((k, v))
961962
} else {
962963
None
@@ -974,10 +975,10 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
974975

975976
let mut shard = unsafe { self._yield_write_shard(idx) };
976977

977-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
978-
let (k, v) = unsafe { bucket.as_ref() };
978+
if let Ok(entry) = shard.find_entry(hash, |(k, _v)| key == k.borrow()) {
979+
let (k, v) = entry.get();
979980
if f(k, v) {
980-
let ((k, v), _) = unsafe { shard.remove(bucket) };
981+
let ((k, v), _) = entry.remove();
981982
Some((k, v))
982983
} else {
983984
None
@@ -998,10 +999,10 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
998999

9991000
let mut shard = unsafe { self._yield_write_shard(idx) };
10001001

1001-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1002-
let (k, v) = unsafe { bucket.as_mut() };
1002+
if let Ok(mut entry) = shard.find_entry(hash, |(k, _v)| key == k.borrow()) {
1003+
let (k, v) = entry.get_mut();
10031004
if f(k, v) {
1004-
let ((k, v), _) = unsafe { shard.remove(bucket) };
1005+
let ((k, v), _) = entry.remove();
10051006
Some((k, v))
10061007
} else {
10071008
None
@@ -1032,11 +1033,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10321033
// SAFETY: The data will not outlive the guard, since we pass the guard to `Ref`.
10331034
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(shard) };
10341035

1035-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1036-
unsafe {
1037-
let (k, v) = bucket.as_ref();
1038-
Some(Ref::new(guard, k, v))
1039-
}
1036+
if let Some((k, v)) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1037+
unsafe { Some(Ref::new(guard, k, v)) }
10401038
} else {
10411039
None
10421040
}
@@ -1055,11 +1053,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10551053
// SAFETY: The data will not outlive the guard, since we pass the guard to `RefMut`.
10561054
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
10571055

1058-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1059-
unsafe {
1060-
let (k, v) = bucket.as_mut();
1061-
Some(RefMut::new(guard, k, v))
1062-
}
1056+
if let Some((k, v)) = shard.find_mut(hash, |(k, _v)| key == k.borrow()) {
1057+
unsafe { Some(RefMut::new(guard, k, v)) }
10631058
} else {
10641059
None
10651060
}
@@ -1081,11 +1076,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10811076
// SAFETY: The data will not outlive the guard, since we pass the guard to `Ref`.
10821077
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(shard) };
10831078

1084-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1085-
unsafe {
1086-
let (k, v) = bucket.as_ref();
1087-
TryResult::Present(Ref::new(guard, k, v))
1088-
}
1079+
if let Some((k, v)) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1080+
unsafe { TryResult::Present(Ref::new(guard, k, v)) }
10891081
} else {
10901082
TryResult::Absent
10911083
}
@@ -1107,11 +1099,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11071099
// SAFETY: The data will not outlive the guard, since we pass the guard to `RefMut`.
11081100
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
11091101

1110-
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
1111-
unsafe {
1112-
let (k, v) = bucket.as_mut();
1113-
TryResult::Present(RefMut::new(guard, k, v))
1114-
}
1102+
if let Some((k, v)) = shard.find_mut(hash, |(k, _v)| key == k.borrow()) {
1103+
unsafe { TryResult::Present(RefMut::new(guard, k, v)) }
11151104
} else {
11161105
TryResult::Absent
11171106
}
@@ -1131,16 +1120,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11311120

11321121
fn _retain(&self, mut f: impl FnMut(&K, &mut V) -> bool) {
11331122
self.shards.iter().for_each(|s| {
1134-
unsafe {
1135-
let mut shard = s.write();
1136-
// Here we only use `iter` as a temporary, preventing use-after-free
1137-
for bucket in shard.iter() {
1138-
let (k, v) = bucket.as_mut();
1139-
if !f(&*k, v) {
1140-
shard.erase(bucket);
1141-
}
1142-
}
1143-
}
1123+
s.write().retain(|(k, v)| f(k, v));
11441124
});
11451125
}
11461126

@@ -1187,7 +1167,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11871167
// SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
11881168
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
11891169

1190-
match shard.find_or_find_insert_slot(
1170+
match shard.entry(
11911171
hash,
11921172
|(k, _v)| k == &key,
11931173
|(k, _v)| {
@@ -1196,8 +1176,12 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11961176
hasher.finish()
11971177
},
11981178
) {
1199-
Ok(elem) => Entry::Occupied(unsafe { OccupiedEntry::new(guard, key, shard, elem) }),
1200-
Err(slot) => Entry::Vacant(unsafe { VacantEntry::new(guard, key, hash, shard, slot) }),
1179+
hash_table::Entry::Occupied(entry) => {
1180+
Entry::Occupied(unsafe { OccupiedEntry::new(guard, key, entry) })
1181+
}
1182+
hash_table::Entry::Vacant(entry) => {
1183+
Entry::Vacant(unsafe { VacantEntry::new(guard, key, entry) })
1184+
}
12011185
}
12021186
}
12031187

@@ -1213,7 +1197,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
12131197
// SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
12141198
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
12151199

1216-
match shard.find_or_find_insert_slot(
1200+
match shard.entry(
12171201
hash,
12181202
|(k, _v)| k == &key,
12191203
|(k, _v)| {
@@ -1222,11 +1206,11 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
12221206
hasher.finish()
12231207
},
12241208
) {
1225-
Ok(elem) => Some(Entry::Occupied(unsafe {
1226-
OccupiedEntry::new(guard, key, shard, elem)
1209+
hash_table::Entry::Occupied(entry) => Some(Entry::Occupied(unsafe {
1210+
OccupiedEntry::new(guard, key, entry)
12271211
})),
1228-
Err(slot) => Some(Entry::Vacant(unsafe {
1229-
VacantEntry::new(guard, key, hash, shard, slot)
1212+
hash_table::Entry::Vacant(entry) => Some(Entry::Vacant(unsafe {
1213+
VacantEntry::new(guard, key, entry)
12301214
})),
12311215
}
12321216
}
@@ -1359,15 +1343,12 @@ where
13591343
.iter()
13601344
.map(|shard_lock| {
13611345
let shard = shard_lock.read();
1362-
let hashtable_size = shard.allocation_info().1.size();
1346+
let hashtable_size = shard.allocation_size();
13631347

13641348
// Safety: The iterator is dropped before the HashTable
1365-
let iter = unsafe { shard.iter() };
1366-
let entry_size_iter = iter.map(|bucket| {
1367-
// Safety: The iterator returns buckets with valid pointers to entries
1368-
let (key, value) = unsafe { bucket.as_ref() };
1369-
key.extra_size() + value.extra_size()
1370-
});
1349+
let iter = shard.iter();
1350+
let entry_size_iter =
1351+
iter.map(|(key, value)| key.extra_size() + value.extra_size());
13711352

13721353
core::mem::size_of::<CachePadded<RwLock<HashMap<K, V>>>>()
13731354
+ hashtable_size

0 commit comments

Comments
 (0)