@@ -10,7 +10,7 @@ use saa::Lock;
1010use sdd:: { AtomicShared , Shared , Tag } ;
1111
1212use crate :: Equivalent ;
13- use crate :: async_helper:: { AsyncGuard , fake_guard } ;
13+ use crate :: async_helper:: AsyncGuard ;
1414
1515/// [`Bucket`] is a lock-protected fixed-size entry array.
1616///
@@ -46,13 +46,13 @@ pub struct DataBlock<K, V, const LEN: usize>([UnsafeCell<MaybeUninit<(K, V)>>; L
4646/// [`Writer`] holds an exclusive lock on a [`Bucket`].
4747#[ derive( Debug ) ]
4848pub struct Writer < K , V , L : LruList , const TYPE : char > {
49- bucket : NonNull < Bucket < K , V , L , TYPE > > ,
49+ bucket_ptr : NonNull < Bucket < K , V , L , TYPE > > ,
5050}
5151
5252/// [`Reader`] holds a shared lock on a [`Bucket`].
5353#[ derive( Debug ) ]
5454pub struct Reader < K , V , L : LruList , const TYPE : char > {
55- bucket : NonNull < Bucket < K , V , L , TYPE > > ,
55+ bucket_ptr : NonNull < Bucket < K , V , L , TYPE > > ,
5656}
5757
5858/// [`EntryPtr`] points to an entry slot in a [`Bucket`].
@@ -164,7 +164,7 @@ impl<K, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
164164 } else {
165165 self . insert_entry (
166166 & self . metadata ,
167- unsafe { data_block . as_ref ( ) } ,
167+ data_block_ref ( data_block ) ,
168168 free_index,
169169 occupied_bitmap,
170170 hash,
@@ -215,7 +215,7 @@ impl<K, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
215215 self . metadata
216216 . occupied_bitmap
217217 . store ( occupied_bitmap & !( 1_u32 << entry_ptr. index ) , Relaxed ) ;
218- Self :: read_data_block ( unsafe { data_block . as_ref ( ) } , entry_ptr. index )
218+ Self :: read_data_block ( data_block_ref ( data_block ) , entry_ptr. index )
219219 }
220220 }
221221
@@ -274,10 +274,7 @@ impl<K, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
274274 self . metadata
275275 . occupied_bitmap
276276 . store ( occupied_bitmap & !( 1_u32 << evicted) , Relaxed ) ;
277- return Some ( Self :: read_data_block (
278- unsafe { data_block. as_ref ( ) } ,
279- evicted,
280- ) ) ;
277+ return Some ( Self :: read_data_block ( data_block_ref ( data_block) , evicted) ) ;
281278 }
282279
283280 None
@@ -346,7 +343,7 @@ impl<K, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
346343 let entry = if let Some ( link) = link_ref ( from_entry_ptr. link_ptr ) {
347344 Self :: read_data_block ( & link. data_block , from_entry_ptr. index )
348345 } else {
349- Self :: read_data_block ( unsafe { from_data_block . as_ref ( ) } , from_entry_ptr. index )
346+ Self :: read_data_block ( data_block_ref ( from_data_block ) , from_entry_ptr. index )
350347 } ;
351348 self . insert ( data_block, hash, entry) ;
352349
@@ -389,7 +386,7 @@ impl<K, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
389386 if occupied_bitmap != 0 {
390387 let mut index = occupied_bitmap. trailing_zeros ( ) ;
391388 while index != 32 {
392- Self :: drop_entry ( unsafe { data_block . as_ref ( ) } , index as usize ) ;
389+ Self :: drop_entry ( data_block_ref ( data_block ) , index as usize ) ;
393390 occupied_bitmap -= 1_u32 << index;
394391 index = occupied_bitmap. trailing_zeros ( ) ;
395392 }
@@ -423,7 +420,7 @@ impl<K, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
423420 }
424421
425422 // Insert a new `LinkedBucket` at the linked list head.
426- let head = self . metadata . link . get_shared ( Relaxed , fake_guard ( ) ) ;
423+ let head = self . metadata . link . get_shared ( Relaxed , fake_ref ( self ) ) ;
427424 let link = unsafe { Shared :: new_unchecked ( LinkedBucket :: new ( head) ) } ;
428425 self . write_cell ( & link. data_block [ 0 ] , |block| unsafe {
429426 block. as_mut_ptr ( ) . write ( entry) ;
@@ -558,7 +555,7 @@ impl<K: Eq, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
558555 {
559556 if self . len ( ) != 0 {
560557 if let Some ( ( entry, _) ) =
561- Self :: search_data_block ( & self . metadata , unsafe { data_block . as_ref ( ) } , key, hash)
558+ Self :: search_data_block ( & self . metadata , data_block_ref ( data_block ) , key, hash)
562559 {
563560 return Some ( entry) ;
564561 }
@@ -592,7 +589,7 @@ impl<K: Eq, V, L: LruList, const TYPE: char> Bucket<K, V, L, TYPE> {
592589 {
593590 if self . len ( ) != 0 {
594591 if let Some ( ( _, index) ) =
595- Self :: search_data_block ( & self . metadata , unsafe { data_block . as_ref ( ) } , key, hash)
592+ Self :: search_data_block ( & self . metadata , data_block_ref ( data_block ) , key, hash)
596593 {
597594 return EntryPtr {
598595 link_ptr : ptr:: null ( ) ,
@@ -718,7 +715,7 @@ impl<K, V, L: LruList, const TYPE: char> Writer<K, V, L, TYPE> {
718715 #[ inline]
719716 pub ( crate ) const fn from_bucket ( bucket : & Bucket < K , V , L , TYPE > ) -> Writer < K , V , L , TYPE > {
720717 Writer {
721- bucket : unsafe { NonNull :: new_unchecked ( from_ref ( bucket) . cast_mut ( ) ) } ,
718+ bucket_ptr : bucket_ptr ( bucket) ,
722719 }
723720 }
724721
@@ -761,7 +758,7 @@ impl<K, V, L: LruList, const TYPE: char> Deref for Writer<K, V, L, TYPE> {
761758
762759 #[ inline]
763760 fn deref ( & self ) -> & Self :: Target {
764- unsafe { self . bucket . as_ref ( ) }
761+ unsafe { self . bucket_ptr . as_ref ( ) }
765762 }
766763}
767764
@@ -793,7 +790,7 @@ impl<'g, K, V, L: LruList, const TYPE: char> Reader<K, V, L, TYPE> {
793790 // The `bucket` was not killed, and will not be killed until the `Reader` is dropped.
794791 // This guarantees that the `BucketArray` will survive as long as the `Reader` is alive.
795792 Some ( Reader {
796- bucket : unsafe { NonNull :: new_unchecked ( from_ref ( bucket) . cast_mut ( ) ) } ,
793+ bucket_ptr : bucket_ptr ( bucket) ,
797794 } )
798795 } else {
799796 None
@@ -807,7 +804,7 @@ impl<'g, K, V, L: LruList, const TYPE: char> Reader<K, V, L, TYPE> {
807804 pub ( crate ) fn lock_sync ( bucket : & Bucket < K , V , L , TYPE > ) -> Option < Reader < K , V , L , TYPE > > {
808805 if bucket. rw_lock . share_sync ( ) {
809806 Some ( Reader {
810- bucket : unsafe { NonNull :: new_unchecked ( from_ref ( bucket) . cast_mut ( ) ) } ,
807+ bucket_ptr : bucket_ptr ( bucket) ,
811808 } )
812809 } else {
813810 None
@@ -819,7 +816,7 @@ impl<'g, K, V, L: LruList, const TYPE: char> Reader<K, V, L, TYPE> {
819816 pub ( crate ) fn try_lock ( bucket : & Bucket < K , V , L , TYPE > ) -> Option < Reader < K , V , L , TYPE > > {
820817 if bucket. rw_lock . try_share ( ) {
821818 Some ( Reader {
822- bucket : unsafe { NonNull :: new_unchecked ( from_ref ( bucket) . cast_mut ( ) ) } ,
819+ bucket_ptr : bucket_ptr ( bucket) ,
823820 } )
824821 } else {
825822 None
@@ -832,7 +829,7 @@ impl<K, V, L: LruList, const TYPE: char> Deref for Reader<K, V, L, TYPE> {
832829
833830 #[ inline]
834831 fn deref ( & self ) -> & Self :: Target {
835- unsafe { self . bucket . as_ref ( ) }
832+ unsafe { self . bucket_ptr . as_ref ( ) }
836833 }
837834}
838835
@@ -877,39 +874,18 @@ impl<K, V, const TYPE: char> EntryPtr<K, V, TYPE> {
877874 }
878875 }
879876
880- /// Moves the [`EntryPtr`] to point to the next occupied entry.
881- ///
882- /// Returns `true` if it successfully found the next occupied entry.
883- #[ inline]
884- pub ( crate ) fn move_to_next < L : LruList > ( & mut self , bucket : & Bucket < K , V , L , TYPE > ) -> bool {
885- if self . index != usize:: MAX {
886- if self . link_ptr . is_null ( ) && self . next_entry :: < L , BUCKET_LEN > ( & bucket. metadata ) {
887- return true ;
888- }
889- while let Some ( link) = link_ref ( self . link_ptr ) {
890- if self . next_entry :: < L , LINKED_BUCKET_LEN > ( & link. metadata ) {
891- return true ;
892- }
893- }
894-
895- // Fuse itself.
896- self . index = usize:: MAX ;
897- }
898-
899- false
900- }
901-
902877 /// Gets a reference to the entry.
903878 ///
904879 /// The [`EntryPtr`] must point to a valid entry.
905880 #[ inline]
906- pub ( crate ) fn get < ' e > ( & self , data_block : NonNull < DataBlock < K , V , BUCKET_LEN > > ) -> & ' e ( K , V ) {
907- debug_assert_ne ! ( self . index, usize :: MAX ) ;
908-
881+ pub ( crate ) const fn get < ' e > (
882+ & self ,
883+ data_block : NonNull < DataBlock < K , V , BUCKET_LEN > > ,
884+ ) -> & ' e ( K , V ) {
909885 let entry_ptr = if let Some ( link) = link_ref ( self . link_ptr ) {
910886 Bucket :: < K , V , ( ) , TYPE > :: entry_ptr ( & link. data_block , self . index )
911887 } else {
912- Bucket :: < K , V , ( ) , TYPE > :: entry_ptr ( unsafe { data_block . as_ref ( ) } , self . index )
888+ Bucket :: < K , V , ( ) , TYPE > :: entry_ptr ( data_block_ref ( data_block ) , self . index )
913889 } ;
914890 unsafe { & ( * entry_ptr) }
915891 }
@@ -918,21 +894,41 @@ impl<K, V, const TYPE: char> EntryPtr<K, V, TYPE> {
918894 ///
919895 /// The associated [`Bucket`] must be locked, and the [`EntryPtr`] must point to a valid entry.
920896 #[ inline]
921- pub ( crate ) fn get_mut < L : LruList > (
897+ pub ( crate ) const fn get_mut < L : LruList > (
922898 & mut self ,
923899 data_block : NonNull < DataBlock < K , V , BUCKET_LEN > > ,
924900 _writer : & Writer < K , V , L , TYPE > ,
925901 ) -> & mut ( K , V ) {
926- debug_assert_ne ! ( self . index, usize :: MAX ) ;
927-
928902 let entry_ptr = if let Some ( link) = link_ref ( self . link_ptr ) {
929903 Bucket :: < K , V , L , TYPE > :: entry_mut_ptr ( & link. data_block , self . index )
930904 } else {
931- Bucket :: < K , V , L , TYPE > :: entry_mut_ptr ( unsafe { data_block . as_ref ( ) } , self . index )
905+ Bucket :: < K , V , L , TYPE > :: entry_mut_ptr ( data_block_ref ( data_block ) , self . index )
932906 } ;
933907 unsafe { & mut ( * entry_ptr) }
934908 }
935909
910+ /// Moves the [`EntryPtr`] to point to the next occupied entry.
911+ ///
912+ /// Returns `true` if it successfully found the next occupied entry.
913+ #[ inline]
914+ pub ( crate ) fn move_to_next < L : LruList > ( & mut self , bucket : & Bucket < K , V , L , TYPE > ) -> bool {
915+ if self . index != usize:: MAX {
916+ if self . link_ptr . is_null ( ) && self . next_entry :: < L , BUCKET_LEN > ( & bucket. metadata ) {
917+ return true ;
918+ }
919+ while let Some ( link) = link_ref ( self . link_ptr ) {
920+ if self . next_entry :: < L , LINKED_BUCKET_LEN > ( & link. metadata ) {
921+ return true ;
922+ }
923+ }
924+
925+ // Fuse itself.
926+ self . index = usize:: MAX ;
927+ }
928+
929+ false
930+ }
931+
936932 /// Unlinks the [`LinkedBucket`] currently pointed to by this [`EntryPtr`] from the linked list.
937933 ///
938934 /// The associated [`Bucket`] must be locked.
@@ -1171,7 +1167,7 @@ impl<K, V, const LEN: usize> Metadata<K, V, LEN> {
11711167 /// Loads the linked bucket pointer.
11721168 #[ inline]
11731169 fn load_link ( & self ) -> * const LinkedBucket < K , V > {
1174- unsafe { self . link . load ( Acquire , fake_guard ( ) ) . as_ptr_unchecked ( ) }
1170+ unsafe { self . link . load ( Acquire , fake_ref ( & self ) ) . as_ptr_unchecked ( ) }
11751171 }
11761172}
11771173
@@ -1224,11 +1220,35 @@ impl<K, V> Drop for LinkedBucket<K, V> {
12241220 }
12251221}
12261222
1223+ /// Returns a pointer to a bucket.
1224+ #[ inline]
1225+ const fn bucket_ptr < K , V , L : LruList , const TYPE : char > (
1226+ bucket : & Bucket < K , V , L , TYPE > ,
1227+ ) -> NonNull < Bucket < K , V , L , TYPE > > {
1228+ unsafe { NonNull :: new_unchecked ( from_ref ( bucket) . cast_mut ( ) ) }
1229+ }
1230+
1231+ /// Returns a reference to the data block.
1232+ #[ inline]
1233+ const fn data_block_ref < ' l , K , V , const LEN : usize > (
1234+ data_block_ptr : NonNull < DataBlock < K , V , LEN > > ,
1235+ ) -> & ' l DataBlock < K , V , LEN > {
1236+ unsafe { data_block_ptr. as_ref ( ) }
1237+ }
1238+
12271239/// Returns a reference to the linked bucket that the pointer might point to.
1240+ #[ inline]
12281241const fn link_ref < ' l , K , V > ( ptr : * const LinkedBucket < K , V > ) -> Option < & ' l LinkedBucket < K , V > > {
12291242 unsafe { ptr. as_ref ( ) }
12301243}
12311244
1245+ /// Returns a fake reference for passing a reference to `U` when it is ensured that the returned
1246+ /// reference is never used.
1247+ #[ inline]
1248+ const fn fake_ref < ' l , T , U > ( v : & T ) -> & ' l U {
1249+ unsafe { & * ptr:: from_ref ( v) . cast :: < U > ( ) }
1250+ }
1251+
12321252#[ cfg( not( feature = "loom" ) ) ]
12331253#[ cfg( test) ]
12341254mod test {
0 commit comments