Skip to content

Commit 18a9e0b

Browse files
committed
POC for outlined RawTable
1 parent 89c331f commit 18a9e0b

File tree

3 files changed

+32
-48
lines changed

3 files changed

+32
-48
lines changed

src/raw/generic.rs

-16
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,6 @@ impl Group {
5353
/// Number of bytes in the group.
5454
pub const WIDTH: usize = mem::size_of::<Self>();
5555

56-
/// Returns a full group of empty bytes, suitable for use as the initial
57-
/// value for an empty hash table.
58-
///
59-
/// This is guaranteed to be aligned to the group size.
60-
#[inline]
61-
pub const fn static_empty() -> &'static [u8] {
62-
union AlignedBytes {
63-
_align: Group,
64-
bytes: [u8; Group::WIDTH],
65-
};
66-
const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
67-
bytes: [EMPTY; Group::WIDTH],
68-
};
69-
unsafe { &ALIGNED_BYTES.bytes }
70-
}
71-
7256
/// Loads a group of bytes starting at the given address.
7357
#[inline]
7458
#[allow(clippy::cast_ptr_alignment)] // unaligned load

src/raw/mod.rs

+31-15
Original file line numberDiff line numberDiff line change
@@ -353,22 +353,23 @@ impl<T> Bucket<T> {
353353
}
354354
}
355355

356+
/// A raw hash table with an unsafe API.
356357
pub struct RawTable<T> {
357358
header: NonNull<Header<T>>,
358359
marker: PhantomData<T>,
359360
}
360361

361-
/// A raw hash table with an unsafe API.
362+
/// The header of a RawTable's allocation (or the EMPTY_SINGLETON)
362363
pub struct Header<T> {
363364
// Mask to get an index from a hash value. The value is one less than the
364365
// number of buckets in the table.
365366
bucket_mask: usize,
366367

367368
// Pointer to the array of control bytes
368-
ctrl: *mut u8,
369+
ctrl: *const u8,
369370

370371
// Pointer to the array of buckets
371-
data: *mut T,
372+
data: *const T,
372373

373374
// Number of elements that can be inserted before we need to grow the table
374375
growth_left: usize,
@@ -377,14 +378,27 @@ pub struct Header<T> {
377378
items: usize,
378379
}
379380

380-
static EMPTY_SINGLETON: Header<()> = Header {
381-
data: 0xA000_0000 as *mut (),
382-
ctrl: std::ptr::null_mut(),
383-
bucket_mask: 0,
384-
items: 0,
385-
growth_left: 0,
381+
static EMPTY_SINGLETON: Header<()> = {
382+
union AlignedBytes {
383+
_align: Group,
384+
bytes: [u8; Group::WIDTH],
385+
};
386+
static ALIGNED_BYTES: AlignedBytes = AlignedBytes {
387+
bytes: [EMPTY; Group::WIDTH],
388+
};
389+
let ctrl = unsafe { &ALIGNED_BYTES.bytes as *const u8 };
390+
391+
Header {
392+
data: core::ptr::null(),
393+
ctrl,
394+
bucket_mask: 0,
395+
items: 0,
396+
growth_left: 0,
397+
}
386398
};
387399

400+
unsafe impl<T: Sync> Sync for Header<T> { }
401+
388402
impl<T> RawTable<T> {
389403
/// Creates a new empty hash table without allocating any memory.
390404
///
@@ -411,8 +425,8 @@ impl<T> RawTable<T> {
411425
calculate_layout::<T>(buckets).ok_or_else(|| fallability.capacity_overflow())?;
412426

413427
let header = NonNull::new(alloc(layout)).ok_or_else(|| fallability.alloc_err(layout))?;
414-
let ctrl = NonNull::new_unchecked(header.as_ptr().add(ctrl_offset) as *mut u8);
415-
let data = NonNull::new_unchecked(header.as_ptr().add(data_offset) as *mut T);
428+
let ctrl = header.as_ptr().add(ctrl_offset) as *mut u8;
429+
let data = header.as_ptr().add(data_offset) as *mut T;
416430

417431
let header = header.cast();
418432
*header.as_ptr() = Header {
@@ -476,24 +490,26 @@ impl<T> RawTable<T> {
476490

477491
#[inline]
478492
fn header(&self) -> &Header<T> {
479-
&*self.header.as_ptr()
493+
unsafe {
494+
&*self.header.as_ptr()
495+
}
480496
}
481497

482498
#[inline]
483-
unsafe fn header_mut(&self) -> &mut Header<T> {
499+
unsafe fn header_mut(&mut self) -> &mut Header<T> {
484500
&mut *self.header.as_ptr()
485501
}
486502

487503
/// Returns a pointer to the data array
488504
#[inline]
489505
fn data_ptr(&self) -> *mut T {
490-
self.header().data.as_ptr()
506+
self.header().data as *mut T
491507
}
492508

493509
/// Returns a pointer to the ctrl array
494510
#[inline]
495511
fn ctrl_ptr(&self) -> *mut u8 {
496-
self.header().ctrl.as_ptr()
512+
self.header().ctrl as *mut u8
497513
}
498514

499515
#[inline]

src/raw/sse2.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,11 @@ pub const BITMASK_MASK: BitMaskWord = 0xffff;
1919
pub struct Group(x86::__m128i);
2020

2121
// FIXME: https://github.com/rust-lang/rust-clippy/issues/3859
22-
#[allow(clippy::use_self)]
22+
#[allow(clippy::use_self)]
2323
impl Group {
2424
/// Number of bytes in the group.
2525
pub const WIDTH: usize = mem::size_of::<Self>();
2626

27-
/// Returns a full group of empty bytes, suitable for use as the initial
28-
/// value for an empty hash table.
29-
///
30-
/// This is guaranteed to be aligned to the group size.
31-
#[inline]
32-
pub fn static_empty() -> &'static [u8] {
33-
union AlignedBytes {
34-
_align: Group,
35-
bytes: [u8; Group::WIDTH],
36-
};
37-
const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
38-
bytes: [EMPTY; Group::WIDTH],
39-
};
40-
unsafe { &ALIGNED_BYTES.bytes }
41-
}
42-
4327
/// Loads a group of bytes starting at the given address.
4428
#[inline]
4529
#[allow(clippy::cast_ptr_alignment)] // unaligned load

0 commit comments

Comments
 (0)