Skip to content

Commit 4bf2932

Browse files
committed
~cosmetic, give Golang scheduler credit for LIFO buffer
1 parent c4e3ef6 commit 4bf2932

File tree

1 file changed

+24
-25
lines changed

1 file changed

+24
-25
lines changed

kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt

+24-25
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ import kotlin.random.*
4040
* that arises from placing tasks to the end of the queue.
4141
* Placing former head to the tail is necessary to provide semi-FIFO order, otherwise, queue degenerates to stack.
4242
* When a coroutine is dispatched from an external thread, it's put into the global queue.
43+
* The original idea with a single-slot LIFO buffer comes from Golang runtime scheduler by D. Vyukov.
44+
* It was proven to be "fair enough", performant and generally well accepted and initially was a significant inspiration
45+
* source for the coroutine scheduler.
4346
*
4447
* ### Work stealing and affinity
4548
*
@@ -490,7 +493,7 @@ internal class CoroutineScheduler(
490493
*/
491494
if (worker.state === WorkerState.TERMINATED) return task
492495
// Do not add CPU tasks in local queue if we are not able to execute it
493-
if (task.mode == TaskMode.NON_BLOCKING && worker.isBlocking) {
496+
if (task.mode === TaskMode.NON_BLOCKING && worker.state === WorkerState.BLOCKING) {
494497
return task
495498
}
496499
worker.mayHaveLocalTasks = true
@@ -596,7 +599,6 @@ internal class CoroutineScheduler(
596599
*/
597600
@JvmField
598601
var state = WorkerState.DORMANT
599-
val isBlocking: Boolean get() = state == WorkerState.BLOCKING
600602

601603
/**
602604
* Small state machine for termination.
@@ -654,15 +656,13 @@ internal class CoroutineScheduler(
654656
* Tries to acquire CPU token if worker doesn't have one
655657
* @return whether worker acquired (or already had) CPU token
656658
*/
657-
private fun tryAcquireCpuPermit(): Boolean {
658-
return when {
659-
state == WorkerState.CPU_ACQUIRED -> true
660-
this@CoroutineScheduler.tryAcquireCpuPermit() -> {
661-
state = WorkerState.CPU_ACQUIRED
662-
true
663-
}
664-
else -> false
659+
private fun tryAcquireCpuPermit(): Boolean = when {
660+
state == WorkerState.CPU_ACQUIRED -> true
661+
this@CoroutineScheduler.tryAcquireCpuPermit() -> {
662+
state = WorkerState.CPU_ACQUIRED
663+
true
665664
}
665+
else -> false
666666
}
667667

668668
/**
@@ -731,22 +731,21 @@ internal class CoroutineScheduler(
731731
private fun tryPark() {
732732
if (!inStack()) {
733733
parkingState.value = PARKING_ALLOWED
734-
}
735-
if (parkedWorkersStackPush(this)) {
734+
parkedWorkersStackPush(this)
736735
return
737-
} else {
738-
assert { localQueue.size == 0 }
739-
// Failed to get a parking permit => we are not in the stack
740-
while (inStack()) {
741-
if (isTerminated || state == WorkerState.TERMINATED) break
742-
if (parkingState.value != PARKED && !parkingState.compareAndSet(PARKING_ALLOWED, PARKED)) {
743-
return
744-
}
745-
tryReleaseCpu(WorkerState.PARKING)
746-
interrupted() // Cleanup interruptions
747-
if (inStack()) {
748-
park()
749-
}
736+
737+
}
738+
assert { localQueue.size == 0 }
739+
// Failed to get a parking permit => we are not in the stack
740+
while (inStack()) {
741+
if (isTerminated || state == WorkerState.TERMINATED) break
742+
if (parkingState.value != PARKED && !parkingState.compareAndSet(PARKING_ALLOWED, PARKED)) {
743+
return
744+
}
745+
tryReleaseCpu(WorkerState.PARKING)
746+
interrupted() // Cleanup interruptions
747+
if (inStack()) {
748+
park()
750749
}
751750
}
752751
}

0 commit comments

Comments
 (0)