Skip to content

Relax atomic loads and stores in Table #766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,13 @@ impl Table {

impl<'p, T: Slot> PageView<'p, T> {
fn page_data(&self) -> &[PageDataEntry<T>] {
let len = self.0.allocated.load(Ordering::Acquire);
let len = self.0.allocated();
// SAFETY: `len` is the initialized length of the page
unsafe { slice::from_raw_parts(self.0.data.cast::<PageDataEntry<T>>().as_ptr(), len) }
}

fn data(&self) -> &'p [T] {
let len = self.0.allocated.load(Ordering::Acquire);
let len = self.0.allocated();
// SAFETY: `len` is the initialized length of the page
unsafe { slice::from_raw_parts(self.0.data.cast::<T>().as_ptr(), len) }
}
Expand All @@ -305,7 +305,7 @@ impl<'p, T: Slot> PageView<'p, T> {
V: FnOnce(Id) -> T,
{
let _guard = self.0.allocation_lock.lock();
let index = self.0.allocated.load(Ordering::Acquire);
let index = self.0.allocated();
if index >= PAGE_LEN {
return Err(value);
}
Expand All @@ -320,7 +320,8 @@ impl<'p, T: Slot> PageView<'p, T> {

// Update the length (this must be done after initialization as otherwise an uninitialized
// read could occur!)
self.0.allocated.store(index + 1, Ordering::Release);
// Ordering: Relaxed is fine as the `allocation_lock` establishes a happens-before relationship
self.0.allocated.store(index + 1, Ordering::Relaxed);

Ok(id)
}
Expand All @@ -341,13 +342,20 @@ impl Page {
}
}

#[inline]
fn allocated(&self) -> usize {
// Ordering: Relaxed is fine as the `allocation_lock` establishes a happens-before
// relationship
self.allocated.load(Ordering::Relaxed)
}

/// Retrieves the pointer for the given slot.
///
/// # Panics
///
/// If slot is out of bounds
fn get(&self, slot: SlotIndex) -> *mut () {
let len = self.allocated.load(Ordering::Acquire);
let len = self.allocated();
assert!(
slot.0 < len,
"out of bounds access `{slot:?}` (maximum slot `{len}`)"
Expand Down