Skip to content

Commit d2b5073

Browse files
committed
switch to using detached guards
1 parent 9535936 commit d2b5073

File tree

5 files changed

+103
-86
lines changed

5 files changed

+103
-86
lines changed

src/lib.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use core::iter::FromIterator;
3636
use core::ops::{BitAnd, BitOr, Shl, Shr, Sub};
3737
use crossbeam_utils::CachePadded;
3838
use iter::{Iter, IterMut, OwningIter};
39+
use lock::{RwLockReadGuardDetached, RwLockWriteGuardDetached};
3940
pub use mapref::entry::{Entry, OccupiedEntry, VacantEntry};
4041
use mapref::multiple::RefMulti;
4142
use mapref::one::{Ref, RefMut};
@@ -1032,11 +1033,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10321033
let idx = self.determine_shard(hash as usize);
10331034

10341035
let shard = unsafe { self._yield_read_shard(idx) };
1036+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Ref`.
1037+
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(shard) };
10351038

10361039
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
10371040
unsafe {
10381041
let (k, v) = bucket.as_ref();
1039-
Some(Ref::new(shard, k, v))
1042+
Some(Ref::new(guard, k, v))
10401043
}
10411044
} else {
10421045
None
@@ -1053,11 +1056,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10531056
let idx = self.determine_shard(hash as usize);
10541057

10551058
let shard = unsafe { self._yield_write_shard(idx) };
1059+
// SAFETY: The data will not outlive the guard, since we pass the guard to `RefMut`.
1060+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
10561061

10571062
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
10581063
unsafe {
10591064
let (k, v) = bucket.as_mut();
1060-
Some(RefMut::new(shard, k, v))
1065+
Some(RefMut::new(guard, k, v))
10611066
}
10621067
} else {
10631068
None
@@ -1077,11 +1082,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10771082
Some(shard) => shard,
10781083
None => return TryResult::Locked,
10791084
};
1085+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Ref`.
1086+
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(shard) };
10801087

10811088
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
10821089
unsafe {
10831090
let (k, v) = bucket.as_ref();
1084-
TryResult::Present(Ref::new(shard, k, v))
1091+
TryResult::Present(Ref::new(guard, k, v))
10851092
}
10861093
} else {
10871094
TryResult::Absent
@@ -1101,11 +1108,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11011108
Some(shard) => shard,
11021109
None => return TryResult::Locked,
11031110
};
1111+
// SAFETY: The data will not outlive the guard, since we pass the guard to `RefMut`.
1112+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
11041113

11051114
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
11061115
unsafe {
11071116
let (k, v) = bucket.as_mut();
1108-
TryResult::Present(RefMut::new(shard, k, v))
1117+
TryResult::Present(RefMut::new(guard, k, v))
11091118
}
11101119
} else {
11111120
TryResult::Absent
@@ -1178,7 +1187,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11781187

11791188
let idx = self.determine_shard(hash as usize);
11801189

1181-
let mut shard = unsafe { self._yield_write_shard(idx) };
1190+
let shard = unsafe { self._yield_write_shard(idx) };
1191+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
1192+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
11821193

11831194
match shard.find_or_find_insert_slot(
11841195
hash,
@@ -1189,8 +1200,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11891200
hasher.finish()
11901201
},
11911202
) {
1192-
Ok(elem) => Entry::Occupied(unsafe { OccupiedEntry::new(shard, key, elem) }),
1193-
Err(slot) => Entry::Vacant(unsafe { VacantEntry::new(shard, key, hash, slot) }),
1203+
Ok(elem) => Entry::Occupied(unsafe { OccupiedEntry::new(guard, key, shard, elem) }),
1204+
Err(slot) => Entry::Vacant(unsafe { VacantEntry::new(guard, key, hash, shard, slot) }),
11941205
}
11951206
}
11961207

@@ -1199,10 +1210,12 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11991210

12001211
let idx = self.determine_shard(hash as usize);
12011212

1202-
let mut shard = match unsafe { self._try_yield_write_shard(idx) } {
1213+
let shard = match unsafe { self._try_yield_write_shard(idx) } {
12031214
Some(shard) => shard,
12041215
None => return None,
12051216
};
1217+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
1218+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
12061219

12071220
match shard.find_or_find_insert_slot(
12081221
hash,
@@ -1214,10 +1227,10 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
12141227
},
12151228
) {
12161229
Ok(elem) => Some(Entry::Occupied(unsafe {
1217-
OccupiedEntry::new(shard, key, elem)
1230+
OccupiedEntry::new(guard, key, shard, elem)
12181231
})),
12191232
Err(slot) => Some(Entry::Vacant(unsafe {
1220-
VacantEntry::new(shard, key, hash, slot)
1233+
VacantEntry::new(guard, key, hash, shard, slot)
12211234
})),
12221235
}
12231236
}

src/mapref/entry.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::one::RefMut;
2-
use crate::lock::RwLockWriteGuard;
2+
use crate::lock::RwLockWriteGuardDetached;
33
use crate::HashMap;
44
use core::hash::Hash;
55
use core::mem;
@@ -111,9 +111,10 @@ impl<'a, K: Eq + Hash, V> Entry<'a, K, V> {
111111
}
112112

113113
pub struct VacantEntry<'a, K, V> {
114-
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
114+
shard: RwLockWriteGuardDetached<'a>,
115115
key: K,
116116
hash: u64,
117+
map: &'a mut HashMap<K, V>,
117118
slot: hashbrown::raw::InsertSlot,
118119
}
119120

@@ -122,23 +123,25 @@ unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for VacantEntry<'a, K, V> {}
122123

123124
impl<'a, K: Eq + Hash, V> VacantEntry<'a, K, V> {
124125
pub(crate) unsafe fn new(
125-
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
126+
shard: RwLockWriteGuardDetached<'a>,
126127
key: K,
127128
hash: u64,
129+
map: &'a mut HashMap<K, V>,
128130
slot: hashbrown::raw::InsertSlot,
129131
) -> Self {
130132
Self {
131133
shard,
132134
key,
133135
hash,
136+
map,
134137
slot,
135138
}
136139
}
137140

138-
pub fn insert(mut self, value: V) -> RefMut<'a, K, V> {
141+
pub fn insert(self, value: V) -> RefMut<'a, K, V> {
139142
unsafe {
140143
let occupied = self
141-
.shard
144+
.map
142145
.insert_in_slot(self.hash, self.slot, (self.key, value));
143146

144147
let (k, v) = occupied.as_mut();
@@ -148,16 +151,16 @@ impl<'a, K: Eq + Hash, V> VacantEntry<'a, K, V> {
148151
}
149152

150153
/// Sets the value of the entry with the VacantEntry’s key, and returns an OccupiedEntry.
151-
pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V>
154+
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V>
152155
where
153156
K: Clone,
154157
{
155158
unsafe {
156159
let bucket = self
157-
.shard
160+
.map
158161
.insert_in_slot(self.hash, self.slot, (self.key.clone(), value));
159162

160-
OccupiedEntry::new(self.shard, self.key, bucket)
163+
OccupiedEntry::new(self.shard, self.key, self.map, bucket)
161164
}
162165
}
163166

@@ -171,7 +174,8 @@ impl<'a, K: Eq + Hash, V> VacantEntry<'a, K, V> {
171174
}
172175

173176
pub struct OccupiedEntry<'a, K, V> {
174-
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
177+
shard: RwLockWriteGuardDetached<'a>,
178+
map: &'a mut HashMap<K, V>,
175179
bucket: hashbrown::raw::Bucket<(K, V)>,
176180
key: K,
177181
}
@@ -181,11 +185,17 @@ unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for OccupiedEntry<'a, K, V> {
181185

182186
impl<'a, K: Eq + Hash, V> OccupiedEntry<'a, K, V> {
183187
pub(crate) unsafe fn new(
184-
shard: RwLockWriteGuard<'a, HashMap<K, V>>,
188+
shard: RwLockWriteGuardDetached<'a>,
185189
key: K,
190+
map: &'a mut HashMap<K, V>,
186191
bucket: hashbrown::raw::Bucket<(K, V)>,
187192
) -> Self {
188-
Self { shard, bucket, key }
193+
Self {
194+
shard,
195+
map,
196+
bucket,
197+
key,
198+
}
189199
}
190200

191201
pub fn get(&self) -> &V {
@@ -215,13 +225,13 @@ impl<'a, K: Eq + Hash, V> OccupiedEntry<'a, K, V> {
215225
unsafe { &self.bucket.as_ref().0 }
216226
}
217227

218-
pub fn remove(mut self) -> V {
219-
let ((_k, v), _) = unsafe { self.shard.remove(self.bucket) };
228+
pub fn remove(self) -> V {
229+
let ((_k, v), _) = unsafe { self.map.remove(self.bucket) };
220230
v
221231
}
222232

223-
pub fn remove_entry(mut self) -> (K, V) {
224-
let ((k, v), _) = unsafe { self.shard.remove(self.bucket) };
233+
pub fn remove_entry(self) -> (K, V) {
234+
let ((k, v), _) = unsafe { self.map.remove(self.bucket) };
225235
(k, v)
226236
}
227237

0 commit comments

Comments
 (0)