]>
git.proxmox.com Git - rustc.git/blob - vendor/salsa/src/runtime/local_state.rs
1 use crate::dependency
::Dependency
;
2 use crate::durability
::Durability
;
3 use crate::runtime
::ActiveQuery
;
4 use crate::runtime
::Revision
;
6 use std
::cell
::{Ref, RefCell, RefMut}
;
8 /// State that is specific to a single execution thread.
10 /// Internally, this type uses ref-cells.
12 /// **Note also that all mutations to the database handle (and hence
13 /// to the local-state) must be undone during unwinding.**
14 pub(super) struct LocalState
<DB
: Database
> {
15 /// Vector of active queries.
17 /// Unwinding note: pushes onto this vector must be popped -- even
19 query_stack
: RefCell
<Vec
<ActiveQuery
<DB
>>>,
22 impl<DB
: Database
> Default
for LocalState
<DB
> {
23 fn default() -> Self {
25 query_stack
: Default
::default(),
30 impl<DB
: Database
> LocalState
<DB
> {
31 pub(super) fn push_query(
33 database_key
: &DB
::DatabaseKey
,
34 max_durability
: Durability
,
35 ) -> ActiveQueryGuard
<'_
, DB
> {
36 let mut query_stack
= self.query_stack
.borrow_mut();
37 query_stack
.push(ActiveQuery
::new(database_key
.clone(), max_durability
));
40 push_len
: query_stack
.len(),
44 /// Returns a reference to the active query stack.
46 /// **Warning:** Because this reference holds the ref-cell lock,
47 /// you should not use any mutating methods of `LocalState` while
49 pub(super) fn borrow_query_stack(&self) -> Ref
<'_
, Vec
<ActiveQuery
<DB
>>> {
50 self.query_stack
.borrow()
53 pub(super) fn borrow_query_stack_mut(&self) -> RefMut
<'_
, Vec
<ActiveQuery
<DB
>>> {
54 self.query_stack
.borrow_mut()
57 pub(super) fn query_in_progress(&self) -> bool
{
58 !self.query_stack
.borrow().is_empty()
61 pub(super) fn active_query(&self) -> Option
<DB
::DatabaseKey
> {
65 .map(|active_query
| active_query
.database_key
.clone())
68 pub(super) fn report_query_read(
70 dependency
: Dependency
<DB
>,
71 durability
: Durability
,
74 if let Some(top_query
) = self.query_stack
.borrow_mut().last_mut() {
75 top_query
.add_read(dependency
, durability
, changed_at
);
79 pub(super) fn report_untracked_read(&self, current_revision
: Revision
) {
80 if let Some(top_query
) = self.query_stack
.borrow_mut().last_mut() {
81 top_query
.add_untracked_read(current_revision
);
85 pub(super) fn report_synthetic_read(&self, durability
: Durability
) {
86 if let Some(top_query
) = self.query_stack
.borrow_mut().last_mut() {
87 top_query
.add_synthetic_read(durability
);
91 pub(super) fn report_anon_read(&self, revision
: Revision
) {
92 if let Some(top_query
) = self.query_stack
.borrow_mut().last_mut() {
93 top_query
.add_anon_read(revision
);
98 impl<DB
> std
::panic
::RefUnwindSafe
for LocalState
<DB
> where DB
: Database {}
100 /// When a query is pushed onto the `active_query` stack, this guard
101 /// is returned to represent its slot. The guard can be used to pop
102 /// the query from the stack -- in the case of unwinding, the guard's
103 /// destructor will also remove the query.
104 pub(super) struct ActiveQueryGuard
<'me
, DB
: Database
> {
105 local_state
: &'me LocalState
<DB
>,
109 impl<'me
, DB
> ActiveQueryGuard
<'me
, DB
>
113 fn pop_helper(&self) -> ActiveQuery
<DB
> {
114 let mut query_stack
= self.local_state
.query_stack
.borrow_mut();
116 // Sanity check: pushes and pops should be balanced.
117 assert_eq
!(query_stack
.len(), self.push_len
);
119 query_stack
.pop().unwrap()
122 /// Invoked when the query has successfully completed execution.
123 pub(super) fn complete(self) -> ActiveQuery
<DB
> {
124 let query
= self.pop_helper();
125 std
::mem
::forget(self);
130 impl<'me
, DB
> Drop
for ActiveQueryGuard
<'me
, DB
>