@@ -172,13 +172,50 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
172
172
173
173
override fun tryLock (owner : Any? ): Boolean =
174
174
if (tryAcquire()) {
175
- assert { this .owner.value == = NO_OWNER }
175
+ val previousOwner = this .owner.value
176
+ // First setup the invariant, then fail on assert of things went south
176
177
this .owner.value = owner
178
+ assert { previousOwner == = NO_OWNER }
177
179
true
178
180
} else {
181
+ /*
182
+ * We have to ensure invariant that any lock attempt on
183
+ * mutex already locked with the same owner fails with ISE.
184
+ * Here we can have the following logical race:
185
+ * - T1: lock(O1) holds
186
+ * - T2: tryLock(O2) fails, we fall into this branch
187
+ * - T1: unlock(O1), lock(O3)
188
+ * - T2: reads O3 in else branch
189
+ */
190
+ check(owner == = null || owner != = this .owner.value) {
191
+ " Invariant violation: already locked by $owner "
192
+ }
179
193
false
180
194
}
181
195
196
+ // override fun tryLock(owner: Any?): Boolean {
197
+ // /*
198
+ // * Here we are maintaining invariant "tryLock(owner) on locked with this very owner mutex throws ISE".
199
+ // * In order to achieve that and avoid check-and-act, we do stamped comparison, restarting the operation if
200
+ // * stamped check failed.
201
+ // */
202
+ // while (true) {
203
+ // val ownerBeforeAcquisition = this.owner.value
204
+ // return if (tryAcquire()) {
205
+ // assert { this.owner.value === NO_OWNER }
206
+ // this.owner.value = owner
207
+ // true
208
+ // } else {
209
+ // // TODO handle nulls as well and do not retry
210
+ // val ownerAfterAcquisition = this.owner.value
211
+ // // Owner changed -> we are racing with lock/unlock and cannot deterministically check the invariant, retry
212
+ // if (ownerBeforeAcquisition !== ownerAfterAcquisition) continue
213
+ // check(owner !== ownerAfterAcquisition) { "Invariant violation: already locked by $owner" }
214
+ // false
215
+ // }
216
+ // }
217
+ // }
218
+
182
219
override fun unlock (owner : Any? ) {
183
220
while (true ) {
184
221
// Is this mutex locked?
0 commit comments