@@ -170,14 +170,36 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
170
170
acquire(contWithOwner)
171
171
}
172
172
173
- override fun tryLock (owner : Any? ): Boolean =
174
- if (tryAcquire()) {
175
- assert { this .owner.value == = NO_OWNER }
176
- this .owner.value = owner
177
- true
178
- } else {
179
- false
173
+ override fun tryLock (owner : Any? ): Boolean = when (tryLockImpl(owner)) {
174
+ TRY_LOCK_SUCCESS -> true
175
+ TRY_LOCK_FAILED -> false
176
+ TRY_LOCK_ALREADY_LOCKED_BY_OWNER -> error(" This mutex is already locked by the specified owner: $owner " )
177
+ else -> error(" unexpected" )
178
+ }
179
+
180
+ private fun tryLockImpl (owner : Any? ): Int {
181
+ while (true ) {
182
+ if (tryAcquire()) {
183
+ assert { this .owner.value == = NO_OWNER }
184
+ this .owner.value = owner
185
+ return TRY_LOCK_SUCCESS
186
+ } else {
187
+ // The semaphore permit acquisition has failed.
188
+ // However, we need to check that this mutex is not
189
+ // locked by our owner.
190
+ if (owner != null ) {
191
+ // Is this mutex locked by our owner?
192
+ if (holdsLock(owner)) return TRY_LOCK_ALREADY_LOCKED_BY_OWNER
193
+ // This mutex is either locked by another owner or unlocked.
194
+ // In the latter case, it is possible that it WAS locked by
195
+ // our owner when the semaphore permit acquisition has failed.
196
+ // To preserve linearizability, the operation restarts in this case.
197
+ if (! isLocked) continue
198
+ }
199
+ return TRY_LOCK_FAILED
200
+ }
180
201
}
202
+ }
181
203
182
204
override fun unlock (owner : Any? ) {
183
205
while (true ) {
@@ -205,10 +227,17 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
205
227
)
206
228
207
229
protected open fun onLockRegFunction (select : SelectInstance <* >, owner : Any? ) {
208
- onAcquireRegFunction(SelectInstanceWithOwner (select, owner), owner)
230
+ if (owner != null && holdsLock(owner)) {
231
+ select.selectInRegistrationPhase(ON_LOCK_ALREADY_LOCKED_BY_OWNER )
232
+ } else {
233
+ onAcquireRegFunction(SelectInstanceWithOwner (select, owner), owner)
234
+ }
209
235
}
210
236
211
237
protected open fun onLockProcessResult (owner : Any? , result : Any? ): Any? {
238
+ if (result == ON_LOCK_ALREADY_LOCKED_BY_OWNER ) {
239
+ error(" This mutex is already locked by the specified owner: $owner " )
240
+ }
212
241
return this
213
242
}
214
243
@@ -263,3 +292,8 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
263
292
}
264
293
265
294
private val NO_OWNER = Symbol (" NO_OWNER" )
295
+ private val ON_LOCK_ALREADY_LOCKED_BY_OWNER = Symbol (" ALREADY_LOCKED_BY_OWNER" )
296
+
297
+ private const val TRY_LOCK_SUCCESS = 0
298
+ private const val TRY_LOCK_FAILED = 1
299
+ private const val TRY_LOCK_ALREADY_LOCKED_BY_OWNER = 2
0 commit comments