Skip to content

Commit 0d9b789

Browse files
committed
Make tryAcquire linearizable
1 parent da8f7c6 commit 0d9b789

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

kotlinx-coroutines-core/common/src/sync/Semaphore.kt

+18-3
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,24 @@ private class SemaphoreImpl(
113113
private val deqIdx = atomic(0L)
114114

115115
override fun tryAcquire(): Boolean {
116-
_availablePermits.loop { p ->
117-
if (p <= 0) return false
118-
if (_availablePermits.compareAndSet(p, p - 1)) return true
116+
while (true) {
117+
val p = _availablePermits.value
118+
if (p > 0) {
119+
// try to get a permit by updating the counter
120+
if (_availablePermits.compareAndSet(p, p - 1)) return true
121+
} else {
122+
// check whether there is a permit in the queue
123+
val enqIdx = this.enqIdx.value
124+
val deqIdx = this.deqIdx.value
125+
if (enqIdx >= deqIdx) return false
126+
// try to get a permit from the queue
127+
if (this.enqIdx.compareAndSet(enqIdx, enqIdx + 1)) {
128+
// update the counter of available permits and check
129+
// whether it was legal to get a permit from the queue
130+
if (_availablePermits.getAndDecrement() <= 0) return true
131+
else release()
132+
}
133+
}
119134
}
120135
}
121136

0 commit comments

Comments
 (0)