salsa/tests/parallel/cycle_a_t1_b_t2_fallback.rs
Micha Reiser 2b5188778e
Some checks are pending
Test / Test (push) Waiting to run
Test / Miri (push) Waiting to run
Test / Shuttle (push) Waiting to run
Test / Benchmarks (push) Waiting to run
Book / Book (push) Waiting to run
Book / Deploy (push) Blocked by required conditions
Release-plz / Release-plz release (push) Waiting to run
Release-plz / Release-plz PR (push) Waiting to run
fix: multithreaded nested fixpoint iteration (#882)
* Set `validate_final` in `execute` after removing the last cycle head

* Add runaway query repro

* Add tracing

* Fix part 1

* Fix `cycle_head_kinds` to always return provisional for memos that aren't verified final (They should be validated by `validate_same_iteration` or wait for the cycle head

* Fix cycle error

* Documentation

* Fix await for queries depending on initial value

* correctly initialize queued

* Cleanup

* Short circuit if entire query runs on single thread

* Move parallel code into its own method

* Rename method, add self_key to queued

* Revert self-key changes

* Move check *after* `deep_verify_memo`

* Add a test for a cycle with changing cycle heads

* Short circuit more often

* Consider iteration in `validate_provisional`

* Only yield if all heads result in a cycle. Retry if even just one inner cycle made progress (in which case there's a probably a new memo)

* Fix hangs

* Cargo fmt

* clippy

* Fix hang if cycle initial panics

* Rename `cycle_head_kind` enable `cycle_a_t1_b_t2_fallback` shuttle test

* Cleanup

* Docs
2025-06-01 08:45:37 +00:00

68 lines
1.5 KiB
Rust

//! Test a specific cycle scenario:
//!
//! ```text
//! Thread T1 Thread T2
//! --------- ---------
//! | |
//! v |
//! query_a() |
//! ^ | v
//! | +------------> query_b()
//! | |
//! +--------------------+
//! ```
use crate::KnobsDatabase;
const FALLBACK_A: u32 = 0b01;
const FALLBACK_B: u32 = 0b10;
const OFFSET_A: u32 = 0b0100;
const OFFSET_B: u32 = 0b1000;
// Signal 1: T1 has entered `query_a`
// Signal 2: T2 has entered `query_b`
#[salsa::tracked(cycle_result=cycle_result_a)]
fn query_a(db: &dyn KnobsDatabase) -> u32 {
db.signal(1);
// Wait for Thread T2 to enter `query_b` before we continue.
db.wait_for(2);
query_b(db) | OFFSET_A
}
#[salsa::tracked(cycle_result=cycle_result_b)]
fn query_b(db: &dyn KnobsDatabase) -> u32 {
// Wait for Thread T1 to enter `query_a` before we continue.
db.wait_for(1);
db.signal(2);
query_a(db) | OFFSET_B
}
fn cycle_result_a(_db: &dyn KnobsDatabase) -> u32 {
FALLBACK_A
}
fn cycle_result_b(_db: &dyn KnobsDatabase) -> u32 {
FALLBACK_B
}
#[test_log::test]
fn the_test() {
use crate::sync::thread;
use crate::Knobs;
crate::sync::check(|| {
let db_t1 = Knobs::default();
let db_t2 = db_t1.clone();
let t1 = thread::spawn(move || query_a(&db_t1));
let t2 = thread::spawn(move || query_b(&db_t2));
let (r_t1, r_t2) = (t1.join(), t2.join());
assert_eq!((r_t1.unwrap(), r_t2.unwrap()), (FALLBACK_A, FALLBACK_B));
});
}