@@ -9,6 +9,7 @@ import kotlinx.coroutines.*
9
9
import kotlinx.coroutines.internal.*
10
10
import kotlinx.coroutines.selects.*
11
11
import kotlin.contracts.*
12
+ import kotlin.jvm.*
12
13
import kotlin.native.concurrent.*
13
14
14
15
/* *
@@ -20,7 +21,7 @@ import kotlin.native.concurrent.*
20
21
*
21
22
* JVM API note:
22
23
* Memory semantic of the [Mutex] is similar to `synchronized` block on JVM:
23
- * An unlock on a [Mutex] happens-before every subsequent successful lock on that [Mutex].
24
+ * An unlock operation on a [Mutex] happens-before every subsequent successful lock on that [Mutex].
24
25
* Unsuccessful call to [tryLock] do not have any memory effects.
25
26
*/
26
27
public interface Mutex {
@@ -171,9 +172,12 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
171
172
172
173
override fun tryLock (owner : Any? ): Boolean =
173
174
if (tryAcquire()) {
175
+ assert { this .owner.value == = NO_OWNER }
174
176
this .owner.value = owner
175
177
true
176
- } else false
178
+ } else {
179
+ false
180
+ }
177
181
178
182
override fun unlock (owner : Any? ) {
179
183
while (true ) {
@@ -192,7 +196,7 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
192
196
}
193
197
}
194
198
195
- @Suppress(" UNCHECKED_CAST" )
199
+ @Suppress(" UNCHECKED_CAST" , " OverridingDeprecatedMember " )
196
200
override val onLock: SelectClause2 <Any ?, Mutex > get() = SelectClause2Impl (
197
201
clauseObject = this ,
198
202
regFunc = MutexImpl ::onLockRegFunction as RegistrationFunction ,
@@ -201,52 +205,67 @@ internal open class MutexImpl(locked: Boolean) : SemaphoreImpl(1, if (locked) 1
201
205
)
202
206
203
207
protected open fun onLockRegFunction (select : SelectInstance <* >, owner : Any? ) {
204
- onAcquire.regFunc( this , SelectInstanceWithOwner (select, owner), owner)
208
+ onAcquireRegFunction( SelectInstanceWithOwner (select, owner), owner)
205
209
}
206
210
207
211
protected open fun onLockProcessResult (owner : Any? , result : Any? ): Any? {
208
- onAcquire.processResFunc(this , null , result)
209
212
return this
210
213
}
211
214
212
- protected val onCancellationUnlockConstructor: OnCancellationConstructor =
213
- { select : SelectInstance <* >, owner: Any? , ignoredResult : Any? ->
215
+ private val onCancellationUnlockConstructor: OnCancellationConstructor =
216
+ { _ : SelectInstance <* >, owner: Any? , _ : Any? ->
214
217
{ unlock(owner) }
215
218
}
216
219
217
220
private inner class CancellableContinuationWithOwner (
221
+ @JvmField
218
222
val cont : CancellableContinuation <Unit >,
223
+ @JvmField
219
224
val owner : Any?
220
225
) : CancellableContinuation<Unit> by cont {
221
226
override fun tryResume (value : Unit , idempotent : Any? , onCancellation : ((cause: Throwable ) -> Unit )? ): Any? {
222
- val token = cont.tryResume(value, idempotent, onCancellation)
223
- if (token != = null ) this @MutexImpl.owner.value = owner
227
+ assert { this @MutexImpl.owner.value == = NO_OWNER }
228
+ val token = cont.tryResume(value, idempotent) {
229
+ assert { this @MutexImpl.owner.value.let { it == = NO_OWNER || it == = owner } }
230
+ this @MutexImpl.owner.value = owner
231
+ unlock(owner)
232
+ }
233
+ if (token != null ) {
234
+ assert { this @MutexImpl.owner.value == = NO_OWNER }
235
+ this @MutexImpl.owner.value = owner
236
+ }
224
237
return token
225
238
}
226
239
227
240
override fun resume (value : Unit , onCancellation : ((cause: Throwable ) -> Unit )? ) {
241
+ assert { this @MutexImpl.owner.value == = NO_OWNER }
228
242
this @MutexImpl.owner.value = owner
229
- cont.resume(value, onCancellation)
243
+ cont.resume(value) { unlock(owner) }
230
244
}
231
245
}
232
246
233
247
private inner class SelectInstanceWithOwner <Q >(
248
+ @JvmField
234
249
val select : SelectInstance <Q >,
250
+ @JvmField
235
251
val owner : Any?
236
252
) : SelectInstance<Q> by select {
237
253
override fun trySelect (clauseObject : Any , result : Any? ): Boolean {
254
+ assert { this @MutexImpl.owner.value == = NO_OWNER }
255
+ this @MutexImpl.owner.value = owner
238
256
return select.trySelect(clauseObject, result).also { success ->
239
- if (success) this @MutexImpl.owner.value = owner
257
+ if (! success) this @MutexImpl.owner.value = NO_OWNER
240
258
}
241
259
}
242
260
243
261
override fun selectInRegistrationPhase (internalResult : Any? ) {
244
- select.selectInRegistrationPhase(internalResult)
262
+ assert { this @MutexImpl.owner.value == = NO_OWNER }
245
263
this @MutexImpl.owner.value = owner
264
+ select.selectInRegistrationPhase(internalResult)
246
265
}
247
266
}
248
267
249
- override fun toString () = " Mutex@${hexAddress} "
268
+ override fun toString () = " Mutex@${hexAddress} [isLocked= $isLocked ,owner= ${owner.value} ] "
250
269
}
251
270
252
271
@SharedImmutable
0 commit comments