Fix invalidate and report_synthetic_read

This commit is contained in:
Jonas Schievink 2021-09-03 21:44:53 +02:00
parent 114d6db8f6
commit 8f0b9b7f82
5 changed files with 32 additions and 17 deletions

View file

@ -229,11 +229,11 @@ where
Q::Key: Borrow<S>,
{
db.salsa_runtime_mut()
.with_incremented_revision(&mut |_new_revision| {
.with_incremented_revision(&mut |new_revision| {
let map_read = self.slot_map.read();
if let Some(slot) = map_read.get(key) {
if let Some(durability) = slot.invalidate() {
if let Some(durability) = slot.invalidate(new_revision) {
return Some(durability);
}
}

View file

@ -461,12 +461,16 @@ where
}
}
pub(super) fn invalidate(&self) -> Option<Durability> {
if let QueryState::Memoized(memo) = &mut *self.state.write() {
memo.revisions.inputs = MemoInputs::Untracked;
Some(memo.revisions.durability)
} else {
None
pub(super) fn invalidate(&self, new_revision: Revision) -> Option<Durability> {
log::debug!("Slot::invalidate(new_revision = {:?})", new_revision);
match &mut *self.state.write() {
QueryState::Memoized(memo) => {
memo.revisions.inputs = MemoInputs::Untracked;
memo.revisions.changed_at = new_revision;
Some(memo.revisions.durability)
}
QueryState::NotComputed => None,
QueryState::InProgress { .. } => unreachable!(),
}
}
@ -495,7 +499,7 @@ where
// entry, that must mean that it was found to be out
// of date and removed.
QueryState::NotComputed => {
debug!("maybe_changed_since({:?}: no value", self);
debug!("maybe_changed_since({:?}): no value", self);
return true;
}
@ -505,7 +509,7 @@ where
QueryState::InProgress { id, waiting } => {
let other_id = *id;
debug!(
"maybe_changed_since({:?}: blocking on thread `{:?}`",
"maybe_changed_since({:?}): blocking on thread `{:?}`",
self, other_id,
);
match self.register_with_in_progress_thread(db, runtime, other_id, waiting) {
@ -527,7 +531,7 @@ where
if memo.revisions.verified_at == revision_now {
debug!(
"maybe_changed_since({:?}: {:?} since up-to-date memo that changed at {:?}",
"maybe_changed_since({:?}): {:?} since up-to-date memo that changed at {:?}",
self,
memo.revisions.changed_at > revision,
memo.revisions.changed_at,
@ -857,7 +861,10 @@ impl MemoRevisions {
assert!(self.verified_at != revision_now);
let verified_at = self.verified_at;
debug!("validate_memoized_value: verified_at={:#?}", self.inputs,);
debug!(
"validate_memoized_value: verified_at={:?}, revision_now={:?}, inputs={:#?}",
verified_at, revision_now, self.inputs
);
if self.check_durability(db.salsa_runtime()) {
return self.mark_value_as_verified(revision_now);
@ -866,7 +873,7 @@ impl MemoRevisions {
match &self.inputs {
// We can't validate values that had untracked inputs; just have to
// re-execute.
MemoInputs::Untracked { .. } => {
MemoInputs::Untracked => {
return false;
}

View file

@ -280,7 +280,8 @@ impl Runtime {
///
/// This is mostly useful to control the durability level for [on-demand inputs](https://salsa-rs.github.io/salsa/common_patterns/on_demand_inputs.html).
pub fn report_synthetic_read(&self, durability: Durability) {
self.local_state.report_synthetic_read(durability);
self.local_state
.report_synthetic_read(durability, self.current_revision());
}
/// Obviously, this should be user configurable at some point.
@ -526,8 +527,9 @@ impl ActiveQuery {
self.changed_at = changed_at;
}
fn add_synthetic_read(&mut self, durability: Durability) {
fn add_synthetic_read(&mut self, durability: Durability, current_revision: Revision) {
self.durability = self.durability.min(durability);
self.changed_at = current_revision;
}
}

View file

@ -81,9 +81,9 @@ impl LocalState {
}
}
pub(super) fn report_synthetic_read(&self, durability: Durability) {
pub(super) fn report_synthetic_read(&self, durability: Durability, current_revision: Revision) {
if let Some(top_query) = self.query_stack.borrow_mut().last_mut() {
top_query.add_synthetic_read(durability);
top_query.add_synthetic_read(durability, current_revision);
}
}
}

View file

@ -73,6 +73,12 @@ fn on_demand_input_works() {
AQuery.in_db_mut(&mut db).invalidate(&1);
assert_eq!(db.b(1), 92);
assert_eq!(db.a(1), 92);
// Downstream queries should also be rerun if we call `a` first.
db.external_state.insert(1, 50);
AQuery.in_db_mut(&mut db).invalidate(&1);
assert_eq!(db.a(1), 50);
assert_eq!(db.b(1), 50);
}
#[test]