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) {
158
158
// atomic unlock operation that checks that waiters queue is empty
159
159
private inner class UnlockOp (val queue : LockFreeLinkedListHead ) {
160
160
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
162
168
val update: Any = if (success) EmptyUnlocked else queue
163
169
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
165
177
}
166
178
}
167
179
}
You can’t perform that action at this time.
0 commit comments