Skip to content
This repository was archived by the owner on Jan 5, 2026. It is now read-only.

Commit 829f2d3

Browse files
committed
chore(*): minor bucket.rs refactoring
1 parent 48740ba commit 829f2d3

2 files changed

Lines changed: 71 additions & 58 deletions

File tree

src/async_helper.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@ pub(crate) trait TryWait {
3030
fn try_wait(&mut self, lock: &Lock);
3131
}
3232

33-
/// Returns a fake [`Guard`] reference for methods receiving a [`Guard`] only to check the lifetime.
34-
#[inline]
35-
pub(super) const fn fake_guard() -> &'static Guard {
36-
static FAKE_GUARD_GLOBAL: usize = 0;
37-
unsafe { &*ptr::from_ref(&FAKE_GUARD_GLOBAL).cast::<Guard>() }
38-
}
39-
4033
impl AsyncGuard {
4134
/// Returns `true` if the [`AsyncGuard`] contains a valid [`Guard`].
4235
#[inline]

src/hash_table/bucket.rs

Lines changed: 71 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use saa::Lock;
1010
use sdd::{AtomicShared, Shared, Tag};
1111

1212
use 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)]
4848
pub 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)]
5454
pub 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]
12281241
const 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)]
12341254
mod test {

0 commit comments

Comments
 (0)