mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-12-24 12:58:37 +00:00
introduce active query and some (unused) fields
This commit is contained in:
parent
dc94984a2b
commit
5ed8cafe04
2 changed files with 70 additions and 38 deletions
|
@ -11,4 +11,5 @@ readme = "README.md"
|
|||
[dependencies]
|
||||
derive-new = "0.5.5"
|
||||
rustc-hash = "1.0"
|
||||
parking_lot = "0.6.4"
|
||||
parking_lot = "0.6.4"
|
||||
indexmap = "1.0.1"
|
||||
|
|
105
src/runtime.rs
105
src/runtime.rs
|
@ -1,47 +1,26 @@
|
|||
use crate::Query;
|
||||
use crate::QueryContext;
|
||||
use rustc_hash::FxHashMap;
|
||||
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::Arc;
|
||||
|
||||
pub struct Runtime<QC>
|
||||
where
|
||||
QC: QueryContext,
|
||||
{
|
||||
type FxIndexSet<K> = indexmap::IndexSet<K, BuildHasherDefault<FxHasher>>;
|
||||
|
||||
/// The salsa runtime stores the storage for all queries as well as
|
||||
/// tracking the query stack and dependencies between cycles.
|
||||
///
|
||||
/// Each new runtime you create (e.g., via `Runtime::new` or
|
||||
/// `Runtime::default`) will have an independent set of query storage
|
||||
/// associated with it. Normally, therefore, you only do this once, at
|
||||
/// the start of your application.
|
||||
pub struct Runtime<QC: QueryContext> {
|
||||
shared_state: Arc<SharedState<QC>>,
|
||||
local_state: RefCell<LocalState<QC>>,
|
||||
}
|
||||
|
||||
/// State that will be common to all threads (when we support multiple threads)
|
||||
struct SharedState<QC>
|
||||
where
|
||||
QC: QueryContext,
|
||||
{
|
||||
storage: QC::QueryContextStorage,
|
||||
revision: AtomicU64,
|
||||
}
|
||||
|
||||
/// State that will be specific to a single execution threads (when we support multiple threads)
|
||||
struct LocalState<QC>
|
||||
where
|
||||
QC: QueryContext,
|
||||
{
|
||||
query_stack: Vec<QC::QueryDescriptor>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Revision {
|
||||
generation: u64,
|
||||
}
|
||||
|
||||
impl Revision {
|
||||
crate fn zero() -> Self {
|
||||
Revision { generation: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<QC> Default for Runtime<QC>
|
||||
where
|
||||
QC: QueryContext,
|
||||
|
@ -63,6 +42,10 @@ impl<QC> Runtime<QC>
|
|||
where
|
||||
QC: QueryContext,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn storage(&self) -> &QC::QueryContextStorage {
|
||||
&self.shared_state.storage
|
||||
}
|
||||
|
@ -90,7 +73,10 @@ where
|
|||
where
|
||||
Q: Query<QC>,
|
||||
{
|
||||
self.local_state.borrow_mut().query_stack.push(descriptor);
|
||||
self.local_state
|
||||
.borrow_mut()
|
||||
.query_stack
|
||||
.push(ActiveQuery::new(descriptor));
|
||||
let value = Q::execute(query, key.clone());
|
||||
self.local_state.borrow_mut().query_stack.pop();
|
||||
value
|
||||
|
@ -103,14 +89,59 @@ where
|
|||
|
||||
let start_index = (0..query_stack.len())
|
||||
.rev()
|
||||
.filter(|&i| query_stack[i] == descriptor)
|
||||
.filter(|&i| query_stack[i].descriptor == descriptor)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let mut message = format!("Internal error, cycle detected:\n");
|
||||
for descriptor in &query_stack[start_index..] {
|
||||
writeln!(message, "- {:?}\n", descriptor).unwrap();
|
||||
for active_query in &query_stack[start_index..] {
|
||||
writeln!(message, "- {:?}\n", active_query.descriptor).unwrap();
|
||||
}
|
||||
panic!(message)
|
||||
}
|
||||
}
|
||||
|
||||
/// State that will be common to all threads (when we support multiple threads)
|
||||
struct SharedState<QC: QueryContext> {
|
||||
storage: QC::QueryContextStorage,
|
||||
revision: AtomicU64,
|
||||
}
|
||||
|
||||
/// State that will be specific to a single execution threads (when we support multiple threads)
|
||||
struct LocalState<QC: QueryContext> {
|
||||
query_stack: Vec<ActiveQuery<QC>>,
|
||||
}
|
||||
|
||||
struct ActiveQuery<QC: QueryContext> {
|
||||
/// What query is executing
|
||||
descriptor: QC::QueryDescriptor,
|
||||
|
||||
/// Each time we execute a subquery, it returns to us the revision
|
||||
/// in which its value last changed. We track the maximum of these
|
||||
/// to find the maximum revision in which *we* changed.
|
||||
max_revision_read: Revision,
|
||||
|
||||
/// Each subquery
|
||||
subqueries: FxIndexSet<QC::QueryDescriptor>,
|
||||
}
|
||||
|
||||
impl<QC: QueryContext> ActiveQuery<QC> {
|
||||
fn new(descriptor: QC::QueryDescriptor) -> Self {
|
||||
ActiveQuery {
|
||||
descriptor,
|
||||
max_revision_read: Revision::zero(),
|
||||
subqueries: FxIndexSet::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Revision {
|
||||
generation: u64,
|
||||
}
|
||||
|
||||
impl Revision {
|
||||
crate fn zero() -> Self {
|
||||
Revision { generation: 0 }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue