mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-22 21:05:11 +00:00
fix gc and volatile tests
This commit is contained in:
parent
6cf1ffd24a
commit
c040b0c673
4 changed files with 100 additions and 10 deletions
|
@ -942,15 +942,6 @@ where
|
||||||
fn sweep(&self, db: &DB, strategy: SweepStrategy) {
|
fn sweep(&self, db: &DB, strategy: SweepStrategy) {
|
||||||
let mut map_write = self.map.write();
|
let mut map_write = self.map.write();
|
||||||
let revision_now = db.salsa_runtime().current_revision();
|
let revision_now = db.salsa_runtime().current_revision();
|
||||||
match (strategy.discard_if, strategy.discard_what) {
|
|
||||||
(DiscardIf::Always, DiscardWhat::Everything) => {
|
|
||||||
debug!("sweep({:?}): clearing the table", Q::default());
|
|
||||||
map_write.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(DiscardIf::Never, _) | (_, DiscardWhat::Nothing) => return,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
map_write.retain(|key, query_state| {
|
map_write.retain(|key, query_state| {
|
||||||
match query_state {
|
match query_state {
|
||||||
// Leave stuff that is currently being computed -- the
|
// Leave stuff that is currently being computed -- the
|
||||||
|
@ -972,6 +963,19 @@ where
|
||||||
revision_now
|
revision_now
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Check if this memo read something "untracked"
|
||||||
|
// -- meaning non-deterministic. In this case, we
|
||||||
|
// can only collect "outdated" data that wasn't
|
||||||
|
// used in the current revision. This is because
|
||||||
|
// if we collected something from the current
|
||||||
|
// revision, we might wind up re-executing the
|
||||||
|
// query later in the revision and getting a
|
||||||
|
// distinct result.
|
||||||
|
let is_volatile = match memo.inputs {
|
||||||
|
MemoInputs::Untracked => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
// Since we don't acquire a query lock in this
|
// Since we don't acquire a query lock in this
|
||||||
// method, it *is* possible for the revision to
|
// method, it *is* possible for the revision to
|
||||||
// change while we are executing. However, it is
|
// change while we are executing. However, it is
|
||||||
|
@ -982,7 +986,19 @@ where
|
||||||
assert!(memo.verified_at <= revision_now);
|
assert!(memo.verified_at <= revision_now);
|
||||||
match strategy.discard_if {
|
match strategy.discard_if {
|
||||||
DiscardIf::Never => unreachable!(),
|
DiscardIf::Never => unreachable!(),
|
||||||
|
|
||||||
|
// If we are only discarding outdated things,
|
||||||
|
// and this is not outdated, keep it.
|
||||||
DiscardIf::Outdated if memo.verified_at == revision_now => true,
|
DiscardIf::Outdated if memo.verified_at == revision_now => true,
|
||||||
|
|
||||||
|
// As explained on the `is_volatile` variable
|
||||||
|
// definition, if this is a volatile entry, we
|
||||||
|
// can't discard it unless it is outdated.
|
||||||
|
DiscardIf::Always if is_volatile && memo.verified_at == revision_now => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we can discard -- discard whatever the user requested.
|
||||||
DiscardIf::Outdated | DiscardIf::Always => match strategy.discard_what {
|
DiscardIf::Outdated | DiscardIf::Always => match strategy.discard_what {
|
||||||
DiscardWhat::Nothing => unreachable!(),
|
DiscardWhat::Nothing => unreachable!(),
|
||||||
DiscardWhat::Values => {
|
DiscardWhat::Values => {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::group;
|
use crate::group;
|
||||||
use crate::interned;
|
use crate::interned;
|
||||||
use crate::log::{HasLog, Log};
|
use crate::log::{HasLog, Log};
|
||||||
|
use crate::volatile_tests;
|
||||||
|
|
||||||
#[salsa::database(group::Gc, interned::Intern)]
|
#[salsa::database(group::Gc, interned::Intern, volatile_tests::Volatile)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct DatabaseImpl {
|
pub(crate) struct DatabaseImpl {
|
||||||
runtime: salsa::Runtime<DatabaseImpl>,
|
runtime: salsa::Runtime<DatabaseImpl>,
|
||||||
|
|
|
@ -16,3 +16,4 @@ mod group;
|
||||||
mod interned;
|
mod interned;
|
||||||
mod log;
|
mod log;
|
||||||
mod shallow_constant_tests;
|
mod shallow_constant_tests;
|
||||||
|
mod volatile_tests;
|
||||||
|
|
72
tests/gc/volatile_tests.rs
Normal file
72
tests/gc/volatile_tests.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use crate::db;
|
||||||
|
use salsa::{Database, SweepStrategy};
|
||||||
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Query group for tests for how interned keys interact with GC.
|
||||||
|
#[salsa::query_group(Volatile)]
|
||||||
|
pub(crate) trait VolatileDatabase {
|
||||||
|
#[salsa::input]
|
||||||
|
fn atomic_cell(&self) -> Arc<AtomicU32>;
|
||||||
|
|
||||||
|
/// Underlying volatile query.
|
||||||
|
#[salsa::volatile]
|
||||||
|
fn volatile(&self) -> u32;
|
||||||
|
|
||||||
|
/// This just executes the intern query and returns the result.
|
||||||
|
fn repeat1(&self) -> u32;
|
||||||
|
|
||||||
|
/// Same as `repeat_intern1`. =)
|
||||||
|
fn repeat2(&self) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn volatile(db: &impl VolatileDatabase) -> u32 {
|
||||||
|
db.atomic_cell().load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn repeat1(db: &impl VolatileDatabase) -> u32 {
|
||||||
|
db.volatile()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn repeat2(db: &impl VolatileDatabase) -> u32 {
|
||||||
|
db.volatile()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn consistency_no_gc() {
|
||||||
|
let mut db = db::DatabaseImpl::default();
|
||||||
|
|
||||||
|
let cell = Arc::new(AtomicU32::new(22));
|
||||||
|
|
||||||
|
db.set_atomic_cell(cell.clone());
|
||||||
|
|
||||||
|
let v1 = db.repeat1();
|
||||||
|
|
||||||
|
cell.store(23, Ordering::SeqCst);
|
||||||
|
|
||||||
|
let v2 = db.repeat2();
|
||||||
|
|
||||||
|
assert_eq!(v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn consistency_with_gc() {
|
||||||
|
let mut db = db::DatabaseImpl::default();
|
||||||
|
|
||||||
|
let cell = Arc::new(AtomicU32::new(22));
|
||||||
|
|
||||||
|
db.set_atomic_cell(cell.clone());
|
||||||
|
|
||||||
|
let v1 = db.repeat1();
|
||||||
|
|
||||||
|
cell.store(23, Ordering::SeqCst);
|
||||||
|
db.query(VolatileQuery).sweep(
|
||||||
|
SweepStrategy::default()
|
||||||
|
.discard_everything()
|
||||||
|
.sweep_all_revisions(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let v2 = db.repeat2();
|
||||||
|
|
||||||
|
assert_eq!(v1, v2);
|
||||||
|
}
|
Loading…
Reference in a new issue