Skip to content

Commit 7fb4eb4

Browse files
committed
Merge branch 'conradludgate-rwlock-detached' (#323)
2 parents c8c936c + 22bd6af commit 7fb4eb4

File tree

10 files changed

+244
-221
lines changed

10 files changed

+244
-221
lines changed

src/iter.rs

Lines changed: 18 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::mapref::multiple::{RefMulti, RefMutMulti};
2-
use crate::lock::{RwLockReadGuard, RwLockWriteGuard};
2+
use crate::lock::{RwLockReadGuardDetached, RwLockWriteGuardDetached};
33
use crate::t::Map;
4-
use crate::{DashMap, HashMap};
4+
use crate::DashMap;
55
use core::hash::{BuildHasher, Hash};
66
use core::mem;
77
use std::collections::hash_map::RandomState;
@@ -69,29 +69,13 @@ impl<K: Eq + Hash, V, S: BuildHasher + Clone> Iterator for OwningIter<K, V, S> {
6969
}
7070
}
7171

72-
unsafe impl<K, V, S> Send for OwningIter<K, V, S>
73-
where
74-
K: Eq + Hash + Send,
75-
V: Send,
76-
S: BuildHasher + Clone + Send,
77-
{
78-
}
79-
80-
unsafe impl<K, V, S> Sync for OwningIter<K, V, S>
81-
where
82-
K: Eq + Hash + Sync,
83-
V: Sync,
84-
S: BuildHasher + Clone + Sync,
85-
{
86-
}
87-
8872
type GuardIter<'a, K, V> = (
89-
Arc<RwLockReadGuard<'a, HashMap<K, V>>>,
73+
Arc<RwLockReadGuardDetached<'a>>,
9074
hashbrown::raw::RawIter<(K, V)>,
9175
);
9276

9377
type GuardIterMut<'a, K, V> = (
94-
Arc<RwLockWriteGuard<'a, HashMap<K, V>>>,
78+
Arc<RwLockWriteGuardDetached<'a>>,
9579
hashbrown::raw::RawIter<(K, V)>,
9680
);
9781

@@ -119,25 +103,9 @@ impl<'i, K: Clone + Hash + Eq, V: Clone, S: Clone + BuildHasher> Clone for Iter<
119103
}
120104
}
121105

122-
unsafe impl<'a, 'i, K, V, S, M> Send for Iter<'i, K, V, S, M>
123-
where
124-
K: 'a + Eq + Hash + Send,
125-
V: 'a + Send,
126-
S: 'a + BuildHasher + Clone,
127-
M: Map<'a, K, V, S>,
128-
{
129-
}
130-
131-
unsafe impl<'a, 'i, K, V, S, M> Sync for Iter<'i, K, V, S, M>
132-
where
133-
K: 'a + Eq + Hash + Sync,
134-
V: 'a + Sync,
135-
S: 'a + BuildHasher + Clone,
136-
M: Map<'a, K, V, S>,
106+
impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>>
107+
Iter<'a, K, V, S, M>
137108
{
138-
}
139-
140-
impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter<'a, K, V, S, M> {
141109
pub(crate) fn new(map: &'a M) -> Self {
142110
Self {
143111
map,
@@ -148,7 +116,7 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter
148116
}
149117
}
150118

151-
impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iterator
119+
impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iterator
152120
for Iter<'a, K, V, S, M>
153121
{
154122
type Item = RefMulti<'a, K, V>;
@@ -170,8 +138,11 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter
170138
}
171139

172140
let guard = unsafe { self.map._yield_read_shard(self.shard_i) };
141+
// SAFETY: we keep the guard alive with the shard iterator,
142+
// and with any refs produced by the iterator
143+
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(guard) };
173144

174-
let iter = unsafe { guard.iter() };
145+
let iter = unsafe { shard.iter() };
175146

176147
self.current = Some((Arc::new(guard), iter));
177148

@@ -199,25 +170,7 @@ pub struct IterMut<'a, K, V, S = RandomState, M = DashMap<K, V, S>> {
199170
marker: PhantomData<S>,
200171
}
201172

202-
unsafe impl<'a, 'i, K, V, S, M> Send for IterMut<'i, K, V, S, M>
203-
where
204-
K: 'a + Eq + Hash + Send,
205-
V: 'a + Send,
206-
S: 'a + BuildHasher + Clone,
207-
M: Map<'a, K, V, S>,
208-
{
209-
}
210-
211-
unsafe impl<'a, 'i, K, V, S, M> Sync for IterMut<'i, K, V, S, M>
212-
where
213-
K: 'a + Eq + Hash + Sync,
214-
V: 'a + Sync,
215-
S: 'a + BuildHasher + Clone,
216-
M: Map<'a, K, V, S>,
217-
{
218-
}
219-
220-
impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>>
173+
impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>>
221174
IterMut<'a, K, V, S, M>
222175
{
223176
pub(crate) fn new(map: &'a M) -> Self {
@@ -230,7 +183,7 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>>
230183
}
231184
}
232185

233-
impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iterator
186+
impl<'a, K: Eq + Hash + 'a, V: 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iterator
234187
for IterMut<'a, K, V, S, M>
235188
{
236189
type Item = RefMutMulti<'a, K, V>;
@@ -253,7 +206,11 @@ impl<'a, K: Eq + Hash, V, S: 'a + BuildHasher + Clone, M: Map<'a, K, V, S>> Iter
253206

254207
let guard = unsafe { self.map._yield_write_shard(self.shard_i) };
255208

256-
let iter = unsafe { guard.iter() };
209+
// SAFETY: we keep the guard alive with the shard iterator,
210+
// and with any refs produced by the iterator
211+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(guard) };
212+
213+
let iter = unsafe { shard.iter() };
257214

258215
self.current = Some((Arc::new(guard), iter));
259216

src/iter_set.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,47 +20,17 @@ impl<K: Eq + Hash, S: BuildHasher + Clone> Iterator for OwningIter<K, S> {
2020
}
2121
}
2222

23-
unsafe impl<K, S> Send for OwningIter<K, S>
24-
where
25-
K: Eq + Hash + Send,
26-
S: BuildHasher + Clone + Send,
27-
{
28-
}
29-
30-
unsafe impl<K, S> Sync for OwningIter<K, S>
31-
where
32-
K: Eq + Hash + Sync,
33-
S: BuildHasher + Clone + Sync,
34-
{
35-
}
36-
3723
pub struct Iter<'a, K, S, M> {
3824
inner: crate::iter::Iter<'a, K, (), S, M>,
3925
}
4026

41-
unsafe impl<'a, 'i, K, S, M> Send for Iter<'i, K, S, M>
42-
where
43-
K: 'a + Eq + Hash + Send,
44-
S: 'a + BuildHasher + Clone,
45-
M: Map<'a, K, (), S>,
46-
{
47-
}
48-
49-
unsafe impl<'a, 'i, K, S, M> Sync for Iter<'i, K, S, M>
50-
where
51-
K: 'a + Eq + Hash + Sync,
52-
S: 'a + BuildHasher + Clone,
53-
M: Map<'a, K, (), S>,
54-
{
55-
}
56-
57-
impl<'a, K: Eq + Hash, S: 'a + BuildHasher + Clone, M: Map<'a, K, (), S>> Iter<'a, K, S, M> {
27+
impl<'a, K: Eq + Hash + 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, (), S>> Iter<'a, K, S, M> {
5828
pub(crate) fn new(inner: crate::iter::Iter<'a, K, (), S, M>) -> Self {
5929
Self { inner }
6030
}
6131
}
6232

63-
impl<'a, K: Eq + Hash, S: 'a + BuildHasher + Clone, M: Map<'a, K, (), S>> Iterator
33+
impl<'a, K: Eq + Hash + 'a, S: 'a + BuildHasher + Clone, M: Map<'a, K, (), S>> Iterator
6434
for Iter<'a, K, S, M>
6535
{
6636
type Item = RefMulti<'a, K>;

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};
@@ -1028,11 +1029,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10281029
let idx = self.determine_shard(hash as usize);
10291030

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

10321035
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
10331036
unsafe {
10341037
let (k, v) = bucket.as_ref();
1035-
Some(Ref::new(shard, k, v))
1038+
Some(Ref::new(guard, k, v))
10361039
}
10371040
} else {
10381041
None
@@ -1049,11 +1052,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10491052
let idx = self.determine_shard(hash as usize);
10501053

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

10531058
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
10541059
unsafe {
10551060
let (k, v) = bucket.as_mut();
1056-
Some(RefMut::new(shard, k, v))
1061+
Some(RefMut::new(guard, k, v))
10571062
}
10581063
} else {
10591064
None
@@ -1073,11 +1078,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10731078
Some(shard) => shard,
10741079
None => return TryResult::Locked,
10751080
};
1081+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Ref`.
1082+
let (guard, shard) = unsafe { RwLockReadGuardDetached::detach_from(shard) };
10761083

10771084
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
10781085
unsafe {
10791086
let (k, v) = bucket.as_ref();
1080-
TryResult::Present(Ref::new(shard, k, v))
1087+
TryResult::Present(Ref::new(guard, k, v))
10811088
}
10821089
} else {
10831090
TryResult::Absent
@@ -1097,11 +1104,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
10971104
Some(shard) => shard,
10981105
None => return TryResult::Locked,
10991106
};
1107+
// SAFETY: The data will not outlive the guard, since we pass the guard to `RefMut`.
1108+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
11001109

11011110
if let Some(bucket) = shard.find(hash, |(k, _v)| key == k.borrow()) {
11021111
unsafe {
11031112
let (k, v) = bucket.as_mut();
1104-
TryResult::Present(RefMut::new(shard, k, v))
1113+
TryResult::Present(RefMut::new(guard, k, v))
11051114
}
11061115
} else {
11071116
TryResult::Absent
@@ -1174,7 +1183,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11741183

11751184
let idx = self.determine_shard(hash as usize);
11761185

1177-
let mut shard = unsafe { self._yield_write_shard(idx) };
1186+
let shard = unsafe { self._yield_write_shard(idx) };
1187+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
1188+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
11781189

11791190
match shard.find_or_find_insert_slot(
11801191
hash,
@@ -1185,8 +1196,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11851196
hasher.finish()
11861197
},
11871198
) {
1188-
Ok(elem) => Entry::Occupied(unsafe { OccupiedEntry::new(shard, key, elem) }),
1189-
Err(slot) => Entry::Vacant(unsafe { VacantEntry::new(shard, key, hash, slot) }),
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) }),
11901201
}
11911202
}
11921203

@@ -1195,10 +1206,12 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
11951206

11961207
let idx = self.determine_shard(hash as usize);
11971208

1198-
let mut shard = match unsafe { self._try_yield_write_shard(idx) } {
1209+
let shard = match unsafe { self._try_yield_write_shard(idx) } {
11991210
Some(shard) => shard,
12001211
None => return None,
12011212
};
1213+
// SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
1214+
let (guard, shard) = unsafe { RwLockWriteGuardDetached::detach_from(shard) };
12021215

12031216
match shard.find_or_find_insert_slot(
12041217
hash,
@@ -1210,10 +1223,10 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
12101223
},
12111224
) {
12121225
Ok(elem) => Some(Entry::Occupied(unsafe {
1213-
OccupiedEntry::new(shard, key, elem)
1226+
OccupiedEntry::new(guard, key, shard, elem)
12141227
})),
12151228
Err(slot) => Some(Entry::Vacant(unsafe {
1216-
VacantEntry::new(shard, key, hash, slot)
1229+
VacantEntry::new(guard, key, hash, shard, slot)
12171230
})),
12181231
}
12191232
}

src/lock.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use parking_lot_core::{ParkToken, SpinWait, UnparkToken};
44
pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
55
pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;
66
pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>;
7+
pub(crate) type RwLockReadGuardDetached<'a> = crate::util::RwLockReadGuardDetached<'a, RawRwLock>;
8+
pub(crate) type RwLockWriteGuardDetached<'a> = crate::util::RwLockWriteGuardDetached<'a, RawRwLock>;
79

810
const READERS_PARKED: usize = 0b0001;
911
const WRITERS_PARKED: usize = 0b0010;
@@ -20,7 +22,7 @@ unsafe impl lock_api::RawRwLock for RawRwLock {
2022
state: AtomicUsize::new(0),
2123
};
2224

23-
type GuardMarker = lock_api::GuardNoSend;
25+
type GuardMarker = lock_api::GuardSend;
2426

2527
#[inline]
2628
fn try_lock_exclusive(&self) -> bool {

0 commit comments

Comments
 (0)