have queries freeze the revision

This commit is contained in:
Niko Matsakis 2018-10-11 16:48:20 -04:00
parent 41b36da054
commit c6f78d5f27
2 changed files with 24 additions and 4 deletions

View file

@ -171,7 +171,11 @@ where
key: &Q::Key,
descriptor: &DB::QueryDescriptor,
) -> Result<StampedValue<Q::Value>, CycleDetected> {
let revision_now = db.salsa_runtime().current_revision();
let runtime = db.salsa_runtime();
let _read_lock = runtime.freeze_revision();
let revision_now = runtime.current_revision();
debug!(
"{:?}({:?}): invoked at {:?}",
@ -239,7 +243,6 @@ where
// Query was not previously executed, or value is potentially
// stale, or value is absent. Let's execute!
let runtime = db.salsa_runtime();
let (mut stamped_value, inputs) = runtime.execute_query_implementation(descriptor, || {
debug!("{:?}({:?}): executing query", Q::default(), key);
@ -254,7 +257,7 @@ where
// not mutate the "inputs" to the query system. Sanity check
// that assumption here, at least to the best of our ability.
assert_eq!(
db.salsa_runtime().current_revision(),
runtime.current_revision(),
revision_now,
"revision altered during query execution",
);

View file

@ -2,7 +2,7 @@ use crate::Database;
use crate::Query;
use crate::QueryFunction;
use log::debug;
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
use parking_lot::{RwLock, RwLockReadGuard, RwLockUpgradableReadGuard};
use rustc_hash::FxHasher;
use std::cell::RefCell;
use std::fmt::Write;
@ -69,6 +69,23 @@ where
self.increment_revision();
}
/// Indicates that a derived query has begun to execute; if this is the
/// first derived query on this thread, then acquires a read-lock on the
/// runtime to prevent us from moving to a new revision until that query
/// completes.
///
/// (However, if other threads invoke `increment_revision`, then
/// the current revision may be considered cancelled, which can be
/// observed through `is_current_revision_canceled`.)
pub(crate) fn freeze_revision(&self) -> Option<RwLockReadGuard<'_, ()>> {
let local_state = self.local_state.borrow();
if local_state.query_stack.is_empty() {
Some(self.shared_state.revision_lock.read())
} else {
None
}
}
/// Read current value of the revision counter.
pub(crate) fn current_revision(&self) -> Revision {
Revision {