mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-12-24 12:58:37 +00:00
add a public next_revision
method and start on incremental test
This commit is contained in:
parent
1929b26505
commit
e134ffcdf4
8 changed files with 158 additions and 0 deletions
|
@ -13,3 +13,6 @@ derive-new = "0.5.5"
|
|||
rustc-hash = "1.0"
|
||||
parking_lot = "0.6.4"
|
||||
indexmap = "1.0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
text-diff = "0.4.0"
|
14
examples/incremental/counter.rs
Normal file
14
examples/incremental/counter.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use std::cell::Cell;
|
||||
|
||||
#[derive(Default)]
|
||||
crate struct Counter {
|
||||
value: Cell<usize>,
|
||||
}
|
||||
|
||||
impl Counter {
|
||||
crate fn increment(&self) -> usize {
|
||||
let v = self.value.get();
|
||||
self.value.set(v + 1);
|
||||
v
|
||||
}
|
||||
}
|
36
examples/incremental/implementation.rs
Normal file
36
examples/incremental/implementation.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use crate::counter::Counter;
|
||||
use crate::log::Log;
|
||||
use crate::queries;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct QueryContextImpl {
|
||||
runtime: salsa::runtime::Runtime<QueryContextImpl>,
|
||||
clock: Counter,
|
||||
log: Log,
|
||||
}
|
||||
|
||||
salsa::query_context_storage! {
|
||||
pub struct QueryContextImplStorage for QueryContextImpl {
|
||||
impl queries::QueryContext {
|
||||
fn memoized2() for queries::Memoized2;
|
||||
fn memoized1() for queries::Memoized1;
|
||||
fn volatile() for queries::Volatile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl queries::CounterContext for QueryContextImpl {
|
||||
fn clock(&self) -> &Counter {
|
||||
&self.clock
|
||||
}
|
||||
|
||||
fn log(&self) -> &Log {
|
||||
&self.log
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::QueryContext for QueryContextImpl {
|
||||
fn salsa_runtime(&self) -> &salsa::runtime::Runtime<QueryContextImpl> {
|
||||
&self.runtime
|
||||
}
|
||||
}
|
16
examples/incremental/log.rs
Normal file
16
examples/incremental/log.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
#[derive(Default)]
|
||||
crate struct Log {
|
||||
data: RefCell<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Log {
|
||||
crate fn add(&self, text: impl Into<String>) {
|
||||
self.data.borrow_mut().push(text.into());
|
||||
}
|
||||
|
||||
crate fn read(&self) -> Vec<String> {
|
||||
self.data.borrow().clone()
|
||||
}
|
||||
}
|
10
examples/incremental/main.rs
Normal file
10
examples/incremental/main.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(underscore_imports)]
|
||||
|
||||
mod counter;
|
||||
mod implementation;
|
||||
mod log;
|
||||
mod queries;
|
||||
mod tests;
|
||||
|
||||
fn main() {}
|
38
examples/incremental/queries.rs
Normal file
38
examples/incremental/queries.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use crate::counter::Counter;
|
||||
use crate::log::Log;
|
||||
|
||||
crate trait CounterContext: salsa::QueryContext {
|
||||
fn clock(&self) -> &Counter;
|
||||
fn log(&self) -> &Log;
|
||||
}
|
||||
|
||||
crate trait QueryContext: CounterContext {
|
||||
salsa::query_prototype! {
|
||||
fn memoized2() for Memoized2;
|
||||
fn memoized1() for Memoized1;
|
||||
fn volatile() for Volatile;
|
||||
}
|
||||
}
|
||||
|
||||
salsa::query_definition! {
|
||||
crate Memoized2(query: &impl QueryContext, (): ()) -> usize {
|
||||
query.log().add("Memoized2 invoked");
|
||||
query.memoized1().of(())
|
||||
}
|
||||
}
|
||||
|
||||
salsa::query_definition! {
|
||||
crate Memoized1(query: &impl QueryContext, (): ()) -> usize {
|
||||
query.log().add("Memoized1 invoked");
|
||||
let v = query.volatile().of(());
|
||||
v / 3
|
||||
}
|
||||
}
|
||||
|
||||
salsa::query_definition! {
|
||||
#[storage(volatile)]
|
||||
crate Volatile(query: &impl QueryContext, (): ()) -> usize {
|
||||
query.log().add("Volatile invoked");
|
||||
query.clock().increment()
|
||||
}
|
||||
}
|
23
examples/incremental/tests.rs
Normal file
23
examples/incremental/tests.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#![cfg(test)]
|
||||
|
||||
use crate::implementation::QueryContextImpl;
|
||||
use crate::queries::CounterContext;
|
||||
use crate::queries::QueryContext;
|
||||
|
||||
impl QueryContextImpl {
|
||||
fn assert_log(&self, expected_log: &[&str]) {
|
||||
let expected_text = format!("{:#?}", expected_log);
|
||||
let actual_text = format!("{:#?}", self.log().read());
|
||||
text_diff::assert_diff(&expected_text, &actual_text, "", 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn foo() {
|
||||
let query = QueryContextImpl::default();
|
||||
|
||||
// Invoking volatile twice will simply execute twice.
|
||||
query.volatile().of(());
|
||||
query.volatile().of(());
|
||||
query.assert_log(&["Volatile invoked", "Volatile invoked"]);
|
||||
}
|
|
@ -50,6 +50,24 @@ where
|
|||
&self.shared_state.storage
|
||||
}
|
||||
|
||||
/// Indicates that some input to the system has changed and hence
|
||||
/// that memoized values **may** be invalidated. This cannot be
|
||||
/// invoked while query computation is in progress.
|
||||
///
|
||||
/// As a user of the system, you would not normally invoke this
|
||||
/// method directly. Instead, you would use "input" queries and
|
||||
/// invoke their `set` method. But it can be useful if you have a
|
||||
/// "volatile" input that you must poll from time to time; in that
|
||||
/// case, you can wrap the input with a "no-storage" query and
|
||||
/// invoke this method from time to time.
|
||||
pub fn next_revision(&self) {
|
||||
if !self.local_state.borrow().query_stack.is_empty() {
|
||||
panic!("next_revision invoked during a query computation");
|
||||
}
|
||||
|
||||
self.increment_revision();
|
||||
}
|
||||
|
||||
/// Read current value of the revision counter.
|
||||
crate fn current_revision(&self) -> Revision {
|
||||
Revision {
|
||||
|
|
Loading…
Reference in a new issue