Skip to content

Commit ff13b79

Browse files
committed
~ Get rid of loop in addAcquireToQueue
1 parent b5e4718 commit ff13b79

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

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

+17-15
Original file line numberDiff line numberDiff line change
@@ -189,23 +189,25 @@ private class SemaphoreImpl(private val permits: Int, acquiredPermits: Int) : Se
189189
val segment = this.tail.findSegmentAndMoveForward(id = enqIdx / SEGMENT_SIZE, startFrom = curTail,
190190
createNewSegment = ::createSegment).segment // cannot be closed
191191
val i = (enqIdx % SEGMENT_SIZE).toInt()
192-
while (true) { // cas loop on cell state
193-
val cellState = segment.get(i)
194-
when {
195-
cellState === null -> // the cell if empty, try to install continuation
196-
if (segment.cas(i, null, cont)) { // fast path -- installed continuation successfully
197-
cont.invokeOnCancellation(CancelSemaphoreAcquisitionHandler(segment, i).asHandler)
198-
return true
199-
}
200-
cellState === PERMIT -> // the cell already has permit from tryResumeNextFromQueue, try to grab it
201-
if (segment.cas(i, PERMIT, TAKEN)) { // took permit thus eliminating acquire/release pair
202-
cont.resume(Unit)
203-
return true
204-
}
205-
cellState === BROKEN -> return false // broken cell, need to retry on a different cell
206-
else -> error("Invalid state $cellState") // this cannot happen
192+
var cellState = segment.get(i)
193+
// Fast path -- if the cell is empty, try to install continuation
194+
if (cellState === null) {
195+
if (segment.cas(i, null, cont)) { // installed continuation successfully
196+
cont.invokeOnCancellation(CancelSemaphoreAcquisitionHandler(segment, i).asHandler)
197+
return true
207198
}
199+
cellState = segment.get(i) // Reread on CAS failure -- it was updated to either PERMIT or BROKEN
208200
}
201+
// the cell already has permit from tryResumeNextFromQueue, try to grab it
202+
if (cellState === PERMIT) {
203+
if (segment.cas(i, PERMIT, TAKEN)) { // took permit thus eliminating acquire/release pair
204+
cont.resume(Unit)
205+
return true
206+
}
207+
cellState = segment.get(i) // Reread on CAS failure -- it could be update to BROKEN
208+
}
209+
check(cellState === BROKEN) { "Invalid state $cellState" }
210+
return false // broken cell, need to retry on a different cell
209211
}
210212

211213
@Suppress("UNCHECKED_CAST")

0 commit comments

Comments
 (0)