mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 05:07:27 +00:00
rewrite map to just grab a write lock, and fix some latent bugs
This commit is contained in:
parent
a7317084dc
commit
42b88fe7e6
1 changed files with 28 additions and 13 deletions
41
src/input.rs
41
src/input.rs
|
@ -46,6 +46,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IsConstant(bool);
|
||||||
|
|
||||||
impl<DB, Q> InputStorage<DB, Q>
|
impl<DB, Q> InputStorage<DB, Q>
|
||||||
where
|
where
|
||||||
Q: Query<DB>,
|
Q: Query<DB>,
|
||||||
|
@ -71,26 +73,44 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_common(&self, key: &Q::Key, value: Q::Value, changed_at: impl FnOnce() -> ChangedAt) {
|
fn set_common(&self, db: &DB, key: &Q::Key, value: Q::Value, is_constant: IsConstant) {
|
||||||
let map = self.map.upgradable_read();
|
let mut map = self.map.write();
|
||||||
|
|
||||||
// If this value was previously stored, check if this is an
|
// If this value was previously stored, check if this is an
|
||||||
// *actual change* before we do anything.
|
// *actual change* before we do anything.
|
||||||
if let Some(old_value) = map.get(key) {
|
if let Some(old_value) = map.get_mut(key) {
|
||||||
if old_value.value == value {
|
if old_value.value == value {
|
||||||
|
// If the value did not change, but it is now
|
||||||
|
// considered constant, we can just update
|
||||||
|
// `changed_at`. We don't have to trigger a new
|
||||||
|
// revision for this case: all the derived values are
|
||||||
|
// still intact, they just have conservative
|
||||||
|
// dependencies. The next revision, they may wind up
|
||||||
|
// with something more precise.
|
||||||
|
if is_constant.0 && !old_value.changed_at.is_constant() {
|
||||||
|
old_value.changed_at = ChangedAt::Constant;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = key.clone();
|
let key = key.clone();
|
||||||
|
|
||||||
let mut map = RwLockUpgradableReadGuard::upgrade(map);
|
// The value is changing, so even if we are setting this to a
|
||||||
|
// constant, we still need a new revision.
|
||||||
|
let next_revision = db.salsa_runtime().increment_revision();
|
||||||
|
|
||||||
// Do this *after* we acquire the lock, so that we are not
|
// Do this *after* we acquire the lock, so that we are not
|
||||||
// racing with somebody else to modify this same cell.
|
// racing with somebody else to modify this same cell.
|
||||||
// (Otherwise, someone else might write a *newer* revision
|
// (Otherwise, someone else might write a *newer* revision
|
||||||
// into the same cell while we block on the lock.)
|
// into the same cell while we block on the lock.)
|
||||||
let changed_at = changed_at();
|
let changed_at = if is_constant.0 {
|
||||||
|
ChangedAt::Constant
|
||||||
|
} else {
|
||||||
|
ChangedAt::Revision(next_revision)
|
||||||
|
};
|
||||||
|
|
||||||
let stamped_value = StampedValue { value, changed_at };
|
let stamped_value = StampedValue { value, changed_at };
|
||||||
|
|
||||||
match map.entry(key) {
|
match map.entry(key) {
|
||||||
|
@ -166,16 +186,11 @@ where
|
||||||
Q::Value: Default,
|
Q::Value: Default,
|
||||||
{
|
{
|
||||||
fn set(&self, db: &DB, key: &Q::Key, value: Q::Value) {
|
fn set(&self, db: &DB, key: &Q::Key, value: Q::Value) {
|
||||||
self.set_common(key, value, || {
|
self.set_common(db, key, value, IsConstant(false))
|
||||||
ChangedAt::Revision(db.salsa_runtime().increment_revision())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_constant(&self, _db: &DB, key: &Q::Key, value: Q::Value) {
|
fn set_constant(&self, db: &DB, key: &Q::Key, value: Q::Value) {
|
||||||
// FIXME. One weirdness: if this previously had a value, but
|
self.set_common(db, key, value, IsConstant(true))
|
||||||
// was not marked as constant, we will not "lower" the
|
|
||||||
// `ChangedAt` rating with the code as it is.
|
|
||||||
self.set_common(key, value, || ChangedAt::Constant);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue