mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-08-04 19:08:32 +00:00
75 lines
1.8 KiB
Rust
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));
|
|
});
|
|
}
|