Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::panic::UnwindSafe;

use accumulated::{Accumulated, AnyAccumulated};

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::function::VerifyResult;
use crate::ingredient::{Ingredient, Jar};
use crate::plumbing::ZalsaLocal;
Expand Down Expand Up @@ -106,7 +106,7 @@ impl<A: Accumulator> Ingredient for IngredientImpl<A> {
_db: crate::database::RawDatabase<'_>,
_input: Id,
_revision: Revision,
_cycle_heads: &mut CycleHeads,
_cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
panic!("nothing should ever depend on an accumulator directly")
}
Expand Down
47 changes: 31 additions & 16 deletions src/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,6 @@ impl CycleHeads {
}
}

#[inline]
pub(crate) fn push_initial(&mut self, database_key_index: DatabaseKeyIndex) {
if let Some(existing) = self
.0
.iter()
.find(|candidate| candidate.database_key_index == database_key_index)
{
assert_eq!(existing.iteration_count, IterationCount::initial());
} else {
self.0.push(CycleHead {
database_key_index,
iteration_count: IterationCount::initial(),
});
}
}

#[inline]
pub(crate) fn extend(&mut self, other: &Self) {
self.0.reserve(other.0.len());
Expand Down Expand Up @@ -247,6 +231,37 @@ pub(crate) fn empty_cycle_heads() -> &'static CycleHeads {
EMPTY_CYCLE_HEADS.get_or_init(|| CycleHeads(ThinVec::new()))
}

/// Set of cycle head database keys.
///
/// Unlike [`CycleHeads`], this type doesn't track the iteration count
/// of each cycle head.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CycleHeadKeys(Vec<DatabaseKeyIndex>);

impl CycleHeadKeys {
pub(crate) fn new() -> Self {
Self(Vec::new())
}

pub(crate) fn insert(&mut self, database_key_index: DatabaseKeyIndex) {
if !self.0.contains(&database_key_index) {
self.0.push(database_key_index);
}
}

pub(crate) fn remove(&mut self, value: &DatabaseKeyIndex) -> bool {
let found = self.0.iter().position(|&head| head == *value);
let Some(found) = found else { return false };

self.0.swap_remove(found);
true
}

pub(crate) fn is_empty(&self) -> bool {
self.0.is_empty()
}
}

#[derive(Debug, PartialEq, Eq)]
pub enum ProvisionalStatus {
Provisional { iteration: IterationCount },
Expand Down
5 changes: 3 additions & 2 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use std::sync::OnceLock;
pub(crate) use sync::SyncGuard;

use crate::cycle::{
empty_cycle_heads, CycleHeads, CycleRecoveryAction, CycleRecoveryStrategy, ProvisionalStatus,
empty_cycle_heads, CycleHeadKeys, CycleHeads, CycleRecoveryAction, CycleRecoveryStrategy,
ProvisionalStatus,
};
use crate::database::RawDatabase;
use crate::function::delete::DeletedEntries;
Expand Down Expand Up @@ -265,7 +266,7 @@ where
db: RawDatabase<'_>,
input: Id,
revision: Revision,
cycle_heads: &mut CycleHeads,
cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
// SAFETY: The `db` belongs to the ingredient as per caller invariant
let db = unsafe { self.view_caster().downcast_unchecked(db) };
Expand Down
4 changes: 2 additions & 2 deletions src/function/fetch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::cycle::{CycleHeads, CycleRecoveryStrategy, IterationCount};
use crate::cycle::{CycleHeadKeys, CycleHeads, CycleRecoveryStrategy, IterationCount};
use crate::function::memo::Memo;
use crate::function::sync::ClaimResult;
use crate::function::{Configuration, IngredientImpl, VerifyResult};
Expand Down Expand Up @@ -222,7 +222,7 @@ where

if let Some(old_memo) = opt_old_memo {
if old_memo.value.is_some() {
let mut cycle_heads = CycleHeads::default();
let mut cycle_heads = CycleHeadKeys::new();
if let VerifyResult::Unchanged { .. } =
self.deep_verify_memo(db, zalsa, old_memo, database_key_index, &mut cycle_heads)
{
Expand Down
12 changes: 6 additions & 6 deletions src/function/maybe_changed_after.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[cfg(feature = "accumulator")]
use crate::accumulator::accumulated_map::InputAccumulatedValues;
use crate::cycle::{CycleHeads, CycleRecoveryStrategy, IterationCount, ProvisionalStatus};
use crate::cycle::{CycleHeadKeys, CycleRecoveryStrategy, IterationCount, ProvisionalStatus};
use crate::function::memo::Memo;
use crate::function::sync::ClaimResult;
use crate::function::{Configuration, IngredientImpl};
Expand Down Expand Up @@ -51,7 +51,7 @@ where
db: &'db C::DbView,
id: Id,
revision: Revision,
cycle_heads: &mut CycleHeads,
cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
let (zalsa, zalsa_local) = db.zalsas();
let memo_ingredient_index = self.memo_ingredient_index(zalsa, id);
Expand Down Expand Up @@ -108,7 +108,7 @@ where
key_index: Id,
revision: Revision,
memo_ingredient_index: MemoIngredientIndex,
cycle_heads: &mut CycleHeads,
cycle_heads: &mut CycleHeadKeys,
) -> Option<VerifyResult> {
let database_key_index = self.database_key_index(key_index);

Expand All @@ -135,7 +135,7 @@ where
crate::tracing::debug!(
"hit cycle at {database_key_index:?} in `maybe_changed_after`, returning fixpoint initial value",
);
cycle_heads.push_initial(database_key_index);
cycle_heads.insert(database_key_index);
return Some(VerifyResult::unchanged());
}
},
Expand Down Expand Up @@ -406,7 +406,7 @@ where
zalsa: &Zalsa,
old_memo: &Memo<'_, C>,
database_key_index: DatabaseKeyIndex,
cycle_heads: &mut CycleHeads,
cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
crate::tracing::debug!(
"{database_key_index:?}: deep_verify_memo(old_memo = {old_memo:#?})",
Expand Down Expand Up @@ -447,7 +447,7 @@ where
// are tracked by the outer query. Nothing should have changed assuming that the
// fixpoint initial function is deterministic.
QueryOriginRef::FixpointInitial => {
cycle_heads.push_initial(database_key_index);
cycle_heads.insert(database_key_index);
VerifyResult::unchanged()
}
QueryOriginRef::DerivedUntracked(_) => {
Expand Down
5 changes: 3 additions & 2 deletions src/ingredient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::any::{Any, TypeId};
use std::fmt;

use crate::cycle::{
empty_cycle_heads, CycleHeads, CycleRecoveryStrategy, IterationCount, ProvisionalStatus,
empty_cycle_heads, CycleHeadKeys, CycleHeads, CycleRecoveryStrategy, IterationCount,
ProvisionalStatus,
};
use crate::database::RawDatabase;
use crate::function::VerifyResult;
Expand Down Expand Up @@ -51,7 +52,7 @@ pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {
db: crate::database::RawDatabase<'_>,
input: Id,
revision: Revision,
cycle_heads: &mut CycleHeads,
cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult;

/// Returns information about the current provisional status of `input`.
Expand Down
4 changes: 2 additions & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod singleton;

use input_field::FieldIngredientImpl;

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::function::VerifyResult;
use crate::id::{AsId, FromId, FromIdWithDb};
use crate::ingredient::Ingredient;
Expand Down Expand Up @@ -226,7 +226,7 @@ impl<C: Configuration> Ingredient for IngredientImpl<C> {
_db: crate::database::RawDatabase<'_>,
_input: Id,
_revision: Revision,
_cycle_heads: &mut CycleHeads,
_cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
// Input ingredients are just a counter, they store no data, they are immortal.
// Their *fields* are stored in function ingredients elsewhere.
Expand Down
4 changes: 2 additions & 2 deletions src/input/input_field.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;
use std::marker::PhantomData;

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::function::VerifyResult;
use crate::ingredient::Ingredient;
use crate::input::{Configuration, IngredientImpl, Value};
Expand Down Expand Up @@ -56,7 +56,7 @@ where
_db: crate::database::RawDatabase<'_>,
input: Id,
revision: Revision,
_cycle_heads: &mut CycleHeads,
_cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
let value = <IngredientImpl<C>>::data(zalsa, input);
VerifyResult::changed_if(value.revisions[self.field_index] > revision)
Expand Down
4 changes: 2 additions & 2 deletions src/interned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crossbeam_utils::CachePadded;
use intrusive_collections::{intrusive_adapter, LinkedList, LinkedListLink, UnsafeRef};
use rustc_hash::FxBuildHasher;

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::durability::Durability;
use crate::function::VerifyResult;
use crate::id::{AsId, FromId};
Expand Down Expand Up @@ -797,7 +797,7 @@ where
_db: crate::database::RawDatabase<'_>,
input: Id,
_revision: Revision,
_cycle_heads: &mut CycleHeads,
_cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
// Record the current revision as active.
let current_revision = zalsa.current_revision();
Expand Down
4 changes: 2 additions & 2 deletions src/key.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::fmt;

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::function::VerifyResult;
use crate::zalsa::{IngredientIndex, Zalsa};
use crate::Id;
Expand Down Expand Up @@ -39,7 +39,7 @@ impl DatabaseKeyIndex {
db: crate::database::RawDatabase<'_>,
zalsa: &Zalsa,
last_verified_at: crate::Revision,
cycle_heads: &mut CycleHeads,
cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
// SAFETY: The `db` belongs to the ingredient
unsafe {
Expand Down
4 changes: 2 additions & 2 deletions src/tracked_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crossbeam_queue::SegQueue;
use thin_vec::ThinVec;
use tracked_field::FieldIngredientImpl;

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::function::VerifyResult;
use crate::id::{AsId, FromId};
use crate::ingredient::{Ingredient, Jar};
Expand Down Expand Up @@ -817,7 +817,7 @@ where
_db: crate::database::RawDatabase<'_>,
_input: Id,
_revision: Revision,
_cycle_heads: &mut CycleHeads,
_cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
// Any change to a tracked struct results in a new ID generation.
VerifyResult::unchanged()
Expand Down
4 changes: 2 additions & 2 deletions src/tracked_struct/tracked_field.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::marker::PhantomData;

use crate::cycle::CycleHeads;
use crate::cycle::CycleHeadKeys;
use crate::function::VerifyResult;
use crate::ingredient::Ingredient;
use crate::sync::Arc;
Expand Down Expand Up @@ -61,7 +61,7 @@ where
_db: crate::database::RawDatabase<'_>,
input: Id,
revision: crate::Revision,
_cycle_heads: &mut CycleHeads,
_cycle_heads: &mut CycleHeadKeys,
) -> VerifyResult {
let data = <super::IngredientImpl<C>>::data(zalsa.table(), input);
let field_changed_at = data.revisions[self.field_index];
Expand Down