mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-12 08:30:51 +00:00
introduce a LocalState
type
This commit is contained in:
parent
2e7e77516e
commit
dc94984a2b
1 changed files with 44 additions and 10 deletions
|
@ -1,8 +1,9 @@
|
||||||
use crate::Query;
|
use crate::Query;
|
||||||
use crate::QueryContext;
|
use crate::QueryContext;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::sync::atomic::AtomicU64;
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct Runtime<QC>
|
pub struct Runtime<QC>
|
||||||
|
@ -10,9 +11,10 @@ where
|
||||||
QC: QueryContext,
|
QC: QueryContext,
|
||||||
{
|
{
|
||||||
shared_state: Arc<SharedState<QC>>,
|
shared_state: Arc<SharedState<QC>>,
|
||||||
execution_stack: RefCell<Vec<QC::QueryDescriptor>>,
|
local_state: RefCell<LocalState<QC>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State that will be common to all threads (when we support multiple threads)
|
||||||
struct SharedState<QC>
|
struct SharedState<QC>
|
||||||
where
|
where
|
||||||
QC: QueryContext,
|
QC: QueryContext,
|
||||||
|
@ -21,9 +23,23 @@ where
|
||||||
revision: AtomicU64,
|
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)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct Revision {
|
pub struct Revision {
|
||||||
generation: usize,
|
generation: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Revision {
|
||||||
|
crate fn zero() -> Self {
|
||||||
|
Revision { generation: 0 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<QC> Default for Runtime<QC>
|
impl<QC> Default for Runtime<QC>
|
||||||
|
@ -36,7 +52,9 @@ where
|
||||||
storage: Default::default(),
|
storage: Default::default(),
|
||||||
revision: Default::default(),
|
revision: Default::default(),
|
||||||
}),
|
}),
|
||||||
execution_stack: RefCell::default(),
|
local_state: RefCell::new(LocalState {
|
||||||
|
query_stack: Default::default(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +67,20 @@ where
|
||||||
&self.shared_state.storage
|
&self.shared_state.storage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read current value of the revision counter.
|
||||||
|
crate fn current_revision(&self) -> Revision {
|
||||||
|
Revision {
|
||||||
|
generation: self.shared_state.revision.load(Ordering::SeqCst),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increments the current revision counter and returns the new value.
|
||||||
|
crate fn increment_revision(&self) -> Revision {
|
||||||
|
Revision {
|
||||||
|
generation: 1 + self.shared_state.revision.fetch_add(1, Ordering::SeqCst),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate fn execute_query_implementation<Q>(
|
crate fn execute_query_implementation<Q>(
|
||||||
&self,
|
&self,
|
||||||
query: &QC,
|
query: &QC,
|
||||||
|
@ -58,23 +90,25 @@ where
|
||||||
where
|
where
|
||||||
Q: Query<QC>,
|
Q: Query<QC>,
|
||||||
{
|
{
|
||||||
self.execution_stack.borrow_mut().push(descriptor);
|
self.local_state.borrow_mut().query_stack.push(descriptor);
|
||||||
let value = Q::execute(query, key.clone());
|
let value = Q::execute(query, key.clone());
|
||||||
self.execution_stack.borrow_mut().pop();
|
self.local_state.borrow_mut().query_stack.pop();
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obviously, this should be user configurable at some point.
|
/// Obviously, this should be user configurable at some point.
|
||||||
crate fn report_unexpected_cycle(&self, descriptor: QC::QueryDescriptor) -> ! {
|
crate fn report_unexpected_cycle(&self, descriptor: QC::QueryDescriptor) -> ! {
|
||||||
let execution_stack = self.execution_stack.borrow();
|
let local_state = self.local_state.borrow();
|
||||||
let start_index = (0..execution_stack.len())
|
let LocalState { query_stack, .. } = &*local_state;
|
||||||
|
|
||||||
|
let start_index = (0..query_stack.len())
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|&i| execution_stack[i] == descriptor)
|
.filter(|&i| query_stack[i] == descriptor)
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut message = format!("Internal error, cycle detected:\n");
|
let mut message = format!("Internal error, cycle detected:\n");
|
||||||
for descriptor in &execution_stack[start_index..] {
|
for descriptor in &query_stack[start_index..] {
|
||||||
writeln!(message, "- {:?}\n", descriptor).unwrap();
|
writeln!(message, "- {:?}\n", descriptor).unwrap();
|
||||||
}
|
}
|
||||||
panic!(message)
|
panic!(message)
|
||||||
|
|
Loading…
Reference in a new issue