mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-22 21:05:11 +00:00
return durability of modified data and remove SharedStateWriteGuard
Now the `with_incremented_revision` method signature does not reference the database DB in any way.
This commit is contained in:
parent
705a35d4b7
commit
c6663f3dcb
3 changed files with 27 additions and 46 deletions
|
@ -226,14 +226,16 @@ where
|
|||
{
|
||||
fn invalidate(&self, db: &mut DB, key: &Q::Key) {
|
||||
db.salsa_runtime_mut()
|
||||
.with_incremented_revision(&mut |_new_revision, guard| {
|
||||
.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() {
|
||||
guard.mark_durability_as_changed(durability);
|
||||
return Some(durability);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ where
|
|||
// case doesn't generally seem worth optimizing for.
|
||||
let mut value = Some(value);
|
||||
db.salsa_runtime_mut()
|
||||
.with_incremented_revision(&mut |next_revision, guard| {
|
||||
.with_incremented_revision(&mut |next_revision| {
|
||||
let mut slots = self.slots.write();
|
||||
|
||||
// Do this *after* we acquire the lock, so that we are not
|
||||
|
@ -209,8 +209,9 @@ where
|
|||
match slots.entry(key.clone()) {
|
||||
Entry::Occupied(entry) => {
|
||||
let mut slot_stamped_value = entry.get().stamped_value.write();
|
||||
guard.mark_durability_as_changed(slot_stamped_value.durability);
|
||||
let old_durability = slot_stamped_value.durability;
|
||||
*slot_stamped_value = stamped_value;
|
||||
Some(old_durability)
|
||||
}
|
||||
|
||||
Entry::Vacant(entry) => {
|
||||
|
@ -225,6 +226,7 @@ where
|
|||
database_key_index,
|
||||
stamped_value: RwLock::new(stamped_value),
|
||||
}));
|
||||
None
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -143,9 +143,7 @@ where
|
|||
/// will block until that snapshot is dropped -- if that snapshot
|
||||
/// is owned by the current thread, this could trigger deadlock.
|
||||
pub fn synthetic_write(&mut self, durability: Durability) {
|
||||
self.with_incremented_revision(&mut |_next_revision, guard| {
|
||||
guard.mark_durability_as_changed(durability);
|
||||
});
|
||||
self.with_incremented_revision(&mut |_next_revision| Some(durability));
|
||||
}
|
||||
|
||||
/// Default implementation for `Database::sweep_all`.
|
||||
|
@ -282,20 +280,29 @@ where
|
|||
|
||||
/// Acquires the **global query write lock** (ensuring that no queries are
|
||||
/// executing) and then increments the current revision counter; invokes
|
||||
/// `op` with the global query write lock still held. The `op` closure is
|
||||
/// given the new revision as an argument, and it should actually perform
|
||||
/// the writes.
|
||||
/// `op` with the global query write lock still held.
|
||||
///
|
||||
/// While we wait to acquire the global query write lock, this method will
|
||||
/// also increment `pending_revision_increments`, thus signalling to queries
|
||||
/// that their results are "canceled" and they should abort as expeditiously
|
||||
/// as possible.
|
||||
///
|
||||
/// The `op` closure should actually perform the writes needed. It is given
|
||||
/// the new revision as an argument, and its return value indicates whether
|
||||
/// any pre-existing value was modified:
|
||||
///
|
||||
/// - returning `None` means that no pre-existing value was modified (this
|
||||
/// could occur e.g. when setting some key on an input that was never set
|
||||
/// before)
|
||||
/// - returning `Some(d)` indicates that a pre-existing value was modified
|
||||
/// and it had the durability `d`. This will update the records for when
|
||||
/// values with each durability were modified.
|
||||
///
|
||||
/// Note that, given our writer model, we can assume that only one thread is
|
||||
/// attempting to increment the global revision at a time.
|
||||
pub(crate) fn with_incremented_revision(
|
||||
&mut self,
|
||||
op: &mut dyn FnMut(Revision, &DatabaseWriteLockGuard<'_, DB>),
|
||||
op: &mut dyn FnMut(Revision) -> Option<Durability>,
|
||||
) {
|
||||
log::debug!("increment_revision()");
|
||||
|
||||
|
@ -318,13 +325,11 @@ where
|
|||
|
||||
debug!("increment_revision: incremented to {:?}", new_revision);
|
||||
|
||||
op(
|
||||
new_revision,
|
||||
&DatabaseWriteLockGuard {
|
||||
runtime: self,
|
||||
new_revision,
|
||||
},
|
||||
)
|
||||
if let Some(d) = op(new_revision) {
|
||||
for rev in &self.shared_state.revisions[1..=d.index()] {
|
||||
rev.store(new_revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn permits_increment(&self) -> bool {
|
||||
|
@ -528,34 +533,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Temporary guard that indicates that the database write-lock is
|
||||
/// held. You can get one of these by invoking
|
||||
/// `with_incremented_revision`. It gives access to the new revision
|
||||
/// and a few other operations that only make sense to do while an
|
||||
/// update is happening.
|
||||
pub(crate) struct DatabaseWriteLockGuard<'db, DB>
|
||||
where
|
||||
DB: Database,
|
||||
{
|
||||
runtime: &'db mut Runtime<DB>,
|
||||
new_revision: Revision,
|
||||
}
|
||||
|
||||
impl<DB> DatabaseWriteLockGuard<'_, DB>
|
||||
where
|
||||
DB: Database,
|
||||
{
|
||||
/// Indicates that this update modified an input marked as
|
||||
/// "constant". This will force re-evaluation of anything that was
|
||||
/// dependent on constants (which otherwise might not get
|
||||
/// re-evaluated).
|
||||
pub(crate) fn mark_durability_as_changed(&self, d: Durability) {
|
||||
for rev in &self.runtime.shared_state.revisions[1..=d.index()] {
|
||||
rev.store(self.new_revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State that will be common to all threads (when we support multiple threads)
|
||||
struct SharedState<DB: Database> {
|
||||
storage: DB::DatabaseStorage,
|
||||
|
|
Loading…
Reference in a new issue