mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-02-02 09:46:06 +00:00
(almost) encansulate Runtime into Zalsa
The distinction is dumb and should go away. But we still need it for a bit.
This commit is contained in:
parent
596461c213
commit
1842b1dfbb
21 changed files with 136 additions and 111 deletions
|
@ -21,6 +21,7 @@ rustc-hash = "2.0.0"
|
|||
salsa-macro-rules = { version = "0.1.0", path = "components/salsa-macro-rules" }
|
||||
salsa-macros = { path = "components/salsa-macros" }
|
||||
smallvec = "1.0.0"
|
||||
lazy_static = "1.5.0"
|
||||
|
||||
[dev-dependencies]
|
||||
annotate-snippets = "0.11.4"
|
||||
|
|
|
@ -86,12 +86,12 @@ macro_rules! setup_input_struct {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn ingredient_mut(db: &mut dyn $zalsa::Database) -> (&mut $zalsa_struct::IngredientImpl<Self>, &mut $zalsa::Runtime) {
|
||||
pub fn ingredient_mut(db: &mut dyn $zalsa::Database) -> (&mut $zalsa_struct::IngredientImpl<Self>, $zalsa::Revision) {
|
||||
let zalsa_mut = db.zalsa_mut();
|
||||
let index = zalsa_mut.add_or_lookup_jar_by_type(&<$zalsa_struct::JarImpl<$Configuration>>::default());
|
||||
let (ingredient, runtime) = zalsa_mut.lookup_ingredient_mut(index);
|
||||
let (ingredient, current_revision) = zalsa_mut.lookup_ingredient_mut(index);
|
||||
let ingredient = ingredient.assert_type_mut::<$zalsa_struct::IngredientImpl<Self>>();
|
||||
(ingredient, runtime)
|
||||
(ingredient, current_revision)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,7 @@ impl<A: Accumulator> IngredientImpl<A> {
|
|||
|
||||
pub fn push(&self, db: &dyn crate::Database, value: A) {
|
||||
local_state::attach(db, |state| {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let current_revision = runtime.current_revision();
|
||||
let current_revision = db.zalsa().current_revision();
|
||||
let (active_query, _) = match state.active_query() {
|
||||
Some(pair) => pair,
|
||||
None => {
|
||||
|
@ -163,7 +162,7 @@ impl<A: Accumulator> Ingredient for IngredientImpl<A> {
|
|||
output_key: Option<crate::Id>,
|
||||
) {
|
||||
assert!(output_key.is_none());
|
||||
let current_revision = db.zalsa().runtime().current_revision();
|
||||
let current_revision = db.zalsa().current_revision();
|
||||
if let Some(mut v) = self.map.get_mut(&executor) {
|
||||
// The value is still valid in the new revision.
|
||||
v.produced_at = current_revision;
|
||||
|
|
|
@ -2,8 +2,9 @@ use crate::{
|
|||
durability::Durability,
|
||||
hash::{FxIndexMap, FxIndexSet},
|
||||
key::{DatabaseKeyIndex, DependencyIndex},
|
||||
local_state::EMPTY_DEPENDENCIES,
|
||||
tracked_struct::Disambiguator,
|
||||
Cycle, Revision, Runtime,
|
||||
Cycle, Revision,
|
||||
};
|
||||
|
||||
use super::local_state::{EdgeKind, QueryEdges, QueryOrigin, QueryRevisions};
|
||||
|
@ -86,9 +87,9 @@ impl ActiveQuery {
|
|||
self.input_outputs.contains(&(EdgeKind::Output, key))
|
||||
}
|
||||
|
||||
pub(crate) fn revisions(&self, runtime: &Runtime) -> QueryRevisions {
|
||||
pub(crate) fn revisions(&self) -> QueryRevisions {
|
||||
let input_outputs = if self.input_outputs.is_empty() {
|
||||
runtime.empty_dependencies()
|
||||
EMPTY_DEPENDENCIES.clone()
|
||||
} else {
|
||||
self.input_outputs.iter().copied().collect()
|
||||
};
|
||||
|
|
|
@ -21,9 +21,9 @@ pub trait Database: ZalsaDatabase + AsDynDatabase {
|
|||
/// will block until that snapshot is dropped -- if that snapshot
|
||||
/// is owned by the current thread, this could trigger deadlock.
|
||||
fn synthetic_write(&mut self, durability: Durability) {
|
||||
let runtime = self.zalsa_mut().runtime_mut();
|
||||
runtime.new_revision();
|
||||
runtime.report_tracked_write(durability);
|
||||
let zalsa_mut = self.zalsa_mut();
|
||||
zalsa_mut.new_revision();
|
||||
zalsa_mut.report_tracked_write(durability);
|
||||
}
|
||||
|
||||
/// Reports that the query depends on some state unknown to salsa.
|
||||
|
@ -33,7 +33,7 @@ pub trait Database: ZalsaDatabase + AsDynDatabase {
|
|||
fn report_untracked_read(&self) {
|
||||
let db = self.as_dyn_database();
|
||||
local_state::attach(db, |state| {
|
||||
state.report_untracked_read(db.zalsa().runtime().current_revision())
|
||||
state.report_untracked_read(db.zalsa().current_revision())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ impl<T: Database> AsDynDatabase for T {
|
|||
}
|
||||
|
||||
pub fn current_revision<Db: ?Sized + Database>(db: &Db) -> Revision {
|
||||
db.zalsa().runtime().current_revision()
|
||||
db.zalsa().current_revision()
|
||||
}
|
||||
|
||||
impl dyn Database {
|
||||
|
|
|
@ -16,7 +16,7 @@ where
|
|||
{
|
||||
local_state::attach(db, |local_state| {
|
||||
let zalsa = db.zalsa();
|
||||
let current_revision = zalsa.runtime().current_revision();
|
||||
let current_revision = zalsa.current_revision();
|
||||
|
||||
let Some(accumulator) = <accumulator::IngredientImpl<A>>::from_db(db) else {
|
||||
return vec![];
|
||||
|
|
|
@ -27,8 +27,7 @@ where
|
|||
opt_old_memo: Option<Arc<Memo<C::Output<'_>>>>,
|
||||
) -> StampedValue<&C::Output<'db>> {
|
||||
let zalsa = db.zalsa();
|
||||
let runtime = zalsa.runtime();
|
||||
let revision_now = runtime.current_revision();
|
||||
let revision_now = zalsa.current_revision();
|
||||
let database_key_index = active_query.database_key_index;
|
||||
|
||||
tracing::info!("{:?}: executing query", database_key_index);
|
||||
|
@ -68,16 +67,7 @@ where
|
|||
}
|
||||
}
|
||||
};
|
||||
let mut revisions = active_query.pop(runtime);
|
||||
|
||||
// We assume that query is side-effect free -- that is, does
|
||||
// not mutate the "inputs" to the query system. Sanity check
|
||||
// that assumption here, at least to the best of our ability.
|
||||
assert_eq!(
|
||||
runtime.current_revision(),
|
||||
revision_now,
|
||||
"revision altered during query execution",
|
||||
);
|
||||
let mut revisions = active_query.pop();
|
||||
|
||||
// If the new value is equal to the old one, then it didn't
|
||||
// really change, even if some of its inputs have. So we can
|
||||
|
|
|
@ -63,8 +63,8 @@ where
|
|||
let memo_guard = self.memo_map.get(key);
|
||||
if let Some(memo) = &memo_guard {
|
||||
if memo.value.is_some() {
|
||||
let runtime = db.zalsa().runtime();
|
||||
if self.shallow_verify_memo(db, runtime, self.database_key_index(key), memo) {
|
||||
let zalsa = db.zalsa();
|
||||
if self.shallow_verify_memo(db, zalsa, self.database_key_index(key), memo) {
|
||||
let value = unsafe {
|
||||
// Unsafety invariant: memo is present in memo_map
|
||||
self.extend_memo_lifetime(memo).unwrap()
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::{
|
|||
key::DatabaseKeyIndex,
|
||||
local_state::{self, ActiveQueryGuard, EdgeKind, LocalState, QueryOrigin},
|
||||
runtime::StampedValue,
|
||||
storage::ZalsaDatabase as _,
|
||||
AsDynDatabase as _, Id, Revision, Runtime,
|
||||
storage::{Zalsa, ZalsaDatabase as _},
|
||||
AsDynDatabase as _, Id, Revision,
|
||||
};
|
||||
|
||||
use super::{memo::Memo, Configuration, IngredientImpl};
|
||||
|
@ -21,7 +21,7 @@ where
|
|||
revision: Revision,
|
||||
) -> bool {
|
||||
local_state::attach(db.as_dyn_database(), |local_state| {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let zalsa = db.zalsa();
|
||||
local_state.unwind_if_revision_cancelled(db.as_dyn_database());
|
||||
|
||||
loop {
|
||||
|
@ -34,7 +34,7 @@ where
|
|||
// Check if we have a verified version: this is the hot path.
|
||||
let memo_guard = self.memo_map.get(key);
|
||||
if let Some(memo) = &memo_guard {
|
||||
if self.shallow_verify_memo(db, runtime, database_key_index, memo) {
|
||||
if self.shallow_verify_memo(db, zalsa, database_key_index, memo) {
|
||||
return memo.revisions.changed_at > revision;
|
||||
}
|
||||
drop(memo_guard); // release the arc-swap guard before cold path
|
||||
|
@ -102,12 +102,12 @@ where
|
|||
pub(super) fn shallow_verify_memo(
|
||||
&self,
|
||||
db: &C::DbView,
|
||||
runtime: &Runtime,
|
||||
zalsa: &dyn Zalsa,
|
||||
database_key_index: DatabaseKeyIndex,
|
||||
memo: &Memo<C::Output<'_>>,
|
||||
) -> bool {
|
||||
let verified_at = memo.verified_at.load();
|
||||
let revision_now = runtime.current_revision();
|
||||
let revision_now = zalsa.current_revision();
|
||||
|
||||
tracing::debug!("{database_key_index:?}: shallow_verify_memo(memo = {memo:#?})",);
|
||||
|
||||
|
@ -116,10 +116,10 @@ where
|
|||
return true;
|
||||
}
|
||||
|
||||
if memo.check_durability(runtime) {
|
||||
if memo.check_durability(zalsa) {
|
||||
// No input of the suitable durability has changed since last verified.
|
||||
let db = db.as_dyn_database();
|
||||
memo.mark_as_verified(db, runtime, database_key_index);
|
||||
memo.mark_as_verified(db, revision_now, database_key_index);
|
||||
memo.mark_outputs_as_verified(db, database_key_index);
|
||||
return true;
|
||||
}
|
||||
|
@ -141,12 +141,12 @@ where
|
|||
old_memo: &Memo<C::Output<'_>>,
|
||||
active_query: &ActiveQueryGuard<'_>,
|
||||
) -> bool {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let zalsa = db.zalsa();
|
||||
let database_key_index = active_query.database_key_index;
|
||||
|
||||
tracing::debug!("{database_key_index:?}: deep_verify_memo(old_memo = {old_memo:#?})",);
|
||||
|
||||
if self.shallow_verify_memo(db, runtime, database_key_index, old_memo) {
|
||||
if self.shallow_verify_memo(db, zalsa, database_key_index, old_memo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
old_memo.mark_as_verified(db.as_dyn_database(), runtime, database_key_index);
|
||||
old_memo.mark_as_verified(
|
||||
db.as_dyn_database(),
|
||||
zalsa.current_revision(),
|
||||
database_key_index,
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ use arc_swap::{ArcSwap, Guard};
|
|||
use crossbeam::atomic::AtomicCell;
|
||||
|
||||
use crate::{
|
||||
hash::FxDashMap, key::DatabaseKeyIndex, local_state::QueryRevisions, Event, EventKind, Id,
|
||||
Revision, Runtime,
|
||||
hash::FxDashMap, key::DatabaseKeyIndex, local_state::QueryRevisions, storage::Zalsa, Event,
|
||||
EventKind, Id, Revision,
|
||||
};
|
||||
|
||||
use super::Configuration;
|
||||
|
@ -129,8 +129,8 @@ impl<V> Memo<V> {
|
|||
}
|
||||
}
|
||||
/// True if this memo is known not to have changed based on its durability.
|
||||
pub(super) fn check_durability(&self, runtime: &Runtime) -> bool {
|
||||
let last_changed = runtime.last_changed_revision(self.revisions.durability);
|
||||
pub(super) fn check_durability(&self, zalsa: &dyn Zalsa) -> bool {
|
||||
let last_changed = zalsa.last_changed_revision(self.revisions.durability);
|
||||
let verified_at = self.verified_at.load();
|
||||
tracing::debug!(
|
||||
"check_durability(last_changed={:?} <= verified_at={:?}) = {:?}",
|
||||
|
@ -146,7 +146,7 @@ impl<V> Memo<V> {
|
|||
pub(super) fn mark_as_verified(
|
||||
&self,
|
||||
db: &dyn crate::Database,
|
||||
runtime: &crate::Runtime,
|
||||
revision_now: Revision,
|
||||
database_key_index: DatabaseKeyIndex,
|
||||
) {
|
||||
db.salsa_event(Event {
|
||||
|
@ -156,7 +156,7 @@ impl<V> Memo<V> {
|
|||
},
|
||||
});
|
||||
|
||||
self.verified_at.store(runtime.current_revision());
|
||||
self.verified_at.store(revision_now);
|
||||
}
|
||||
|
||||
pub(super) fn mark_outputs_as_verified(
|
||||
|
|
|
@ -64,7 +64,7 @@ where
|
|||
// - a result that is verified in the current revision, because it was set, which will use the set value
|
||||
// - a result that is NOT verified and has untracked inputs, which will re-execute (and likely panic)
|
||||
|
||||
let revision = db.zalsa().runtime().current_revision();
|
||||
let revision = db.zalsa().current_revision();
|
||||
let mut revisions = QueryRevisions {
|
||||
changed_at: current_deps.changed_at,
|
||||
durability: current_deps.durability,
|
||||
|
@ -101,7 +101,7 @@ where
|
|||
executor: DatabaseKeyIndex,
|
||||
key: Id,
|
||||
) {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let zalsa = db.zalsa();
|
||||
|
||||
let memo = match self.memo_map.get(key) {
|
||||
Some(m) => m,
|
||||
|
@ -119,6 +119,10 @@ where
|
|||
}
|
||||
|
||||
let database_key_index = self.database_key_index(key);
|
||||
memo.mark_as_verified(db.as_dyn_database(), runtime, database_key_index);
|
||||
memo.mark_as_verified(
|
||||
db.as_dyn_database(),
|
||||
zalsa.current_revision(),
|
||||
database_key_index,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ impl SyncMap {
|
|||
local_state: &LocalState,
|
||||
database_key_index: DatabaseKeyIndex,
|
||||
) -> Option<ClaimGuard<'me>> {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let runtime = db.zalsa().runtimex();
|
||||
let thread_id = std::thread::current().id();
|
||||
match self.sync_map.entry(database_key_index.key_index) {
|
||||
dashmap::mapref::entry::Entry::Vacant(entry) => {
|
||||
|
|
|
@ -78,7 +78,7 @@ impl<Db: Database> Handle<Db> {
|
|||
/// same database!
|
||||
fn cancel_others(&mut self) {
|
||||
let zalsa = self.db().zalsa();
|
||||
zalsa.runtime().set_cancellation_flag();
|
||||
zalsa.set_cancellation_flag();
|
||||
|
||||
self.db().salsa_event(Event {
|
||||
thread_id: std::thread::current().id(),
|
||||
|
|
|
@ -19,7 +19,6 @@ use crate::{
|
|||
key::{DatabaseKeyIndex, DependencyIndex},
|
||||
local_state::{self, QueryOrigin},
|
||||
plumbing::{Jar, Stamp},
|
||||
runtime::Runtime,
|
||||
storage::IngredientIndex,
|
||||
Database, Durability, Id, Revision,
|
||||
};
|
||||
|
@ -121,18 +120,17 @@ impl<C: Configuration> IngredientImpl<C> {
|
|||
/// * `setter`, function that modifies the fields tuple; should only modify the element for `field_index`
|
||||
pub fn set_field<R>(
|
||||
&mut self,
|
||||
runtime: &mut Runtime,
|
||||
current_revision: Revision,
|
||||
id: C::Struct,
|
||||
field_index: usize,
|
||||
durability: Durability,
|
||||
setter: impl FnOnce(&mut C::Fields) -> R,
|
||||
) -> R {
|
||||
let revision = runtime.current_revision();
|
||||
let id: Id = id.as_id();
|
||||
let mut r = self.struct_map.update(id);
|
||||
let stamp = &mut r.stamps[field_index];
|
||||
stamp.durability = durability;
|
||||
stamp.changed_at = revision;
|
||||
stamp.changed_at = current_revision;
|
||||
setter(&mut r.fields)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use crate::input::{Configuration, IngredientImpl};
|
||||
use crate::{Durability, Runtime};
|
||||
use crate::{Durability, Revision};
|
||||
|
||||
/// Setter for a field of an input.
|
||||
pub trait Setter: Sized {
|
||||
|
@ -12,7 +12,7 @@ pub trait Setter: Sized {
|
|||
|
||||
#[must_use]
|
||||
pub struct SetterImpl<'setter, C: Configuration, S, F> {
|
||||
runtime: &'setter mut Runtime,
|
||||
current_revision: Revision,
|
||||
id: C::Struct,
|
||||
ingredient: &'setter mut IngredientImpl<C>,
|
||||
durability: Durability,
|
||||
|
@ -27,14 +27,14 @@ where
|
|||
S: FnOnce(&mut C::Fields, F) -> F,
|
||||
{
|
||||
pub fn new(
|
||||
runtime: &'setter mut Runtime,
|
||||
current_revision: Revision,
|
||||
id: C::Struct,
|
||||
field_index: usize,
|
||||
ingredient: &'setter mut IngredientImpl<C>,
|
||||
setter: S,
|
||||
) -> Self {
|
||||
SetterImpl {
|
||||
runtime,
|
||||
current_revision,
|
||||
id,
|
||||
field_index,
|
||||
ingredient,
|
||||
|
@ -59,7 +59,7 @@ where
|
|||
|
||||
fn to(self, value: F) -> F {
|
||||
let Self {
|
||||
runtime,
|
||||
current_revision,
|
||||
id,
|
||||
ingredient,
|
||||
durability,
|
||||
|
@ -68,7 +68,7 @@ where
|
|||
phantom: _,
|
||||
} = self;
|
||||
|
||||
ingredient.set_field(runtime, id, field_index, durability, |tuple| {
|
||||
ingredient.set_field(current_revision, id, field_index, durability, |tuple| {
|
||||
setter(tuple, value)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::Database;
|
|||
use crate::Event;
|
||||
use crate::EventKind;
|
||||
use crate::Revision;
|
||||
use crate::Runtime;
|
||||
use std::cell::Cell;
|
||||
use std::cell::RefCell;
|
||||
use std::ptr::NonNull;
|
||||
|
@ -321,21 +320,20 @@ impl LocalState {
|
|||
/// `salsa_event` is emitted when this method is called, so that should be
|
||||
/// used instead.
|
||||
pub(crate) fn unwind_if_revision_cancelled(&self, db: &dyn Database) {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let thread_id = std::thread::current().id();
|
||||
db.salsa_event(Event {
|
||||
thread_id,
|
||||
|
||||
kind: EventKind::WillCheckCancellation,
|
||||
});
|
||||
if runtime.load_cancellation_flag() {
|
||||
self.unwind_cancelled(runtime);
|
||||
let zalsa = db.zalsa();
|
||||
if zalsa.load_cancellation_flag() {
|
||||
self.unwind_cancelled(zalsa.current_revision());
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
pub(crate) fn unwind_cancelled(&self, runtime: &Runtime) {
|
||||
let current_revision = runtime.current_revision();
|
||||
pub(crate) fn unwind_cancelled(&self, current_revision: Revision) {
|
||||
self.report_untracked_read(current_revision);
|
||||
Cancelled::PendingWrite.throw();
|
||||
}
|
||||
|
@ -414,6 +412,10 @@ pub enum EdgeKind {
|
|||
Output,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub(crate) static ref EMPTY_DEPENDENCIES: Arc<[(EdgeKind, DependencyIndex)]> = Arc::new([]);
|
||||
}
|
||||
|
||||
/// The edges between a memoized value and other queries in the dependency graph.
|
||||
/// These edges include both dependency edges
|
||||
/// e.g., when creating the memoized value for Q0 executed another function Q1)
|
||||
|
@ -497,14 +499,14 @@ impl ActiveQueryGuard<'_> {
|
|||
/// which summarizes the other queries that were accessed during this
|
||||
/// query's execution.
|
||||
#[inline]
|
||||
pub(crate) fn pop(self, runtime: &Runtime) -> QueryRevisions {
|
||||
pub(crate) fn pop(self) -> QueryRevisions {
|
||||
// Extract accumulated inputs.
|
||||
let popped_query = self.complete();
|
||||
|
||||
// If this frame were a cycle participant, it would have unwound.
|
||||
assert!(popped_query.cycle.is_none());
|
||||
|
||||
popped_query.revisions(runtime)
|
||||
popped_query.revisions()
|
||||
}
|
||||
|
||||
/// If the active query is registered as a cycle participant, remove and
|
||||
|
|
|
@ -8,13 +8,9 @@ use crossbeam::atomic::AtomicCell;
|
|||
use parking_lot::Mutex;
|
||||
|
||||
use crate::{
|
||||
active_query::ActiveQuery,
|
||||
cycle::CycleRecoveryStrategy,
|
||||
durability::Durability,
|
||||
key::{DatabaseKeyIndex, DependencyIndex},
|
||||
local_state::{EdgeKind, LocalState},
|
||||
revision::AtomicRevision,
|
||||
Cancelled, Cycle, Database, Event, EventKind, Revision,
|
||||
active_query::ActiveQuery, cycle::CycleRecoveryStrategy, durability::Durability,
|
||||
key::DatabaseKeyIndex, local_state::LocalState, revision::AtomicRevision, Cancelled, Cycle,
|
||||
Database, Event, EventKind, Revision,
|
||||
};
|
||||
|
||||
use self::dependency_graph::DependencyGraph;
|
||||
|
@ -25,9 +21,6 @@ pub struct Runtime {
|
|||
/// Stores the next id to use for a snapshotted runtime (starts at 1).
|
||||
next_id: AtomicUsize,
|
||||
|
||||
/// Vector we can clone
|
||||
empty_dependencies: Arc<[(EdgeKind, DependencyIndex)]>,
|
||||
|
||||
/// Set to true when the current revision has been canceled.
|
||||
/// This is done when we an input is being changed. The flag
|
||||
/// is set back to false once the input has been changed.
|
||||
|
@ -89,7 +82,6 @@ impl Default for Runtime {
|
|||
.map(|_| AtomicRevision::start())
|
||||
.collect(),
|
||||
next_id: AtomicUsize::new(1),
|
||||
empty_dependencies: None.into_iter().collect(),
|
||||
revision_canceled: Default::default(),
|
||||
dependency_graph: Default::default(),
|
||||
}
|
||||
|
@ -112,10 +104,6 @@ impl Runtime {
|
|||
self.revisions[0].load()
|
||||
}
|
||||
|
||||
pub(crate) fn empty_dependencies(&self) -> Arc<[(EdgeKind, DependencyIndex)]> {
|
||||
self.empty_dependencies.clone()
|
||||
}
|
||||
|
||||
/// Reports that an input with durability `durability` changed.
|
||||
/// This will update the 'last changed at' values for every durability
|
||||
/// less than or equal to `durability` to the current revision.
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::ingredient::{Ingredient, Jar};
|
|||
use crate::nonce::{Nonce, NonceGenerator};
|
||||
use crate::runtime::Runtime;
|
||||
use crate::views::{Views, ViewsOf};
|
||||
use crate::Database;
|
||||
use crate::{Database, Durability, Revision};
|
||||
|
||||
pub fn views<Db: ?Sized + Database>(db: &Db) -> &Views {
|
||||
db.zalsa().views()
|
||||
|
@ -55,17 +55,36 @@ pub trait Zalsa {
|
|||
/// Gets an `&`-ref to an ingredient by index
|
||||
fn lookup_ingredient(&self, index: IngredientIndex) -> &dyn Ingredient;
|
||||
|
||||
/// Gets an `&mut`-ref to an ingredient by index; also returns the runtime for further use
|
||||
/// Gets an `&mut`-ref to an ingredient by index.
|
||||
///
|
||||
/// **Triggers a new revision.** Returns the `&mut` reference
|
||||
/// along with the new revision index.
|
||||
fn lookup_ingredient_mut(
|
||||
&mut self,
|
||||
index: IngredientIndex,
|
||||
) -> (&mut dyn Ingredient, &mut Runtime);
|
||||
) -> (&mut dyn Ingredient, Revision);
|
||||
|
||||
/// Gets the salsa runtime
|
||||
fn runtime(&self) -> &Runtime;
|
||||
fn runtimex(&self) -> &Runtime;
|
||||
|
||||
/// Gets the salsa runtime
|
||||
fn runtime_mut(&mut self) -> &mut Runtime;
|
||||
/// Return the current revision
|
||||
fn current_revision(&self) -> Revision;
|
||||
|
||||
/// Increment revision counter.
|
||||
///
|
||||
/// **Triggers a new revision.**
|
||||
fn new_revision(&mut self) -> Revision;
|
||||
|
||||
/// Return the time when an input of durability `durability` last changed
|
||||
fn last_changed_revision(&self, durability: Durability) -> Revision;
|
||||
|
||||
/// True if any threads have signalled for cancellation
|
||||
fn load_cancellation_flag(&self) -> bool;
|
||||
|
||||
/// Signal for cancellation, indicating current thread is trying to get unique access.
|
||||
fn set_cancellation_flag(&self);
|
||||
|
||||
/// Reports a (synthetic) tracked write to "some input of the given durability".
|
||||
fn report_tracked_write(&mut self, durability: Durability);
|
||||
}
|
||||
|
||||
impl<Db: Database> Zalsa for Storage<Db> {
|
||||
|
@ -119,19 +138,11 @@ impl<Db: Database> Zalsa for Storage<Db> {
|
|||
&**self.ingredients_vec.get(index.as_usize()).unwrap()
|
||||
}
|
||||
|
||||
fn runtime(&self) -> &Runtime {
|
||||
&self.runtime
|
||||
}
|
||||
|
||||
fn runtime_mut(&mut self) -> &mut Runtime {
|
||||
&mut self.runtime
|
||||
}
|
||||
|
||||
fn lookup_ingredient_mut(
|
||||
&mut self,
|
||||
index: IngredientIndex,
|
||||
) -> (&mut dyn Ingredient, &mut Runtime) {
|
||||
self.runtime.new_revision();
|
||||
) -> (&mut dyn Ingredient, Revision) {
|
||||
let new_revision = self.runtime.new_revision();
|
||||
|
||||
for index in self.ingredients_requiring_reset.iter() {
|
||||
self.ingredients_vec
|
||||
|
@ -142,9 +153,37 @@ impl<Db: Database> Zalsa for Storage<Db> {
|
|||
|
||||
(
|
||||
&mut **self.ingredients_vec.get_mut(index.as_usize()).unwrap(),
|
||||
&mut self.runtime,
|
||||
new_revision,
|
||||
)
|
||||
}
|
||||
|
||||
fn current_revision(&self) -> Revision {
|
||||
self.runtime.current_revision()
|
||||
}
|
||||
|
||||
fn load_cancellation_flag(&self) -> bool {
|
||||
self.runtime.load_cancellation_flag()
|
||||
}
|
||||
|
||||
fn report_tracked_write(&mut self, durability: Durability) {
|
||||
self.runtime.report_tracked_write(durability)
|
||||
}
|
||||
|
||||
fn runtimex(&self) -> &Runtime {
|
||||
&self.runtime
|
||||
}
|
||||
|
||||
fn last_changed_revision(&self, durability: Durability) -> Revision {
|
||||
self.runtime.last_changed_revision(durability)
|
||||
}
|
||||
|
||||
fn set_cancellation_flag(&self) {
|
||||
self.runtime.set_cancellation_flag()
|
||||
}
|
||||
|
||||
fn new_revision(&mut self) -> Revision {
|
||||
self.runtime.new_revision()
|
||||
}
|
||||
}
|
||||
|
||||
/// Nonce type representing the underlying database storage.
|
||||
|
|
|
@ -307,7 +307,7 @@ where
|
|||
let (id, new_id) = self.intern(entity_key);
|
||||
local_state.add_output(self.database_key_index(id).into());
|
||||
|
||||
let current_revision = zalsa.runtime().current_revision();
|
||||
let current_revision = zalsa.current_revision();
|
||||
if new_id {
|
||||
// This is a new tracked struct, so create an entry in the struct map.
|
||||
|
||||
|
@ -379,7 +379,7 @@ where
|
|||
///
|
||||
/// If the struct has not been created in this revision.
|
||||
pub fn lookup_struct<'db>(&'db self, db: &'db dyn Database, id: Id) -> C::Struct<'db> {
|
||||
let current_revision = db.zalsa().runtime().current_revision();
|
||||
let current_revision = db.zalsa().current_revision();
|
||||
self.struct_map.get(current_revision, id)
|
||||
}
|
||||
|
||||
|
@ -458,9 +458,9 @@ where
|
|||
_executor: DatabaseKeyIndex,
|
||||
output_key: Option<crate::Id>,
|
||||
) {
|
||||
let runtime = db.zalsa().runtime();
|
||||
let current_revision = db.zalsa().current_revision();
|
||||
let output_key = output_key.unwrap();
|
||||
self.struct_map.validate(runtime, output_key);
|
||||
self.struct_map.validate(current_revision, output_key);
|
||||
}
|
||||
|
||||
fn remove_stale_output(
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
use crossbeam::queue::SegQueue;
|
||||
use dashmap::mapref::one::RefMut;
|
||||
|
||||
use crate::{alloc::Alloc, hash::FxDashMap, Id, Revision, Runtime};
|
||||
use crate::{alloc::Alloc, hash::FxDashMap, Id, Revision};
|
||||
|
||||
use super::{Configuration, KeyStruct, Value};
|
||||
|
||||
|
@ -99,7 +99,7 @@ where
|
|||
unsafe { C::struct_from_raw(pointer) }
|
||||
}
|
||||
|
||||
pub fn validate<'db>(&'db self, runtime: &'db Runtime, id: Id) {
|
||||
pub fn validate<'db>(&'db self, current_revision: Revision, id: Id) {
|
||||
let mut data = self.map.get_mut(&id).unwrap();
|
||||
|
||||
// UNSAFE: We never permit `&`-access in the current revision until data.created_at
|
||||
|
@ -107,7 +107,6 @@ where
|
|||
let data = unsafe { data.as_mut() };
|
||||
|
||||
// Never update a struct twice in the same revision.
|
||||
let current_revision = runtime.current_revision();
|
||||
assert!(data.created_at < current_revision);
|
||||
data.created_at = current_revision;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ where
|
|||
/// The caller is responible for selecting the appropriate element.
|
||||
pub fn field<'db>(&'db self, db: &'db dyn Database, id: Id) -> &'db C::Fields<'db> {
|
||||
local_state::attach(db, |local_state| {
|
||||
let current_revision = db.zalsa().runtime().current_revision();
|
||||
let current_revision = db.zalsa().current_revision();
|
||||
let data = self.struct_map.get(current_revision, id);
|
||||
let data = C::deref_struct(data);
|
||||
let changed_at = data.revisions[self.field_index];
|
||||
|
@ -85,7 +85,7 @@ where
|
|||
input: Option<Id>,
|
||||
revision: crate::Revision,
|
||||
) -> bool {
|
||||
let current_revision = db.zalsa().runtime().current_revision();
|
||||
let current_revision = db.zalsa().current_revision();
|
||||
let id = input.unwrap();
|
||||
let data = self.struct_map.get(current_revision, id);
|
||||
let data = C::deref_struct(data);
|
||||
|
|
Loading…
Reference in a new issue