@@ -27,6 +27,9 @@ use crate::lock::RwLock;
27
27
28
28
#[ cfg( feature = "raw-api" ) ]
29
29
pub use crate :: lock:: { RawRwLock , RwLock } ;
30
+ use crate :: mapref:: entry_ref:: EntryRef ;
31
+ use crate :: mapref:: entry_ref:: OccupiedEntryRef ;
32
+ use crate :: mapref:: entry_ref:: VacantEntryRef ;
30
33
31
34
use cfg_if:: cfg_if;
32
35
use core:: fmt;
@@ -889,6 +892,17 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
889
892
self . _try_entry ( key)
890
893
}
891
894
895
+ /// Advanced entry API that tries to mimic `hashbrown::HashMap::entry_ref`.
896
+ /// See the documentation on `dashmap::mapref::entry_ref` for more details.
897
+ ///
898
+ /// **Locking behaviour:** May deadlock if called when holding any sort of reference into the map.
899
+ pub fn entry_ref < ' q , Q > ( & ' a self , key : & ' q Q ) -> EntryRef < ' a , ' q , K , Q , V >
900
+ where
901
+ Q : Hash + Equivalent < K > ,
902
+ {
903
+ self . _entry_ref ( key)
904
+ }
905
+
892
906
/// Advanced entry API that tries to mimic `std::collections::HashMap::try_reserve`.
893
907
/// Tries to reserve capacity for at least `shard * additional`
894
908
/// and may reserve more space to avoid frequent reallocations.
@@ -1182,6 +1196,69 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> DashMap<K, V, S>
1182
1196
}
1183
1197
}
1184
1198
1199
+ fn _entry_ref < ' q , Q > ( & ' a self , key : & ' q Q ) -> EntryRef < ' a , ' q , K , Q , V >
1200
+ where
1201
+ Q : Hash + Equivalent < K > ,
1202
+ {
1203
+ let hash = self . hash_u64 ( & key) ;
1204
+
1205
+ let idx = self . determine_shard ( hash as usize ) ;
1206
+
1207
+ let shard = self . shards [ idx] . write ( ) ;
1208
+ // SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
1209
+ let ( guard, shard) = unsafe { RwLockWriteGuardDetached :: detach_from ( shard) } ;
1210
+
1211
+ match shard. entry (
1212
+ hash,
1213
+ |( k, _v) | key. equivalent ( k) ,
1214
+ |( k, _v) | {
1215
+ let mut hasher = self . hasher . build_hasher ( ) ;
1216
+ k. hash ( & mut hasher) ;
1217
+ hasher. finish ( )
1218
+ } ,
1219
+ ) {
1220
+ hash_table:: Entry :: Occupied ( entry) => {
1221
+ EntryRef :: Occupied ( OccupiedEntryRef :: new ( guard, key, entry) )
1222
+ }
1223
+ hash_table:: Entry :: Vacant ( entry) => {
1224
+ EntryRef :: Vacant ( VacantEntryRef :: new ( guard, key, entry) )
1225
+ }
1226
+ }
1227
+ }
1228
+
1229
+ fn _try_entry_ref < ' q , Q > ( & ' a self , key : & ' q Q ) -> Option < EntryRef < ' a , ' q , K , Q , V > >
1230
+ where
1231
+ Q : Hash + Equivalent < K > ,
1232
+ {
1233
+ let hash = self . hash_u64 ( & key) ;
1234
+
1235
+ let idx = self . determine_shard ( hash as usize ) ;
1236
+
1237
+ let shard = match self . shards [ idx] . try_write ( ) {
1238
+ Some ( shard) => shard,
1239
+ None => return None ,
1240
+ } ;
1241
+ // SAFETY: The data will not outlive the guard, since we pass the guard to `Entry`.
1242
+ let ( guard, shard) = unsafe { RwLockWriteGuardDetached :: detach_from ( shard) } ;
1243
+
1244
+ match shard. entry (
1245
+ hash,
1246
+ |( k, _v) | key. equivalent ( k) ,
1247
+ |( k, _v) | {
1248
+ let mut hasher = self . hasher . build_hasher ( ) ;
1249
+ k. hash ( & mut hasher) ;
1250
+ hasher. finish ( )
1251
+ } ,
1252
+ ) {
1253
+ hash_table:: Entry :: Occupied ( entry) => {
1254
+ Some ( EntryRef :: Occupied ( OccupiedEntryRef :: new ( guard, key, entry) ) )
1255
+ }
1256
+ hash_table:: Entry :: Vacant ( entry) => {
1257
+ Some ( EntryRef :: Vacant ( VacantEntryRef :: new ( guard, key, entry) ) )
1258
+ }
1259
+ }
1260
+ }
1261
+
1185
1262
fn _clear ( & self ) {
1186
1263
self . _retain ( |_, _| false )
1187
1264
}
0 commit comments