Skip to content

Commit 1b15e41

Browse files
committed
Simplify WaitGroup implementation
1 parent c3f86b8 commit 1b15e41

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

src/storage.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Public API facades for the implementation details of [`Zalsa`] and [`ZalsaLocal`].
22
use std::marker::PhantomData;
3+
use std::mem;
34
use std::panic::RefUnwindSafe;
45

56
use crate::database::RawDatabase;
@@ -25,8 +26,6 @@ pub struct StorageHandle<Db> {
2526

2627
impl<Db> Clone for StorageHandle<Db> {
2728
fn clone(&self) -> Self {
28-
*self.coordinate.clones.lock() += 1;
29-
3029
Self {
3130
zalsa_impl: self.zalsa_impl.clone(),
3231
coordinate: CoordinateDrop(Arc::clone(&self.coordinate)),
@@ -53,7 +52,7 @@ impl<Db: Database> StorageHandle<Db> {
5352
Self {
5453
zalsa_impl: Arc::new(Zalsa::new::<Db>(event_callback, jars)),
5554
coordinate: CoordinateDrop(Arc::new(Coordinate {
56-
clones: Mutex::new(1),
55+
coordinate_lock: Mutex::default(),
5756
cvar: Default::default(),
5857
})),
5958
phantom: PhantomData,
@@ -95,17 +94,6 @@ impl<Db> Drop for Storage<Db> {
9594
}
9695
}
9796

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-
10997
impl<Db: Database> Default for Storage<Db> {
11098
fn default() -> Self {
11199
Self::new(None)
@@ -168,12 +156,14 @@ impl<Db: Database> Storage<Db> {
168156
.zalsa_impl
169157
.event(&|| Event::new(EventKind::DidSetCancellationFlag));
170158

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();
159+
let mut coordinate_lock = self.handle.coordinate.coordinate_lock.lock();
160+
let zalsa = loop {
161+
if let Some(zalsa) = Arc::get_mut(&mut self.handle.zalsa_impl) {
162+
// SAFETY: Polonius when ... https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions
163+
break unsafe { mem::transmute::<&mut Zalsa, &mut Zalsa>(zalsa) };
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+
263263
struct CoordinateDrop(Arc<Coordinate>);
264264

265265
impl std::ops::Deref for CoordinateDrop {
@@ -272,7 +272,6 @@ impl std::ops::Deref for CoordinateDrop {
272272

273273
impl 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

Comments
 (0)