mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 05:07:27 +00:00
make memos take read-lock (and infallible return)
We want to ensure that accessing the memos only occurs in revision R after the struct is created.
This commit is contained in:
parent
8833a7168b
commit
3dabb0ddc8
4 changed files with 46 additions and 36 deletions
|
@ -308,7 +308,7 @@ impl<C> Slot for Value<C>
|
|||
where
|
||||
C: Configuration,
|
||||
{
|
||||
fn memos(&self) -> Option<&crate::table::memo::MemoTable> {
|
||||
Some(&self.memos)
|
||||
fn memos(&self, _current_revision: Revision) -> &crate::table::memo::MemoTable {
|
||||
&self.memos
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ impl<C> Slot for Value<C>
|
|||
where
|
||||
C: Configuration,
|
||||
{
|
||||
fn memos(&self) -> Option<&MemoTable> {
|
||||
Some(&self.memos)
|
||||
fn memos(&self, _current_revision: Revision) -> &MemoTable {
|
||||
&self.memos
|
||||
}
|
||||
}
|
||||
|
|
16
src/table.rs
16
src/table.rs
|
@ -24,7 +24,7 @@ pub(crate) struct Table {
|
|||
pub(crate) trait TablePage: Any + Send + Sync {
|
||||
fn hidden_type_name(&self) -> &'static str;
|
||||
|
||||
fn memos(&self, slot: SlotIndex) -> Option<&MemoTable>;
|
||||
fn memos(&self, slot: SlotIndex, current_revision: Revision) -> &MemoTable;
|
||||
}
|
||||
|
||||
pub(crate) struct Page<T: Slot> {
|
||||
|
@ -51,7 +51,7 @@ pub(crate) struct Page<T: Slot> {
|
|||
}
|
||||
|
||||
pub(crate) trait Slot: Any + Send + Sync {
|
||||
fn memos(&self) -> Option<&MemoTable>;
|
||||
fn memos(&self, current_revision: Revision) -> &MemoTable;
|
||||
}
|
||||
|
||||
unsafe impl<T: Slot> Send for Page<T> {}
|
||||
|
@ -117,9 +117,13 @@ impl Table {
|
|||
}
|
||||
|
||||
/// Get the memo table associated with `id` (if any)
|
||||
pub fn memos(&self, id: Id) -> Option<&MemoTable> {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If the ingredient for `id` doesn't have associated memo-tables on its slots.
|
||||
pub fn memos(&self, id: Id, current_revision: Revision) -> &MemoTable {
|
||||
let (page, slot) = split_id(id);
|
||||
self.pages[page.0].memos(slot)
|
||||
self.pages[page.0].memos(slot, current_revision)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,8 +198,8 @@ impl<T: Slot> TablePage for Page<T> {
|
|||
std::any::type_name::<Self>()
|
||||
}
|
||||
|
||||
fn memos(&self, slot: SlotIndex) -> Option<&MemoTable> {
|
||||
self.get(slot).memos()
|
||||
fn memos(&self, slot: SlotIndex, current_revision: Revision) -> &MemoTable {
|
||||
self.get(slot).memos(current_revision)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -521,7 +521,7 @@ where
|
|||
let field_ingredient_index = self.ingredient_index.successor(field_index);
|
||||
let data = Self::data(zalsa.table(), id);
|
||||
|
||||
self.read_lock(data, zalsa.current_revision());
|
||||
data.read_lock(zalsa.current_revision());
|
||||
|
||||
let field_changed_at = data.revisions[field_index];
|
||||
|
||||
|
@ -536,29 +536,6 @@ where
|
|||
|
||||
unsafe { self.to_self_ref(&data.fields) }
|
||||
}
|
||||
|
||||
fn read_lock(&self, data: &Value<C>, current_revision: Revision) {
|
||||
loop {
|
||||
match data.updated_at.load() {
|
||||
None => {
|
||||
panic!("access to field whilst the value is being initialized");
|
||||
}
|
||||
Some(r) => {
|
||||
if r == current_revision {
|
||||
return;
|
||||
}
|
||||
|
||||
if data
|
||||
.updated_at
|
||||
.compare_exchange(Some(r), Some(current_revision))
|
||||
.is_ok()
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Ingredient for IngredientImpl<C>
|
||||
|
@ -640,11 +617,40 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<C> Value<C>
|
||||
where
|
||||
C: Configuration,
|
||||
{
|
||||
fn read_lock(&self, current_revision: Revision) {
|
||||
loop {
|
||||
match self.updated_at.load() {
|
||||
None => {
|
||||
panic!("access to field whilst the value is being initialized");
|
||||
}
|
||||
Some(r) => {
|
||||
if r == current_revision {
|
||||
return;
|
||||
}
|
||||
|
||||
if self
|
||||
.updated_at
|
||||
.compare_exchange(Some(r), Some(current_revision))
|
||||
.is_ok()
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Slot for Value<C>
|
||||
where
|
||||
C: Configuration,
|
||||
{
|
||||
fn memos(&self) -> Option<&crate::table::memo::MemoTable> {
|
||||
Some(&self.memos)
|
||||
fn memos(&self, current_revision: Revision) -> &crate::table::memo::MemoTable {
|
||||
self.read_lock(current_revision);
|
||||
&self.memos
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue