diff --git a/Cargo.toml b/Cargo.toml index 09e1f3d3..c7ec1e45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/components/salsa-macro-rules/src/setup_input_struct.rs b/components/salsa-macro-rules/src/setup_input_struct.rs index 10257b6d..ccdc60c9 100644 --- a/components/salsa-macro-rules/src/setup_input_struct.rs +++ b/components/salsa-macro-rules/src/setup_input_struct.rs @@ -86,12 +86,12 @@ macro_rules! setup_input_struct { }) } - pub fn ingredient_mut(db: &mut dyn $zalsa::Database) -> (&mut $zalsa_struct::IngredientImpl, &mut $zalsa::Runtime) { + pub fn ingredient_mut(db: &mut dyn $zalsa::Database) -> (&mut $zalsa_struct::IngredientImpl, $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>(); - (ingredient, runtime) + (ingredient, current_revision) } } diff --git a/src/accumulator.rs b/src/accumulator.rs index f00be0d8..1e9c368d 100644 --- a/src/accumulator.rs +++ b/src/accumulator.rs @@ -81,8 +81,7 @@ impl IngredientImpl { 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 Ingredient for IngredientImpl { output_key: Option, ) { 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; diff --git a/src/active_query.rs b/src/active_query.rs index 46ef8f02..8f575b75 100644 --- a/src/active_query.rs +++ b/src/active_query.rs @@ -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() }; diff --git a/src/database.rs b/src/database.rs index 5d01801b..ba39cf66 100644 --- a/src/database.rs +++ b/src/database.rs @@ -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 AsDynDatabase for T { } pub fn current_revision(db: &Db) -> Revision { - db.zalsa().runtime().current_revision() + db.zalsa().current_revision() } impl dyn Database { diff --git a/src/function/accumulated.rs b/src/function/accumulated.rs index e533fb28..d1fc003d 100644 --- a/src/function/accumulated.rs +++ b/src/function/accumulated.rs @@ -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) = >::from_db(db) else { return vec![]; diff --git a/src/function/execute.rs b/src/function/execute.rs index f564c3ce..7cbbf62d 100644 --- a/src/function/execute.rs +++ b/src/function/execute.rs @@ -27,8 +27,7 @@ where opt_old_memo: Option>>>, ) -> 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 diff --git a/src/function/fetch.rs b/src/function/fetch.rs index 5b25a70d..2474acbe 100644 --- a/src/function/fetch.rs +++ b/src/function/fetch.rs @@ -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() diff --git a/src/function/maybe_changed_after.rs b/src/function/maybe_changed_after.rs index 80ec605a..a9426cf7 100644 --- a/src/function/maybe_changed_after.rs +++ b/src/function/maybe_changed_after.rs @@ -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>, ) -> 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>, 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 } } diff --git a/src/function/memo.rs b/src/function/memo.rs index 074fcf1a..ef26a014 100644 --- a/src/function/memo.rs +++ b/src/function/memo.rs @@ -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 Memo { } } /// 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 Memo { 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 Memo { }, }); - self.verified_at.store(runtime.current_revision()); + self.verified_at.store(revision_now); } pub(super) fn mark_outputs_as_verified( diff --git a/src/function/specify.rs b/src/function/specify.rs index 9d2a3dd2..37e88082 100644 --- a/src/function/specify.rs +++ b/src/function/specify.rs @@ -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, + ); } } diff --git a/src/function/sync.rs b/src/function/sync.rs index d59cc7e5..0f1d5178 100644 --- a/src/function/sync.rs +++ b/src/function/sync.rs @@ -28,7 +28,7 @@ impl SyncMap { local_state: &LocalState, database_key_index: DatabaseKeyIndex, ) -> Option> { - 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) => { diff --git a/src/handle.rs b/src/handle.rs index 6b4dd167..28661888 100644 --- a/src/handle.rs +++ b/src/handle.rs @@ -78,7 +78,7 @@ impl Handle { /// 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(), diff --git a/src/input.rs b/src/input.rs index ba1bd41a..6fa683e6 100644 --- a/src/input.rs +++ b/src/input.rs @@ -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 IngredientImpl { /// * `setter`, function that modifies the fields tuple; should only modify the element for `field_index` pub fn set_field( &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) } diff --git a/src/input/setter.rs b/src/input/setter.rs index a976aad0..e19d9c95 100644 --- a/src/input/setter.rs +++ b/src/input/setter.rs @@ -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, 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, 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) }) } diff --git a/src/local_state.rs b/src/local_state.rs index c83f9c90..4531809d 100644 --- a/src/local_state.rs +++ b/src/local_state.rs @@ -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; @@ -317,21 +316,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(); } @@ -410,6 +408,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) @@ -493,14 +495,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 diff --git a/src/runtime.rs b/src/runtime.rs index 04b83645..3db4a6a6 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -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. diff --git a/src/storage.rs b/src/storage.rs index 3139cbd6..0ecf132e 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -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: &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 Zalsa for Storage { @@ -119,19 +138,11 @@ impl Zalsa for Storage { &**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 Zalsa for Storage { ( &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. diff --git a/src/tracked_struct.rs b/src/tracked_struct.rs index 78bba1d8..0621782b 100644 --- a/src/tracked_struct.rs +++ b/src/tracked_struct.rs @@ -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, ) { - 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( diff --git a/src/tracked_struct/struct_map.rs b/src/tracked_struct/struct_map.rs index 4779a278..b8ea1578 100644 --- a/src/tracked_struct/struct_map.rs +++ b/src/tracked_struct/struct_map.rs @@ -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; } diff --git a/src/tracked_struct/tracked_field.rs b/src/tracked_struct/tracked_field.rs index a10eb31f..7a6b7b42 100644 --- a/src/tracked_struct/tracked_field.rs +++ b/src/tracked_struct/tracked_field.rs @@ -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, 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);