File tree Expand file tree Collapse file tree 1 file changed +14
-2
lines changed
kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental Expand file tree Collapse file tree 1 file changed +14
-2
lines changed Original file line number Diff line number Diff line change @@ -158,10 +158,22 @@ public class Mutex(locked: Boolean = false) {
158158 // atomic unlock operation that checks that waiters queue is empty
159159 private inner class UnlockOp (val queue : LockFreeLinkedListHead ) {
160160 fun helpComplete (): Boolean {
161- val success = queue.isEmpty // Note: queue cannot change anymore (so decision is consistent)
161+ /*
162+ Note: queue cannot change while this UnlockOp is in progress, so all concurrent attempts to
163+ make a decision will reach it consistently. It does not matter what is a proposed
164+ decision when this UnlockOp is not longer active, because in this case the following CAS
165+ will fail anyway.
166+ */
167+ val success = queue.isEmpty
162168 val update: Any = if (success) EmptyUnlocked else queue
163169 STATE .compareAndSet(this @Mutex, this @UnlockOp, update)
164- return success
170+ /*
171+ `helpComplete` invocation from the original `unlock` invocation may be coming too late, when
172+ some other thread had already helped to complete it (either successfully or not).
173+ That operation was unsuccessful if `state` was restored to this `queue` reference and
174+ that is what is being checked below.
175+ */
176+ return state != = queue
165177 }
166178 }
167179}
You can’t perform that action at this time.
0 commit comments