@@ -703,37 +703,18 @@ internal class CoroutineScheduler(
703
703
assert { state == WorkerState .BLOCKING }
704
704
decrementBlockingTasks()
705
705
if (tryAcquireCpuPermit()) return
706
- class CpuPermitTransfer {
707
- private val status = atomic(false )
708
- fun check (): Boolean = status.value
709
- fun complete (): Boolean = status.compareAndSet(false , true )
710
- }
711
- val permitTransfer = CpuPermitTransfer ()
712
- val blockedWorker = this @Worker
713
- scheduler.dispatch(Runnable {
706
+ val permitTransfer = PermitTransfer ()
707
+ scheduler.dispatch(permitTransfer.releaseFun {
714
708
// this code runs in a different worker thread that holds a CPU token
715
709
val cpuHolder = currentThread() as Worker
716
710
assert { cpuHolder.state == WorkerState .CPU_ACQUIRED }
717
- if (permitTransfer.complete()) {
718
- cpuHolder.state = WorkerState .BLOCKING
719
- LockSupport .unpark(blockedWorker)
720
- }
711
+ cpuHolder.state = WorkerState .BLOCKING
721
712
}, taskContext = NonBlockingContext )
722
- while (true ) {
723
- if (permitTransfer.check()) {
724
- state = WorkerState .CPU_ACQUIRED
725
- break
726
- }
727
- if (tryAcquireCpuPermit()) {
728
- if (! permitTransfer.complete()) {
729
- // race: transfer was completed by another thread
730
- releaseCpuPermit()
731
- }
732
- assert { state == WorkerState .CPU_ACQUIRED }
733
- break
734
- }
735
- LockSupport .parkNanos(CPU_REACQUIRE_PARK_NS )
736
- }
713
+ permitTransfer.acquire(
714
+ tryAllocatePermit = this @CoroutineScheduler::tryAcquireCpuPermit,
715
+ deallocatePermit = ::releaseCpuPermit
716
+ )
717
+ state = WorkerState .CPU_ACQUIRED
737
718
}
738
719
739
720
override fun run () = runWorker()
@@ -841,14 +822,20 @@ internal class CoroutineScheduler(
841
822
842
823
private fun inStack (): Boolean = nextParkedWorker != = NOT_IN_STACK
843
824
825
+ private var currentTask: Task ? = null
826
+
844
827
private fun executeTask (task : Task ) {
845
828
val taskMode = task.mode
846
829
idleReset(taskMode)
847
830
beforeTask(taskMode)
831
+ currentTask = task
848
832
runSafely(task)
833
+ currentTask = null
849
834
afterTask(taskMode)
850
835
}
851
836
837
+ internal fun getCurrentTaskImpl (): TaskImpl ? = currentTask as ? TaskImpl
838
+
852
839
private fun beforeTask (taskMode : Int ) {
853
840
if (taskMode == TASK_NON_BLOCKING ) return
854
841
// Always notify about new work when releasing CPU-permit to execute some blocking task
@@ -1091,7 +1078,9 @@ internal fun mayNotBlock(thread: Thread) = thread is CoroutineScheduler.Worker &
1091
1078
*/
1092
1079
internal fun withUnlimitedIOScheduler (blocking : () -> Unit ) {
1093
1080
withoutCpuPermit {
1094
- blocking()
1081
+ withTaskBlockingDispatch {
1082
+ blocking()
1083
+ }
1095
1084
}
1096
1085
}
1097
1086
@@ -1104,3 +1093,14 @@ private fun withoutCpuPermit(body: () -> Unit) {
1104
1093
if (releasedPermit) worker.reacquireCpu()
1105
1094
}
1106
1095
}
1096
+
1097
+ private fun withTaskBlockingDispatch (body : () -> Unit ) {
1098
+ val worker = Thread .currentThread() as ? CoroutineScheduler .Worker ? : return body()
1099
+ val dispatchAware = worker.getCurrentTaskImpl()?.block as ? BlockingDispatchAware ? : return body()
1100
+ dispatchAware.beforeDispatchElsewhere()
1101
+ try {
1102
+ return body()
1103
+ } finally {
1104
+ dispatchAware.afterDispatchBack()
1105
+ }
1106
+ }
0 commit comments