@@ -25,8 +25,6 @@ pub struct StorageHandle<Db> {
2525
2626impl < Db > Clone for StorageHandle < Db > {
2727 fn clone ( & self ) -> Self {
28- * self . coordinate . clones . lock ( ) += 1 ;
29-
3028 Self {
3129 zalsa_impl : self . zalsa_impl . clone ( ) ,
3230 coordinate : CoordinateDrop ( Arc :: clone ( & self . coordinate ) ) ,
@@ -53,7 +51,7 @@ impl<Db: Database> StorageHandle<Db> {
5351 Self {
5452 zalsa_impl : Arc :: new ( Zalsa :: new :: < Db > ( event_callback, jars) ) ,
5553 coordinate : CoordinateDrop ( Arc :: new ( Coordinate {
56- clones : Mutex :: new ( 1 ) ,
54+ coordinate_lock : Mutex :: default ( ) ,
5755 cvar : Default :: default ( ) ,
5856 } ) ) ,
5957 phantom : PhantomData ,
@@ -95,17 +93,6 @@ impl<Db> Drop for Storage<Db> {
9593 }
9694}
9795
98- struct Coordinate {
99- /// Counter of the number of clones of actor. Begins at 1.
100- /// Incremented when cloned, decremented when dropped.
101- clones : Mutex < usize > ,
102- cvar : Condvar ,
103- }
104-
105- // We cannot panic while holding a lock to `clones: Mutex<usize>` and therefore we cannot enter an
106- // inconsistent state.
107- impl RefUnwindSafe for Coordinate { }
108-
10996impl < Db : Database > Default for Storage < Db > {
11097 fn default ( ) -> Self {
11198 Self :: new ( None )
@@ -168,12 +155,15 @@ impl<Db: Database> Storage<Db> {
168155 . zalsa_impl
169156 . event ( & || Event :: new ( EventKind :: DidSetCancellationFlag ) ) ;
170157
171- let mut clones = self . handle . coordinate . clones . lock ( ) ;
172- while * clones != 1 {
173- clones = self . handle . coordinate . cvar . wait ( clones) ;
174- }
175- // The ref count on the `Arc` should now be 1
176- let zalsa = Arc :: get_mut ( & mut self . handle . zalsa_impl ) . unwrap ( ) ;
158+ let mut coordinate_lock = self . handle . coordinate . coordinate_lock . lock ( ) ;
159+ let zalsa = loop {
160+ if Arc :: strong_count ( & self . handle . zalsa_impl ) == 1 {
161+ // SAFETY: The strong count is 1, and we never create any weak pointers,
162+ // so we have a unique reference.
163+ break unsafe { & mut * ( Arc :: as_ptr ( & self . handle . zalsa_impl ) . cast_mut ( ) ) } ;
164+ }
165+ coordinate_lock = self . handle . coordinate . cvar . wait ( coordinate_lock) ;
166+ } ;
177167 // cancellation is done, so reset the flag
178168 zalsa. runtime_mut ( ) . reset_cancellation_flag ( ) ;
179169 zalsa
@@ -260,6 +250,16 @@ impl<Db: Database> Clone for Storage<Db> {
260250 }
261251}
262252
253+ /// A simplified `WaitGroup`, this is used together with `Arc<Zalsa>` as the actual counter
254+ struct Coordinate {
255+ coordinate_lock : Mutex < ( ) > ,
256+ cvar : Condvar ,
257+ }
258+
259+ // We cannot panic while holding a lock to `clones: Mutex<usize>` and therefore we cannot enter an
260+ // inconsistent state.
261+ impl RefUnwindSafe for Coordinate { }
262+
263263struct CoordinateDrop ( Arc < Coordinate > ) ;
264264
265265impl std:: ops:: Deref for CoordinateDrop {
@@ -272,7 +272,6 @@ impl std::ops::Deref for CoordinateDrop {
272272
273273impl Drop for CoordinateDrop {
274274 fn drop ( & mut self ) {
275- * self . 0 . clones . lock ( ) -= 1 ;
276275 self . 0 . cvar . notify_all ( ) ;
277276 }
278277}
0 commit comments