@@ -40,6 +40,9 @@ import kotlin.random.*
40
40
* that arises from placing tasks to the end of the queue.
41
41
* Placing former head to the tail is necessary to provide semi-FIFO order, otherwise, queue degenerates to stack.
42
42
* 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.
43
46
*
44
47
* ### Work stealing and affinity
45
48
*
@@ -490,7 +493,7 @@ internal class CoroutineScheduler(
490
493
*/
491
494
if (worker.state == = WorkerState .TERMINATED ) return task
492
495
// 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 ) {
494
497
return task
495
498
}
496
499
worker.mayHaveLocalTasks = true
@@ -596,7 +599,6 @@ internal class CoroutineScheduler(
596
599
*/
597
600
@JvmField
598
601
var state = WorkerState .DORMANT
599
- val isBlocking: Boolean get() = state == WorkerState .BLOCKING
600
602
601
603
/* *
602
604
* Small state machine for termination.
@@ -654,15 +656,13 @@ internal class CoroutineScheduler(
654
656
* Tries to acquire CPU token if worker doesn't have one
655
657
* @return whether worker acquired (or already had) CPU token
656
658
*/
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
665
664
}
665
+ else -> false
666
666
}
667
667
668
668
/* *
@@ -731,22 +731,21 @@ internal class CoroutineScheduler(
731
731
private fun tryPark () {
732
732
if (! inStack()) {
733
733
parkingState.value = PARKING_ALLOWED
734
- }
735
- if (parkedWorkersStackPush(this )) {
734
+ parkedWorkersStackPush(this )
736
735
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()
750
749
}
751
750
}
752
751
}
0 commit comments