Skip to content

Commit a59c169

Browse files
committed
Add RawTable#is_full
There's currently no way to tell if a particular bucket is full. This can be handy for choosing a random element or iterating over a hash table in a specific order of buckets, so I've added the is_full function to RawTable.
1 parent 1d2c1a8 commit a59c169

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

src/raw/mod.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
796796
{
797797
let index = self.bucket_index(&bucket);
798798
let old_ctrl = *self.table.ctrl(index);
799-
debug_assert!(is_full(old_ctrl));
799+
debug_assert!(self.is_full(index));
800800
let old_growth_left = self.table.growth_left;
801801
let item = self.remove(bucket);
802802
if let Some(new_item) = f(item) {
@@ -928,6 +928,12 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
928928
self.table.bucket_mask + 1
929929
}
930930

931+
/// Checks whether the bucket at `index` is full.
932+
#[inline]
933+
pub fn is_full(&self, index: usize) -> bool {
934+
self.table.is_full(index)
935+
}
936+
931937
/// Returns an iterator over every element in the table. It is up to
932938
/// the caller to ensure that the `RawTable` outlives the `RawIter`.
933939
/// Because we cannot make the `next` method unsafe on the `RawIter`
@@ -1148,7 +1154,7 @@ impl<A: Allocator + Clone> RawTableInner<A> {
11481154
// table. This second scan is guaranteed to find an empty
11491155
// slot (due to the load factor) before hitting the trailing
11501156
// control bytes (containing EMPTY).
1151-
if unlikely(is_full(*self.ctrl(result))) {
1157+
if unlikely(self.is_full(result)) {
11521158
debug_assert!(self.bucket_mask < Group::WIDTH);
11531159
debug_assert_ne!(probe_seq.pos, 0);
11541160
return Group::load_aligned(self.ctrl(0))
@@ -1329,6 +1335,13 @@ impl<A: Allocator + Clone> RawTableInner<A> {
13291335
self.bucket_mask + 1
13301336
}
13311337

1338+
/// Checks whether the bucket at `index` is full.
1339+
#[inline]
1340+
fn is_full(&self, index: usize) -> bool {
1341+
debug_assert!(index < self.buckets());
1342+
is_full(unsafe { *self.ctrl(index) })
1343+
}
1344+
13321345
#[inline]
13331346
fn num_ctrl_bytes(&self) -> usize {
13341347
self.bucket_mask + 1 + Group::WIDTH
@@ -1427,7 +1440,7 @@ impl<A: Allocator + Clone> RawTableInner<A> {
14271440

14281441
// Copy all elements to the new table.
14291442
for i in 0..self.buckets() {
1430-
if !is_full(*self.ctrl(i)) {
1443+
if !self.is_full(i) {
14311444
continue;
14321445
}
14331446

@@ -1572,7 +1585,7 @@ impl<A: Allocator + Clone> RawTableInner<A> {
15721585

15731586
#[inline]
15741587
unsafe fn erase(&mut self, index: usize) {
1575-
debug_assert!(is_full(*self.ctrl(index)));
1588+
debug_assert!(self.is_full(index));
15761589
let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
15771590
let empty_before = Group::load(self.ctrl(index_before)).match_empty();
15781591
let empty_after = Group::load(self.ctrl(index)).match_empty();
@@ -1722,7 +1735,7 @@ impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
17221735
let mut guard = guard((0, &mut *self), |(index, self_)| {
17231736
if mem::needs_drop::<T>() && !self_.is_empty() {
17241737
for i in 0..=*index {
1725-
if is_full(*self_.table.ctrl(i)) {
1738+
if self_.is_full(i) {
17261739
self_.bucket(i).drop();
17271740
}
17281741
}

0 commit comments

Comments
 (0)