mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-11-25 04:27:52 +00:00
daaa78056a
Under this design, *all* databases are a `DatabaseImpl<U>`, where the `U` implements `UserData` (you can use `()` if there is none). Code would default to `&dyn salsa::Database` but if you want to give access to the userdata, you can define a custom database trait `MyDatabase: salsa::Databse` so long as you * annotate `MyDatabase` trait definition of impls of `MyDatabase` with `#[salsa::db]` * implement `MyDatabase` for `DatabaseImpl<U>` where `U` is your userdata (this could be a blanket impl, if you don't know the precise userdata type). The `tests/common/mod.rs` shows the pattern.
61 lines
1.7 KiB
Rust
61 lines
1.7 KiB
Rust
use crossbeam::atomic::AtomicCell;
|
|
use salsa::{Database, DatabaseImpl, UserData};
|
|
|
|
use crate::signal::Signal;
|
|
|
|
/// Various "knobs" and utilities used by tests to force
|
|
/// a certain behavior.
|
|
#[salsa::db]
|
|
pub(crate) trait KnobsDatabase: Database {
|
|
fn knobs(&self) -> &Knobs;
|
|
|
|
fn signal(&self, stage: usize);
|
|
|
|
fn wait_for(&self, stage: usize);
|
|
}
|
|
|
|
/// Various "knobs" that can be used to customize how the queries
|
|
/// behave on one specific thread. Note that this state is
|
|
/// intentionally thread-local (apart from `signal`).
|
|
#[derive(Default)]
|
|
pub(crate) struct Knobs {
|
|
/// A kind of flexible barrier used to coordinate execution across
|
|
/// threads to ensure we reach various weird states.
|
|
pub(crate) signal: Signal,
|
|
|
|
/// When this database is about to block, send this signal.
|
|
pub(crate) signal_on_will_block: AtomicCell<usize>,
|
|
|
|
/// When this database has set the cancellation flag, send this signal.
|
|
pub(crate) signal_on_did_cancel: AtomicCell<usize>,
|
|
}
|
|
|
|
impl UserData for Knobs {
|
|
fn salsa_event(db: &DatabaseImpl<Self>, event: &dyn Fn() -> salsa::Event) {
|
|
let event = event();
|
|
match event.kind {
|
|
salsa::EventKind::WillBlockOn { .. } => {
|
|
db.signal(db.signal_on_will_block.load());
|
|
}
|
|
salsa::EventKind::DidSetCancellationFlag => {
|
|
db.signal(db.signal_on_did_cancel.load());
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[salsa::db]
|
|
impl KnobsDatabase for DatabaseImpl<Knobs> {
|
|
fn knobs(&self) -> &Knobs {
|
|
self
|
|
}
|
|
|
|
fn signal(&self, stage: usize) {
|
|
self.signal.signal(stage);
|
|
}
|
|
|
|
fn wait_for(&self, stage: usize) {
|
|
self.signal.wait_for(stage);
|
|
}
|
|
}
|