@@ -36,6 +36,7 @@ use core::iter::FromIterator;
36
36
use core:: ops:: { BitAnd , BitOr , Shl , Shr , Sub } ;
37
37
use crossbeam_utils:: CachePadded ;
38
38
use iter:: { Iter , IterMut , OwningIter } ;
39
+ use lock:: { RwLockReadGuardDetached , RwLockWriteGuardDetached } ;
39
40
pub use mapref:: entry:: { Entry , OccupiedEntry , VacantEntry } ;
40
41
use mapref:: multiple:: RefMulti ;
41
42
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>
1032
1033
let idx = self . determine_shard ( hash as usize ) ;
1033
1034
1034
1035
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) } ;
1035
1038
1036
1039
if let Some ( bucket) = shard. find ( hash, |( k, _v) | key == k. borrow ( ) ) {
1037
1040
unsafe {
1038
1041
let ( k, v) = bucket. as_ref ( ) ;
1039
- Some ( Ref :: new ( shard , k, v) )
1042
+ Some ( Ref :: new ( guard , k, v) )
1040
1043
}
1041
1044
} else {
1042
1045
None
@@ -1053,11 +1056,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1053
1056
let idx = self . determine_shard ( hash as usize ) ;
1054
1057
1055
1058
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) } ;
1056
1061
1057
1062
if let Some ( bucket) = shard. find ( hash, |( k, _v) | key == k. borrow ( ) ) {
1058
1063
unsafe {
1059
1064
let ( k, v) = bucket. as_mut ( ) ;
1060
- Some ( RefMut :: new ( shard , k, v) )
1065
+ Some ( RefMut :: new ( guard , k, v) )
1061
1066
}
1062
1067
} else {
1063
1068
None
@@ -1077,11 +1082,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1077
1082
Some ( shard) => shard,
1078
1083
None => return TryResult :: Locked ,
1079
1084
} ;
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) } ;
1080
1087
1081
1088
if let Some ( bucket) = shard. find ( hash, |( k, _v) | key == k. borrow ( ) ) {
1082
1089
unsafe {
1083
1090
let ( k, v) = bucket. as_ref ( ) ;
1084
- TryResult :: Present ( Ref :: new ( shard , k, v) )
1091
+ TryResult :: Present ( Ref :: new ( guard , k, v) )
1085
1092
}
1086
1093
} else {
1087
1094
TryResult :: Absent
@@ -1101,11 +1108,13 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1101
1108
Some ( shard) => shard,
1102
1109
None => return TryResult :: Locked ,
1103
1110
} ;
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) } ;
1104
1113
1105
1114
if let Some ( bucket) = shard. find ( hash, |( k, _v) | key == k. borrow ( ) ) {
1106
1115
unsafe {
1107
1116
let ( k, v) = bucket. as_mut ( ) ;
1108
- TryResult :: Present ( RefMut :: new ( shard , k, v) )
1117
+ TryResult :: Present ( RefMut :: new ( guard , k, v) )
1109
1118
}
1110
1119
} else {
1111
1120
TryResult :: Absent
@@ -1178,7 +1187,9 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1178
1187
1179
1188
let idx = self . determine_shard ( hash as usize ) ;
1180
1189
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) } ;
1182
1193
1183
1194
match shard. find_or_find_insert_slot (
1184
1195
hash,
@@ -1189,8 +1200,8 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1189
1200
hasher. finish ( )
1190
1201
} ,
1191
1202
) {
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) } ) ,
1194
1205
}
1195
1206
}
1196
1207
@@ -1199,10 +1210,12 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1199
1210
1200
1211
let idx = self . determine_shard ( hash as usize ) ;
1201
1212
1202
- let mut shard = match unsafe { self . _try_yield_write_shard ( idx) } {
1213
+ let shard = match unsafe { self . _try_yield_write_shard ( idx) } {
1203
1214
Some ( shard) => shard,
1204
1215
None => return None ,
1205
1216
} ;
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) } ;
1206
1219
1207
1220
match shard. find_or_find_insert_slot (
1208
1221
hash,
@@ -1214,10 +1227,10 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
1214
1227
} ,
1215
1228
) {
1216
1229
Ok ( elem) => Some ( Entry :: Occupied ( unsafe {
1217
- OccupiedEntry :: new ( shard , key, elem)
1230
+ OccupiedEntry :: new ( guard , key, shard , elem)
1218
1231
} ) ) ,
1219
1232
Err ( slot) => Some ( Entry :: Vacant ( unsafe {
1220
- VacantEntry :: new ( shard , key, hash, slot)
1233
+ VacantEntry :: new ( guard , key, hash, shard , slot)
1221
1234
} ) ) ,
1222
1235
}
1223
1236
}
0 commit comments