introduce a LocalState type

This commit is contained in:
Niko Matsakis 2018-09-29 07:02:32 -04:00
parent 2e7e77516e
commit dc94984a2b

View file

@ -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)