mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-02-02 09:46:06 +00:00
refactor ChangedAt
into a struct
There are really two orthogonal things going on here.
This commit is contained in:
parent
03751d3d5c
commit
1ab8d1a64e
3 changed files with 68 additions and 55 deletions
|
@ -319,8 +319,8 @@ where
|
|||
if let Some(old_memo) = &old_memo {
|
||||
if let Some(old_value) = &old_memo.value {
|
||||
if MP::memoized_value_eq(&old_value, &stamped_value.value) {
|
||||
assert!(old_memo.changed_at <= stamped_value.changed_at);
|
||||
stamped_value.changed_at = old_memo.changed_at;
|
||||
assert!(old_memo.changed_at.revision <= stamped_value.changed_at.revision);
|
||||
stamped_value.changed_at.revision = old_memo.changed_at.revision;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -717,7 +717,10 @@ where
|
|||
let mut map_write = self.map.write();
|
||||
|
||||
let current_revision = db.salsa_runtime().current_revision();
|
||||
let changed_at = ChangedAt::Revision(current_revision);
|
||||
let changed_at = ChangedAt {
|
||||
is_constant: false,
|
||||
revision: current_revision,
|
||||
};
|
||||
|
||||
map_write.insert(
|
||||
key,
|
||||
|
@ -751,20 +754,13 @@ where
|
|||
fn verify_inputs(&self, db: &DB) -> bool {
|
||||
match &self.inputs {
|
||||
QueryDescriptorSet::Constant => {
|
||||
debug_assert!(match self.changed_at {
|
||||
ChangedAt::Constant(_) => true,
|
||||
ChangedAt::Revision(_) => false,
|
||||
});
|
||||
|
||||
debug_assert!(self.changed_at.is_constant);
|
||||
true
|
||||
}
|
||||
|
||||
QueryDescriptorSet::Tracked { descriptors } => {
|
||||
debug_assert!(!descriptors.is_empty());
|
||||
debug_assert!(match self.changed_at {
|
||||
ChangedAt::Constant(_) => false,
|
||||
ChangedAt::Revision(_) => true,
|
||||
});
|
||||
debug_assert!(!self.changed_at.is_constant);
|
||||
|
||||
// Check whether any of our inputs changed since the
|
||||
// **last point where we were verified** (not since we
|
||||
|
|
28
src/input.rs
28
src/input.rs
|
@ -61,7 +61,10 @@ where
|
|||
|
||||
Ok(StampedValue {
|
||||
value: <Q::Value>::default(),
|
||||
changed_at: ChangedAt::Revision(Revision::ZERO),
|
||||
changed_at: ChangedAt {
|
||||
is_constant: false,
|
||||
revision: Revision::ZERO,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -80,8 +83,10 @@ where
|
|||
if is_constant.0 && !old_value.changed_at.is_constant() {
|
||||
let mut map = RwLockUpgradableReadGuard::upgrade(map);
|
||||
let old_value = map.get_mut(key).unwrap();
|
||||
old_value.changed_at =
|
||||
ChangedAt::Constant(db.salsa_runtime().current_revision());
|
||||
old_value.changed_at = ChangedAt {
|
||||
is_constant: true,
|
||||
revision: db.salsa_runtime().current_revision(),
|
||||
};
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -106,10 +111,9 @@ where
|
|||
// racing with somebody else to modify this same cell.
|
||||
// (Otherwise, someone else might write a *newer* revision
|
||||
// into the same cell while we block on the lock.)
|
||||
let changed_at = if is_constant.0 {
|
||||
ChangedAt::Constant(next_revision)
|
||||
} else {
|
||||
ChangedAt::Revision(next_revision)
|
||||
let changed_at = ChangedAt {
|
||||
is_constant: is_constant.0,
|
||||
revision: next_revision,
|
||||
};
|
||||
|
||||
let stamped_value = StampedValue { value, changed_at };
|
||||
|
@ -174,7 +178,10 @@ where
|
|||
map_read
|
||||
.get(key)
|
||||
.map(|v| v.changed_at)
|
||||
.unwrap_or(ChangedAt::Revision(Revision::ZERO))
|
||||
.unwrap_or(ChangedAt {
|
||||
is_constant: false,
|
||||
revision: Revision::ZERO,
|
||||
})
|
||||
};
|
||||
|
||||
debug!(
|
||||
|
@ -229,7 +236,10 @@ where
|
|||
|
||||
// Unlike with `set`, here we use the **current revision** and
|
||||
// do not create a new one.
|
||||
let changed_at = ChangedAt::Revision(db.salsa_runtime().current_revision());
|
||||
let changed_at = ChangedAt {
|
||||
is_constant: false,
|
||||
revision: db.salsa_runtime().current_revision(),
|
||||
};
|
||||
|
||||
map_write.insert(key, StampedValue { value, changed_at });
|
||||
}
|
||||
|
|
|
@ -258,6 +258,11 @@ where
|
|||
local_state.query_stack.pop().unwrap()
|
||||
};
|
||||
|
||||
let is_constant = match &subqueries {
|
||||
Some(set) => set.is_empty(),
|
||||
None => false,
|
||||
};
|
||||
|
||||
let query_descriptor_set = match subqueries {
|
||||
None => QueryDescriptorSet::Untracked,
|
||||
Some(set) => {
|
||||
|
@ -271,7 +276,16 @@ where
|
|||
}
|
||||
};
|
||||
|
||||
(StampedValue { value, changed_at }, query_descriptor_set)
|
||||
(
|
||||
StampedValue {
|
||||
value,
|
||||
changed_at: ChangedAt {
|
||||
is_constant,
|
||||
revision: changed_at,
|
||||
},
|
||||
},
|
||||
query_descriptor_set,
|
||||
)
|
||||
}
|
||||
|
||||
/// Reports that the currently active query read the result from
|
||||
|
@ -294,8 +308,7 @@ where
|
|||
|
||||
pub(crate) fn report_untracked_read(&self) {
|
||||
if let Some(top_query) = self.local_state.borrow_mut().query_stack.last_mut() {
|
||||
let changed_at = ChangedAt::Revision(self.current_revision());
|
||||
top_query.add_untracked_read(changed_at);
|
||||
top_query.add_untracked_read(self.current_revision());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,7 +475,7 @@ struct ActiveQuery<DB: Database> {
|
|||
descriptor: DB::QueryDescriptor,
|
||||
|
||||
/// Records the maximum revision where any subquery changed
|
||||
changed_at: ChangedAt,
|
||||
changed_at: Revision,
|
||||
|
||||
/// Each subquery
|
||||
subqueries: Option<FxIndexSet<DB::QueryDescriptor>>,
|
||||
|
@ -472,27 +485,29 @@ impl<DB: Database> ActiveQuery<DB> {
|
|||
fn new(descriptor: DB::QueryDescriptor) -> Self {
|
||||
ActiveQuery {
|
||||
descriptor,
|
||||
changed_at: ChangedAt::Constant(Revision::ZERO),
|
||||
changed_at: Revision::ZERO,
|
||||
subqueries: Some(FxIndexSet::default()),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_read(&mut self, subquery: &DB::QueryDescriptor, changed_at: ChangedAt) {
|
||||
match changed_at {
|
||||
ChangedAt::Constant(_) => {
|
||||
// When we read constant values, we don't need to
|
||||
// track the source of the value.
|
||||
}
|
||||
ChangedAt::Revision(_) => {
|
||||
if let Some(set) = &mut self.subqueries {
|
||||
set.insert(subquery.clone());
|
||||
}
|
||||
self.changed_at = self.changed_at.max(changed_at);
|
||||
let ChangedAt {
|
||||
is_constant,
|
||||
revision,
|
||||
} = changed_at;
|
||||
|
||||
if is_constant {
|
||||
// When we read constant values, we don't need to
|
||||
// track the source of the value.
|
||||
} else {
|
||||
if let Some(set) = &mut self.subqueries {
|
||||
set.insert(subquery.clone());
|
||||
}
|
||||
self.changed_at = self.changed_at.max(revision);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_untracked_read(&mut self, changed_at: ChangedAt) {
|
||||
fn add_untracked_read(&mut self, changed_at: Revision) {
|
||||
self.subqueries = None;
|
||||
self.changed_at = self.changed_at.max(changed_at);
|
||||
}
|
||||
|
@ -519,35 +534,27 @@ impl std::fmt::Debug for Revision {
|
|||
}
|
||||
|
||||
/// Records when a stamped value changed.
|
||||
///
|
||||
/// Note: the order of variants is significant. We sometimes use `max`
|
||||
/// for example to find the "most recent revision" when something
|
||||
/// changed.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ChangedAt {
|
||||
/// Will never change again (and the revision in which we became a
|
||||
/// constant).
|
||||
Constant(Revision),
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ChangedAt {
|
||||
// Will this value ever change again?
|
||||
pub(crate) is_constant: bool,
|
||||
|
||||
/// Last changed in the given revision. May change in the future.
|
||||
Revision(Revision),
|
||||
// At which revision did this value last change? (If this value is
|
||||
// the value of a constant input, this indicates when it became
|
||||
// constant.)
|
||||
pub(crate) revision: Revision,
|
||||
}
|
||||
|
||||
impl ChangedAt {
|
||||
pub fn is_constant(self) -> bool {
|
||||
match self {
|
||||
ChangedAt::Constant(_) => true,
|
||||
ChangedAt::Revision(_) => false,
|
||||
}
|
||||
self.is_constant
|
||||
}
|
||||
|
||||
/// True if a value is stored with this `ChangedAt` value has
|
||||
/// changed after `revision`. This is invoked by query storage
|
||||
/// when their dependents are asking them if they have changed.
|
||||
pub fn changed_since(self, revision: Revision) -> bool {
|
||||
match self {
|
||||
ChangedAt::Constant(r) | ChangedAt::Revision(r) => r > revision,
|
||||
}
|
||||
self.revision > revision
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue