]> git.proxmox.com Git - rustc.git/blob - vendor/salsa/src/runtime/local_state.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / 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;
5 use crate::Database;
6 use std::cell::{Ref, RefCell, RefMut};
7
8 /// State that is specific to a single execution thread.
9 ///
10 /// Internally, this type uses ref-cells.
11 ///
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.
16 ///
17 /// Unwinding note: pushes onto this vector must be popped -- even
18 /// during unwinding.
19 query_stack: RefCell<Vec<ActiveQuery<DB>>>,
20 }
21
22 impl<DB: Database> Default for LocalState<DB> {
23 fn default() -> Self {
24 LocalState {
25 query_stack: Default::default(),
26 }
27 }
28 }
29
30 impl<DB: Database> LocalState<DB> {
31 pub(super) fn push_query(
32 &self,
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));
38 ActiveQueryGuard {
39 local_state: self,
40 push_len: query_stack.len(),
41 }
42 }
43
44 /// Returns a reference to the active query stack.
45 ///
46 /// **Warning:** Because this reference holds the ref-cell lock,
47 /// you should not use any mutating methods of `LocalState` while
48 /// reading from it.
49 pub(super) fn borrow_query_stack(&self) -> Ref<'_, Vec<ActiveQuery<DB>>> {
50 self.query_stack.borrow()
51 }
52
53 pub(super) fn borrow_query_stack_mut(&self) -> RefMut<'_, Vec<ActiveQuery<DB>>> {
54 self.query_stack.borrow_mut()
55 }
56
57 pub(super) fn query_in_progress(&self) -> bool {
58 !self.query_stack.borrow().is_empty()
59 }
60
61 pub(super) fn active_query(&self) -> Option<DB::DatabaseKey> {
62 self.query_stack
63 .borrow()
64 .last()
65 .map(|active_query| active_query.database_key.clone())
66 }
67
68 pub(super) fn report_query_read(
69 &self,
70 dependency: Dependency<DB>,
71 durability: Durability,
72 changed_at: Revision,
73 ) {
74 if let Some(top_query) = self.query_stack.borrow_mut().last_mut() {
75 top_query.add_read(dependency, durability, changed_at);
76 }
77 }
78
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);
82 }
83 }
84
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);
88 }
89 }
90
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);
94 }
95 }
96 }
97
98 impl<DB> std::panic::RefUnwindSafe for LocalState<DB> where DB: Database {}
99
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>,
106 push_len: usize,
107 }
108
109 impl<'me, DB> ActiveQueryGuard<'me, DB>
110 where
111 DB: Database,
112 {
113 fn pop_helper(&self) -> ActiveQuery<DB> {
114 let mut query_stack = self.local_state.query_stack.borrow_mut();
115
116 // Sanity check: pushes and pops should be balanced.
117 assert_eq!(query_stack.len(), self.push_len);
118
119 query_stack.pop().unwrap()
120 }
121
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);
126 query
127 }
128 }
129
130 impl<'me, DB> Drop for ActiveQueryGuard<'me, DB>
131 where
132 DB: Database,
133 {
134 fn drop(&mut self) {
135 self.pop_helper();
136 }
137 }