|
1 |
| -use std::{any::Any, marker::PhantomData, panic::RefUnwindSafe, sync::Arc}; |
| 1 | +use std::any::Any; |
2 | 2 |
|
3 |
| -use parking_lot::{Condvar, Mutex}; |
4 |
| - |
5 |
| -use crate::{ |
6 |
| - self as salsa, |
7 |
| - zalsa::Zalsa, |
8 |
| - zalsa_local::{self, ZalsaLocal}, |
9 |
| - Durability, Event, EventKind, Revision, |
10 |
| -}; |
| 3 | +use crate::{zalsa::ZalsaDatabase, Durability, Event, Revision}; |
11 | 4 |
|
12 | 5 | /// The trait implemented by all Salsa databases.
|
13 |
| -/// You can create your own subtraits of this trait using the `#[salsa::db]` procedural macro. |
14 |
| -/// |
15 |
| -/// # Safety |
16 |
| -/// |
17 |
| -/// This trait can only safely be implemented by Salsa's [`DatabaseImpl`][] type. |
18 |
| -/// |
19 |
| -/// FIXME: Document better the unsafety conditions we require. |
20 |
| -#[salsa_macros::db] |
21 |
| -pub unsafe trait Database: Send + AsDynDatabase + Any { |
| 6 | +/// You can create your own subtraits of this trait using the `#[salsa::db]`(`crate::db`) procedural macro. |
| 7 | +#[crate::db] |
| 8 | +pub trait Database: Send + AsDynDatabase + Any + ZalsaDatabase { |
22 | 9 | /// This function is invoked by the salsa runtime at various points during execution.
|
23 | 10 | /// You can customize what happens by implementing the [`UserData`][] trait.
|
24 | 11 | /// By default, the event is logged at level debug using tracing facade.
|
@@ -58,21 +45,6 @@ pub unsafe trait Database: Send + AsDynDatabase + Any {
|
58 | 45 | {
|
59 | 46 | crate::attach::attach(self, || op(self))
|
60 | 47 | }
|
61 |
| - |
62 |
| - /// Plumbing method: Access the internal salsa methods. |
63 |
| - #[doc(hidden)] |
64 |
| - fn zalsa(&self) -> &Zalsa; |
65 |
| - |
66 |
| - /// Plumbing method: Access the internal salsa methods for mutating the database. |
67 |
| - /// |
68 |
| - /// **WARNING:** Triggers a new revision, canceling other database handles. |
69 |
| - /// This can lead to deadlock! |
70 |
| - #[doc(hidden)] |
71 |
| - fn zalsa_mut(&mut self) -> &mut Zalsa; |
72 |
| - |
73 |
| - /// Access the thread-local state associated with this database |
74 |
| - #[doc(hidden)] |
75 |
| - fn zalsa_local(&self) -> &ZalsaLocal; |
76 | 48 | }
|
77 | 49 |
|
78 | 50 | /// Upcast to a `dyn Database`.
|
@@ -108,174 +80,3 @@ impl dyn Database {
|
108 | 80 | self.zalsa().views().try_view_as(self).unwrap()
|
109 | 81 | }
|
110 | 82 | }
|
111 |
| - |
112 |
| -/// Concrete implementation of the [`Database`][] trait. |
113 |
| -/// Takes an optional type parameter `U` that allows you to thread your own data. |
114 |
| -pub struct DatabaseImpl<U: UserData = ()> { |
115 |
| - /// Reference to the database. This is always `Some` except during destruction. |
116 |
| - zalsa_impl: Option<Arc<Zalsa>>, |
117 |
| - |
118 |
| - /// Coordination data for cancellation of other handles when `zalsa_mut` is called. |
119 |
| - /// This could be stored in Zalsa but it makes things marginally cleaner to keep it separate. |
120 |
| - coordinate: Arc<Coordinate>, |
121 |
| - |
122 |
| - /// Per-thread state |
123 |
| - zalsa_local: zalsa_local::ZalsaLocal, |
124 |
| - |
125 |
| - /// The `U` is stored as a `dyn Any` in `zalsa_impl` |
126 |
| - phantom: PhantomData<U>, |
127 |
| -} |
128 |
| - |
129 |
| -impl<U: UserData + Default> Default for DatabaseImpl<U> { |
130 |
| - fn default() -> Self { |
131 |
| - Self::with(U::default()) |
132 |
| - } |
133 |
| -} |
134 |
| - |
135 |
| -impl DatabaseImpl<()> { |
136 |
| - /// Create a new database with the given user data. |
137 |
| - /// |
138 |
| - /// You can also use the [`Default`][] trait if your userdata implements it. |
139 |
| - pub fn new() -> Self { |
140 |
| - Self::with(()) |
141 |
| - } |
142 |
| -} |
143 |
| - |
144 |
| -impl<U: UserData> DatabaseImpl<U> { |
145 |
| - /// Create a new database with the given user data. |
146 |
| - /// |
147 |
| - /// You can also use the [`Default`][] trait if your userdata implements it. |
148 |
| - pub fn with(u: U) -> Self { |
149 |
| - Self { |
150 |
| - zalsa_impl: Some(Arc::new(Zalsa::with(u))), |
151 |
| - coordinate: Arc::new(Coordinate { |
152 |
| - clones: Mutex::new(1), |
153 |
| - cvar: Default::default(), |
154 |
| - }), |
155 |
| - zalsa_local: ZalsaLocal::new(), |
156 |
| - phantom: PhantomData::<U>, |
157 |
| - } |
158 |
| - } |
159 |
| - |
160 |
| - /// Access the `Arc<Zalsa>`. This should always be |
161 |
| - /// possible as `zalsa_impl` only becomes |
162 |
| - /// `None` once we are in the `Drop` impl. |
163 |
| - fn zalsa_impl(&self) -> &Arc<Zalsa> { |
164 |
| - self.zalsa_impl.as_ref().unwrap() |
165 |
| - } |
166 |
| - |
167 |
| - // ANCHOR: cancel_other_workers |
168 |
| - /// Sets cancellation flag and blocks until all other workers with access |
169 |
| - /// to this storage have completed. |
170 |
| - /// |
171 |
| - /// This could deadlock if there is a single worker with two handles to the |
172 |
| - /// same database! |
173 |
| - fn cancel_others(&mut self) { |
174 |
| - let zalsa = self.zalsa_impl(); |
175 |
| - zalsa.set_cancellation_flag(); |
176 |
| - |
177 |
| - self.salsa_event(&|| Event { |
178 |
| - thread_id: std::thread::current().id(), |
179 |
| - |
180 |
| - kind: EventKind::DidSetCancellationFlag, |
181 |
| - }); |
182 |
| - |
183 |
| - let mut clones = self.coordinate.clones.lock(); |
184 |
| - while *clones != 1 { |
185 |
| - self.coordinate.cvar.wait(&mut clones); |
186 |
| - } |
187 |
| - } |
188 |
| - // ANCHOR_END: cancel_other_workers |
189 |
| -} |
190 |
| - |
191 |
| -impl<U: UserData> std::ops::Deref for DatabaseImpl<U> { |
192 |
| - type Target = U; |
193 |
| - |
194 |
| - fn deref(&self) -> &U { |
195 |
| - self.zalsa_impl().user_data().downcast_ref::<U>().unwrap() |
196 |
| - } |
197 |
| -} |
198 |
| - |
199 |
| -impl<U: UserData> std::ops::DerefMut for DatabaseImpl<U> { |
200 |
| - fn deref_mut(&mut self) -> &mut U { |
201 |
| - self.zalsa_mut() |
202 |
| - .user_data_mut() |
203 |
| - .downcast_mut::<U>() |
204 |
| - .unwrap() |
205 |
| - } |
206 |
| -} |
207 |
| - |
208 |
| -impl<U: UserData + RefUnwindSafe> RefUnwindSafe for DatabaseImpl<U> {} |
209 |
| - |
210 |
| -#[salsa_macros::db] |
211 |
| -unsafe impl<U: UserData> Database for DatabaseImpl<U> { |
212 |
| - fn zalsa(&self) -> &Zalsa { |
213 |
| - &**self.zalsa_impl() |
214 |
| - } |
215 |
| - |
216 |
| - fn zalsa_mut(&mut self) -> &mut Zalsa { |
217 |
| - self.cancel_others(); |
218 |
| - |
219 |
| - // The ref count on the `Arc` should now be 1 |
220 |
| - let arc_zalsa_mut = self.zalsa_impl.as_mut().unwrap(); |
221 |
| - let zalsa_mut = Arc::get_mut(arc_zalsa_mut).unwrap(); |
222 |
| - zalsa_mut.new_revision(); |
223 |
| - zalsa_mut |
224 |
| - } |
225 |
| - |
226 |
| - fn zalsa_local(&self) -> &ZalsaLocal { |
227 |
| - &self.zalsa_local |
228 |
| - } |
229 |
| - |
230 |
| - // Report a salsa event. |
231 |
| - fn salsa_event(&self, event: &dyn Fn() -> Event) { |
232 |
| - U::salsa_event(self, event) |
233 |
| - } |
234 |
| -} |
235 |
| - |
236 |
| -impl<U: UserData> Clone for DatabaseImpl<U> { |
237 |
| - fn clone(&self) -> Self { |
238 |
| - *self.coordinate.clones.lock() += 1; |
239 |
| - |
240 |
| - Self { |
241 |
| - zalsa_impl: self.zalsa_impl.clone(), |
242 |
| - coordinate: Arc::clone(&self.coordinate), |
243 |
| - zalsa_local: ZalsaLocal::new(), |
244 |
| - phantom: PhantomData::<U>, |
245 |
| - } |
246 |
| - } |
247 |
| -} |
248 |
| - |
249 |
| -impl<U: UserData> Drop for DatabaseImpl<U> { |
250 |
| - fn drop(&mut self) { |
251 |
| - // Drop the database handle *first* |
252 |
| - self.zalsa_impl.take(); |
253 |
| - |
254 |
| - // *Now* decrement the number of clones and notify once we have completed |
255 |
| - *self.coordinate.clones.lock() -= 1; |
256 |
| - self.coordinate.cvar.notify_all(); |
257 |
| - } |
258 |
| -} |
259 |
| - |
260 |
| -pub trait UserData: Any + Sized + Send + Sync { |
261 |
| - /// Callback invoked by the [`Database`][] at key points during salsa execution. |
262 |
| - /// By overriding this method, you can inject logging or other custom behavior. |
263 |
| - /// |
264 |
| - /// By default, the event is logged at level debug using the `tracing` crate. |
265 |
| - /// |
266 |
| - /// # Parameters |
267 |
| - /// |
268 |
| - /// * `event` a fn that, if called, will return the event that occurred |
269 |
| - fn salsa_event(_db: &DatabaseImpl<Self>, event: &dyn Fn() -> Event) { |
270 |
| - tracing::debug!("salsa_event: {:?}", event()) |
271 |
| - } |
272 |
| -} |
273 |
| - |
274 |
| -impl UserData for () {} |
275 |
| - |
276 |
| -struct Coordinate { |
277 |
| - /// Counter of the number of clones of actor. Begins at 1. |
278 |
| - /// Incremented when cloned, decremented when dropped. |
279 |
| - clones: Mutex<usize>, |
280 |
| - cvar: Condvar, |
281 |
| -} |
0 commit comments