@@ -137,10 +137,12 @@ enum WaitingTime {
137137pub struct CrossProcessLockGuard {
138138 /// A clone of [`CrossProcessLock::inner`].
139139 ///
140- /// - Every time [`CrossProcessLockGuard`] is cloned, the number of holders
141- /// of `CrossProcessLockInner` increases.
142- /// - Every time [`CrossProcessLockGuard`] is dropped, the number of holders
143- /// of `CrossProcessLockInner` decreases.
140+ /// The number of guards/holders is based on the `Weak::weak_count`.
141+ ///
142+ /// - Every time [`CrossProcessLockGuard`] is cloned, `Weak` is cloned, and
143+ /// thus the number of holders of `CrossProcessLockInner` increases.
144+ /// - Every time [`CrossProcessLockGuard`] is dropped, `Weak` is dropped,
145+ /// and thus the number of holders of `CrossProcessLockInner` decreases.
144146 inner : Weak < CrossProcessLockInner > ,
145147}
146148
@@ -157,7 +159,13 @@ impl CrossProcessLockGuard {
157159 /// See [`CrossProcessLockState::Dirty`] to learn more about the semantics
158160 /// of _dirty_.
159161 pub fn is_dirty ( & self ) -> bool {
160- self . inner . upgrade ( ) . map ( |inner| inner. is_dirty ( ) ) . unwrap_or ( false )
162+ self . inner
163+ . upgrade ( )
164+ . map ( |inner| inner. is_dirty ( ) )
165+ // If it's not possible to upgrade the weak pointer, it means the lock _and_ the
166+ // `renew_task` have been dropped. In this case, whether the lock is dirty or
167+ // not doesn't make any difference.
168+ . unwrap_or ( false )
161169 }
162170
163171 /// Clear the dirty state from the cross-process lock associated to this
@@ -167,6 +175,9 @@ impl CrossProcessLockGuard {
167175 /// this method is called. This allows recovering from a dirty state and
168176 /// marking that it has recovered.
169177 pub fn clear_dirty ( & self ) {
178+ // If it's not possible to upgrade the weak pointer, it means the lock _and_ the
179+ // `renew_task` have been dropped. Marking the lock as non-dirty makes no
180+ // particular sense, so we do nothing.
170181 if let Some ( inner) = self . inner . upgrade ( ) {
171182 inner. clear_dirty ( ) ;
172183 }
@@ -204,22 +215,26 @@ pub struct CrossProcessLock<L> {
204215 //
205216 // Notes about the `Arc`/`Weak` usage:
206217 //
218+ // - We want to track the number of holders, i.e. the number of guards. To achieve that, we
219+ // could use a thread-safe counter, or hijack `Arc` and `Weak` which provide two thread-safe
220+ // counters: strong count and weak count.
207221 // - `CrossProcessLock` holds an `Arc` (this field).
208- // - The `renew_task` holds an `Arc` (a clone of this field).
209- // - `CrossProcessLockGuard` holds a `Weak`.
222+ // - `renew_task` holds an `Arc` (a clone of this field).
223+ // - `CrossProcessLockGuard` holds a `Weak` (it could use an `Arc`, but a `Weak` is fine in
224+ // this context and offers a unique counter for guards!).
210225 // - Counting holders = counting the number of `Weak` pointers.
211226 // - It is safe to upgrade the `Weak` pointer to an `Arc` (to get information about dirtiness)
212- // in a guard because the `renew_task` holds a clone of the `Arc` and will not exit as long
213- // as all guards have been dropped.
227+ // in a guard because the `renew_task` holds a clone of the `Arc` and will not exit until all
228+ // guards have been dropped.
214229 // - It is always possible to create a `Weak` pointer (i) either from `CrossProcessLock` by
215230 // using `Arc::downgrade`, (ii) or from `CrossProcessLockGuard` by cloning it.
216231 inner : Arc < CrossProcessLockInner > ,
217232
218233 /// The key used in the key/value mapping for the lock entry.
219234 lock_key : String ,
220235
221- /// A mutex to control an attempt to take the lock, to avoid making it
222- /// re-entrant.
236+ /// A mutex to control an attempt to take the lock, to prevent someone using
237+ /// it in a re-entrant way .
223238 locking_attempt : Arc < Mutex < ( ) > > ,
224239
225240 /// Backoff time, in milliseconds.
0 commit comments