@@ -27,6 +27,9 @@ use crate::lock::RwLock;
2727
2828#[ cfg( feature = "raw-api" ) ]
2929pub 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 ;
3033
3134use cfg_if:: cfg_if;
3235use core:: fmt;
@@ -889,6 +892,17 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
889892 self . _try_entry ( key)
890893 }
891894
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+
892906 /// Advanced entry API that tries to mimic `std::collections::HashMap::try_reserve`.
893907 /// Tries to reserve capacity for at least `shard * additional`
894908 /// 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>
11821196 }
11831197 }
11841198
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+
11851262 fn _clear ( & self ) {
11861263 self . _retain ( |_, _| false )
11871264 }
0 commit comments