diff --git a/src/storage.rs b/src/storage.rs index 4d1bacd2..88cbbfb7 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -25,6 +25,18 @@ pub struct StorageHandle { phantom: PhantomData Db>, } +impl Clone for StorageHandle { + fn clone(&self) -> Self { + *self.coordinate.clones.lock() += 1; + + Self { + zalsa_impl: self.zalsa_impl.clone(), + coordinate: CoordinateDrop(Arc::clone(&self.coordinate)), + phantom: PhantomData, + } + } +} + impl Default for StorageHandle { fn default() -> Self { Self { @@ -40,15 +52,8 @@ impl Default for StorageHandle { impl StorageHandle { pub fn into_storage(self) -> Storage { - let StorageHandle { - zalsa_impl, - coordinate, - phantom, - } = self; Storage { - zalsa_impl, - coordinate, - phantom, + handle: self, zalsa_local: ZalsaLocal::new(), } } @@ -68,20 +73,10 @@ pub unsafe trait HasStorage: Database + Clone + Sized { /// Concrete implementation of the [`Database`] trait with local state that can be used to drive computations. pub struct Storage { - // Note: Drop order is important, zalsa_impl needs to drop before coordinate - /// Reference to the database. - zalsa_impl: Arc, - - // Note: Drop order is important, coordinate needs to drop after zalsa_impl - /// Coordination data for cancellation of other handles when `zalsa_mut` is called. - /// This could be stored in Zalsa but it makes things marginally cleaner to keep it separate. - coordinate: CoordinateDrop, + handle: StorageHandle, /// Per-thread state zalsa_local: zalsa_local::ZalsaLocal, - - /// We store references to `Db` - phantom: PhantomData Db>, } struct Coordinate { @@ -98,13 +93,8 @@ impl RefUnwindSafe for Coordinate {} impl Default for Storage { fn default() -> Self { Self { - zalsa_impl: Arc::new(Zalsa::new::()), - coordinate: CoordinateDrop(Arc::new(Coordinate { - clones: Mutex::new(1), - cvar: Default::default(), - })), + handle: StorageHandle::default(), zalsa_local: ZalsaLocal::new(), - phantom: PhantomData, } } } @@ -114,16 +104,10 @@ impl Storage { /// and [`std::panic::UnwindSafe`]. pub fn into_zalsa_handle(self) -> StorageHandle { let Storage { - zalsa_impl, - coordinate, - phantom, + handle, zalsa_local: _, } = self; - StorageHandle { - zalsa_impl, - coordinate, - phantom, - } + handle } pub fn debug_input_entries(&self) -> impl Iterator> @@ -171,7 +155,7 @@ impl Storage { /// possible as `zalsa_impl` only becomes /// `None` once we are in the `Drop` impl. fn zalsa_impl(&self) -> &Arc { - &self.zalsa_impl + &self.handle.zalsa_impl } // ANCHOR: cancel_other_workers @@ -181,13 +165,13 @@ impl Storage { /// This could deadlock if there is a single worker with two handles to the /// same database! fn cancel_others(&self, db: &Db) { - self.zalsa_impl.set_cancellation_flag(); + self.handle.zalsa_impl.set_cancellation_flag(); db.salsa_event(&|| Event::new(EventKind::DidSetCancellationFlag)); - let mut clones = self.coordinate.clones.lock(); + let mut clones = self.handle.coordinate.clones.lock(); while *clones != 1 { - self.coordinate.cvar.wait(&mut clones); + self.handle.coordinate.cvar.wait(&mut clones); } } // ANCHOR_END: cancel_other_workers @@ -195,7 +179,7 @@ impl Storage { unsafe impl ZalsaDatabase for T { fn zalsa(&self) -> &Zalsa { - &self.storage().zalsa_impl + &self.storage().handle.zalsa_impl } fn zalsa_mut(&mut self) -> &mut Zalsa { @@ -203,7 +187,7 @@ unsafe impl ZalsaDatabase for T { let storage = self.storage_mut(); // The ref count on the `Arc` should now be 1 - let zalsa_mut = Arc::get_mut(&mut storage.zalsa_impl).unwrap(); + let zalsa_mut = Arc::get_mut(&mut storage.handle.zalsa_impl).unwrap(); zalsa_mut.new_revision(); zalsa_mut } @@ -219,13 +203,9 @@ unsafe impl ZalsaDatabase for T { impl Clone for Storage { fn clone(&self) -> Self { - *self.coordinate.clones.lock() += 1; - Self { - zalsa_impl: self.zalsa_impl.clone(), - coordinate: CoordinateDrop(Arc::clone(&self.coordinate)), + handle: self.handle.clone(), zalsa_local: ZalsaLocal::new(), - phantom: PhantomData, } } }