mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-11-28 17:42:00 +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::QueryContext;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Write;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Runtime<QC>
|
||||
|
@ -10,9 +11,10 @@ where
|
|||
QC: QueryContext,
|
||||
{
|
||||
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>
|
||||
where
|
||||
QC: QueryContext,
|
||||
|
@ -21,9 +23,23 @@ where
|
|||
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: usize,
|
||||
generation: u64,
|
||||
}
|
||||
|
||||
impl Revision {
|
||||
crate fn zero() -> Self {
|
||||
Revision { generation: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<QC> Default for Runtime<QC>
|
||||
|
@ -36,7 +52,9 @@ where
|
|||
storage: 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
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
&self,
|
||||
query: &QC,
|
||||
|
@ -58,23 +90,25 @@ where
|
|||
where
|
||||
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());
|
||||
self.execution_stack.borrow_mut().pop();
|
||||
self.local_state.borrow_mut().query_stack.pop();
|
||||
value
|
||||
}
|
||||
|
||||
/// Obviously, this should be user configurable at some point.
|
||||
crate fn report_unexpected_cycle(&self, descriptor: QC::QueryDescriptor) -> ! {
|
||||
let execution_stack = self.execution_stack.borrow();
|
||||
let start_index = (0..execution_stack.len())
|
||||
let local_state = self.local_state.borrow();
|
||||
let LocalState { query_stack, .. } = &*local_state;
|
||||
|
||||
let start_index = (0..query_stack.len())
|
||||
.rev()
|
||||
.filter(|&i| execution_stack[i] == descriptor)
|
||||
.filter(|&i| query_stack[i] == descriptor)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
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();
|
||||
}
|
||||
panic!(message)
|
||||
|
|
Loading…
Reference in a new issue