mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-13 00:40:22 +00:00
commit
bf44ef35d4
17 changed files with 44 additions and 51 deletions
|
@ -1,6 +1,6 @@
|
|||
language: rust
|
||||
rust:
|
||||
- nightly
|
||||
- beta
|
||||
script:
|
||||
- RUST_BACKTRACE=1 CARGO_INCREMENTAL=0 cargo test --all
|
||||
- RUST_BACKTRACE=1 CARGO_INCREMENTAL=0 cargo test --tests --all
|
||||
|
|
|
@ -41,9 +41,11 @@ Using salsa is as easy as 1, 2, 3...
|
|||
the inputs/queries you will be using. The query struct will contain
|
||||
the storage for all of the inputs/queries and may also contain
|
||||
anything else that your code needs (e.g., configuration data).
|
||||
|
||||
|
||||
To see an example of this in action, check out [the `hello_world`
|
||||
example](examples/hello_world/main.rs), which has a number of comments
|
||||
explaining how things work. The [`hello_world`
|
||||
README](examples/hello_world/README.md) has a more detailed writeup.
|
||||
|
||||
Salsa requires at least Rust 1.30 (beta at the time of writing).
|
||||
|
||||
|
|
|
@ -323,9 +323,9 @@ where
|
|||
DB: Database,
|
||||
MP: MemoizationPolicy<DB, Q>,
|
||||
{
|
||||
fn try_fetch<'q>(
|
||||
fn try_fetch(
|
||||
&self,
|
||||
db: &'q DB,
|
||||
db: &DB,
|
||||
key: &Q::Key,
|
||||
descriptor: &DB::QueryDescriptor,
|
||||
) -> Result<Q::Value, CycleDetected> {
|
||||
|
@ -338,7 +338,7 @@ where
|
|||
|
||||
fn maybe_changed_since(
|
||||
&self,
|
||||
db: &'q DB,
|
||||
db: &DB,
|
||||
revision: Revision,
|
||||
key: &Q::Key,
|
||||
descriptor: &DB::QueryDescriptor,
|
||||
|
|
|
@ -78,9 +78,9 @@ where
|
|||
DB: Database,
|
||||
Q::Value: Default,
|
||||
{
|
||||
fn try_fetch<'q>(
|
||||
fn try_fetch(
|
||||
&self,
|
||||
db: &'q DB,
|
||||
db: &DB,
|
||||
key: &Q::Key,
|
||||
descriptor: &DB::QueryDescriptor,
|
||||
) -> Result<Q::Value, CycleDetected> {
|
||||
|
@ -93,7 +93,7 @@ where
|
|||
|
||||
fn maybe_changed_since(
|
||||
&self,
|
||||
_db: &'q DB,
|
||||
_db: &DB,
|
||||
revision: Revision,
|
||||
key: &Q::Key,
|
||||
_descriptor: &DB::QueryDescriptor,
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
#![deny(rust_2018_idioms)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(nll)]
|
||||
#![feature(integer_atomics)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
|
@ -160,7 +156,7 @@ where
|
|||
|
||||
pub struct CycleDetected;
|
||||
|
||||
impl<DB, Q> QueryTable<'me, DB, Q>
|
||||
impl<DB, Q> QueryTable<'_, DB, Q>
|
||||
where
|
||||
DB: Database,
|
||||
Q: Query<DB>,
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_hash::FxHasher;
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::Write;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
type FxIndexSet<K> = indexmap::IndexSet<K, BuildHasherDefault<FxHasher>>;
|
||||
|
@ -67,20 +67,22 @@ where
|
|||
}
|
||||
|
||||
/// Read current value of the revision counter.
|
||||
crate fn current_revision(&self) -> Revision {
|
||||
pub(crate) fn current_revision(&self) -> Revision {
|
||||
Revision {
|
||||
generation: self.shared_state.revision.load(Ordering::SeqCst),
|
||||
generation: self.shared_state.revision.load(Ordering::SeqCst) as u64,
|
||||
}
|
||||
}
|
||||
|
||||
/// Increments the current revision counter and returns the new value.
|
||||
crate fn increment_revision(&self) -> Revision {
|
||||
pub(crate) fn increment_revision(&self) -> Revision {
|
||||
if !self.local_state.borrow().query_stack.is_empty() {
|
||||
panic!("increment_revision invoked during a query computation");
|
||||
}
|
||||
|
||||
let old_revision = self.shared_state.revision.fetch_add(1, Ordering::SeqCst);
|
||||
assert!(old_revision != usize::max_value(), "revision overflow");
|
||||
let result = Revision {
|
||||
generation: 1 + self.shared_state.revision.fetch_add(1, Ordering::SeqCst),
|
||||
generation: 1 + old_revision as u64,
|
||||
};
|
||||
|
||||
debug!("increment_revision: incremented to {:?}", result);
|
||||
|
@ -88,7 +90,7 @@ where
|
|||
result
|
||||
}
|
||||
|
||||
crate fn execute_query_implementation<V>(
|
||||
pub(crate) fn execute_query_implementation<V>(
|
||||
&self,
|
||||
descriptor: &DB::QueryDescriptor,
|
||||
execute: impl FnOnce() -> V,
|
||||
|
@ -132,13 +134,13 @@ where
|
|||
/// - `descriptor`: the query whose result was read
|
||||
/// - `changed_revision`: the last revision in which the result of that
|
||||
/// query had changed
|
||||
crate fn report_query_read(&self, descriptor: &DB::QueryDescriptor, changed_at: ChangedAt) {
|
||||
pub(crate) fn report_query_read(&self, descriptor: &DB::QueryDescriptor, changed_at: ChangedAt) {
|
||||
if let Some(top_query) = self.local_state.borrow_mut().query_stack.last_mut() {
|
||||
top_query.add_read(descriptor, changed_at);
|
||||
}
|
||||
}
|
||||
|
||||
crate fn report_untracked_read(&self) {
|
||||
pub(crate) fn report_untracked_read(&self) {
|
||||
if let Some(top_query) = self.local_state.borrow_mut().query_stack.last_mut() {
|
||||
let changed_at = ChangedAt::Revision(self.current_revision());
|
||||
top_query.add_untracked_read(changed_at);
|
||||
|
@ -146,7 +148,7 @@ where
|
|||
}
|
||||
|
||||
/// Obviously, this should be user configurable at some point.
|
||||
crate fn report_unexpected_cycle(&self, descriptor: DB::QueryDescriptor) -> ! {
|
||||
pub(crate) fn report_unexpected_cycle(&self, descriptor: DB::QueryDescriptor) -> ! {
|
||||
let local_state = self.local_state.borrow();
|
||||
let LocalState { query_stack, .. } = &*local_state;
|
||||
|
||||
|
@ -167,7 +169,8 @@ where
|
|||
/// State that will be common to all threads (when we support multiple threads)
|
||||
struct SharedState<DB: Database> {
|
||||
storage: DB::DatabaseStorage,
|
||||
revision: AtomicU64,
|
||||
// Ideally, this should be `AtomicU64`, but that is currently unstable.
|
||||
revision: AtomicUsize,
|
||||
}
|
||||
|
||||
/// State that will be specific to a single execution threads (when we
|
||||
|
@ -213,7 +216,7 @@ pub struct Revision {
|
|||
}
|
||||
|
||||
impl Revision {
|
||||
crate const ZERO: Self = Revision { generation: 0 };
|
||||
pub(crate) const ZERO: Self = Revision { generation: 0 };
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Revision {
|
||||
|
@ -243,7 +246,7 @@ impl ChangedAt {
|
|||
|
||||
/// An insertion-order-preserving set of queries. Used to track the
|
||||
/// inputs accessed during query execution.
|
||||
crate enum QueryDescriptorSet<DB: Database> {
|
||||
pub(crate) enum QueryDescriptorSet<DB: Database> {
|
||||
/// All reads were to tracked things:
|
||||
Tracked(FxIndexSet<DB::QueryDescriptor>),
|
||||
|
||||
|
@ -285,7 +288,7 @@ impl<DB: Database> QueryDescriptorSet<DB> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
crate struct StampedValue<V> {
|
||||
crate value: V,
|
||||
crate changed_at: ChangedAt,
|
||||
pub(crate) struct StampedValue<V> {
|
||||
pub(crate) value: V,
|
||||
pub(crate) changed_at: ChangedAt,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(crate_visibility_modifier)]
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DatabaseImpl {
|
||||
runtime: salsa::Runtime<DatabaseImpl>,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use std::cell::Cell;
|
||||
|
||||
#[derive(Default)]
|
||||
crate struct Counter {
|
||||
pub(crate) struct Counter {
|
||||
value: Cell<usize>,
|
||||
}
|
||||
|
||||
impl Counter {
|
||||
crate fn increment(&self) -> usize {
|
||||
pub(crate) fn increment(&self) -> usize {
|
||||
let v = self.value.get();
|
||||
self.value.set(v + 1);
|
||||
v
|
||||
|
|
|
@ -4,20 +4,20 @@ use crate::memoized_dep_inputs;
|
|||
use crate::memoized_inputs;
|
||||
use crate::memoized_volatile;
|
||||
|
||||
crate trait TestContext: salsa::Database {
|
||||
pub(crate) trait TestContext: salsa::Database {
|
||||
fn clock(&self) -> &Counter;
|
||||
fn log(&self) -> &Log;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
crate struct TestContextImpl {
|
||||
pub(crate) struct TestContextImpl {
|
||||
runtime: salsa::Runtime<TestContextImpl>,
|
||||
clock: Counter,
|
||||
log: Log,
|
||||
}
|
||||
|
||||
impl TestContextImpl {
|
||||
crate fn assert_log(&self, expected_log: &[&str]) {
|
||||
pub(crate) fn assert_log(&self, expected_log: &[&str]) {
|
||||
use difference::{Changeset, Difference};
|
||||
|
||||
let expected_text = &format!("{:#?}", expected_log);
|
||||
|
@ -42,7 +42,7 @@ impl TestContextImpl {
|
|||
}
|
||||
|
||||
salsa::database_storage! {
|
||||
crate struct TestContextImplStorage for TestContextImpl {
|
||||
pub(crate) struct TestContextImplStorage for TestContextImpl {
|
||||
impl memoized_dep_inputs::MemoizedDepInputsContext {
|
||||
fn dep_memoized2() for memoized_dep_inputs::Memoized2;
|
||||
fn dep_memoized1() for memoized_dep_inputs::Memoized1;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
#[derive(Default)]
|
||||
crate struct Log {
|
||||
pub(crate) struct Log {
|
||||
data: RefCell<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Log {
|
||||
crate fn add(&self, text: impl Into<String>) {
|
||||
pub(crate) fn add(&self, text: impl Into<String>) {
|
||||
self.data.borrow_mut().push(text.into());
|
||||
}
|
||||
|
||||
crate fn take(&self) -> Vec<String> {
|
||||
pub(crate) fn take(&self) -> Vec<String> {
|
||||
std::mem::replace(&mut *self.data.borrow_mut(), vec![])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(underscore_imports)]
|
||||
|
||||
mod counter;
|
||||
mod implementation;
|
||||
mod log;
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::implementation::{TestContext, TestContextImpl};
|
|||
use salsa::Database;
|
||||
|
||||
salsa::query_group! {
|
||||
crate trait MemoizedDepInputsContext: TestContext {
|
||||
pub(crate) trait MemoizedDepInputsContext: TestContext {
|
||||
fn dep_memoized2(key: ()) -> usize {
|
||||
type Memoized2;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::implementation::{TestContext, TestContextImpl};
|
|||
use salsa::Database;
|
||||
|
||||
salsa::query_group! {
|
||||
crate trait MemoizedInputsContext: TestContext {
|
||||
pub(crate) trait MemoizedInputsContext: TestContext {
|
||||
fn max(key: ()) -> usize {
|
||||
type Max;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::implementation::{TestContext, TestContextImpl};
|
|||
use salsa::Database;
|
||||
|
||||
salsa::query_group! {
|
||||
crate trait MemoizedVolatileContext: TestContext {
|
||||
pub(crate) trait MemoizedVolatileContext: TestContext {
|
||||
// Queries for testing a "volatile" value wrapped by
|
||||
// memoization.
|
||||
fn memoized2(key: ()) -> usize {
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(underscore_imports)]
|
||||
|
||||
mod implementation;
|
||||
mod queries;
|
||||
mod tests;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
crate trait Counter: salsa::Database {
|
||||
pub(crate) trait Counter: salsa::Database {
|
||||
fn increment(&self) -> usize;
|
||||
}
|
||||
|
||||
salsa::query_group! {
|
||||
crate trait Database: Counter {
|
||||
pub(crate) trait Database: Counter {
|
||||
fn memoized(key: ()) -> usize {
|
||||
type Memoized;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::implementation::DatabaseImpl;
|
||||
use crate::queries::Database;
|
||||
use salsa::Database as _;
|
||||
use salsa::Database as _Database;
|
||||
|
||||
#[test]
|
||||
fn memoized_twice() {
|
||||
|
|
Loading…
Reference in a new issue