Skip to content

Commit 72d58a8

Browse files
Rename PreemptingDispatcher -> WorkStealingDispatcher and rewrite it.
The old implementation had a bug where the dispatch loop coroutine could prevent a dispatch context from finishing. The new implementation avoids the dispatch coroutine entirely by using a special Continuation implementation.
1 parent eeb366b commit 72d58a8

File tree

3 files changed

+253
-217
lines changed

3 files changed

+253
-217
lines changed

workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/internal/compose/RecomposerDriver.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.squareup.workflow1.internal.compose
22

33
import androidx.compose.runtime.MonotonicFrameClock
44
import androidx.compose.runtime.Recomposer
5-
import com.squareup.workflow1.internal.compose.coroutines.PreemptingDispatcher
5+
import com.squareup.workflow1.internal.compose.coroutines.WorkStealingDispatcher
66
import com.squareup.workflow1.internal.compose.coroutines.requireSend
77
import kotlinx.coroutines.CancellableContinuation
88
import kotlinx.coroutines.CoroutineDispatcher
@@ -65,18 +65,20 @@ interface RecomposerDriver {
6565
)
6666
}
6767

68-
@OptIn(ExperimentalStdlibApi::class)
6968
internal fun RecomposerDriver(recomposer: Recomposer): RecomposerDriver =
7069
RealRecomposerDriver(
7170
recomposer,
72-
PreemptingDispatcher(
73-
recomposer.effectCoroutineContext[CoroutineDispatcher] ?: Dispatchers.Default
71+
WorkStealingDispatcher(
72+
// It's fine to run the recompose loop on Unconfined since it's thread-safe internally, and
73+
// the only threading guarantee we care about is that the frame callback is executed during
74+
// the render pass, which we already control and doesn't depend on what dispatcher is used.
75+
Dispatchers.Unconfined
7476
)
7577
)
7678

7779
private class RealRecomposerDriver(
7880
private val recomposer: Recomposer,
79-
private val dispatcher: PreemptingDispatcher,
81+
private val dispatcher: WorkStealingDispatcher,
8082
) : RecomposerDriver, MonotonicFrameClock {
8183

8284
private val frameRequestChannel = Channel<FrameRequest<*>>(capacity = 1)

workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/internal/compose/coroutines/PreemptingDispatcher.kt

Lines changed: 0 additions & 212 deletions
This file was deleted.

0 commit comments

Comments
 (0)