salsa/tests/parallel/cycle_a_t1_b_t2.rs
Ibraheem Ahmed 0414d89327
Replace loom with shuttle (#876)
* replace loom with shuttle

* inline `empty_cycle_heads`

* ignore failing shuttle test
2025-05-23 15:28:51 +00:00

75 lines
1.8 KiB
Rust

//! Test a specific cycle scenario:
//!
//! ```text
//! Thread T1 Thread T2
//! --------- ---------
//! | |
//! v |
//! query_a() |
//! ^ | v
//! | +------------> query_b()
//! | |
//! +--------------------+
//! ```
use crate::sync::thread;
use crate::{Knobs, KnobsDatabase};
use salsa::CycleRecoveryAction;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, salsa::Update)]
struct CycleValue(u32);
const MIN: CycleValue = CycleValue(0);
const MAX: CycleValue = CycleValue(3);
// Signal 1: T1 has entered `query_a`
// Signal 2: T2 has entered `query_b`
#[salsa::tracked(cycle_fn=cycle_fn, cycle_initial=initial)]
fn query_a(db: &dyn KnobsDatabase) -> CycleValue {
db.signal(1);
// Wait for Thread T2 to enter `query_b` before we continue.
db.wait_for(2);
query_b(db)
}
#[salsa::tracked(cycle_fn=cycle_fn, cycle_initial=initial)]
fn query_b(db: &dyn KnobsDatabase) -> CycleValue {
// Wait for Thread T1 to enter `query_a` before we continue.
db.wait_for(1);
db.signal(2);
let a_value = query_a(db);
CycleValue(a_value.0 + 1).min(MAX)
}
fn cycle_fn(
_db: &dyn KnobsDatabase,
_value: &CycleValue,
_count: u32,
) -> CycleRecoveryAction<CycleValue> {
CycleRecoveryAction::Iterate
}
fn initial(_db: &dyn KnobsDatabase) -> CycleValue {
MIN
}
#[test_log::test]
fn the_test() {
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().unwrap(), t2.join().unwrap());
assert_eq!((r_t1, r_t2), (MAX, MAX));
});
}