Coroutines Concepts
Dispatcher Queue Model
A dispatcher decides where work should run; this example models dispatching as a deterministic queue of labels.
dispatcher
A dispatcher chooses an execution lane. This page models lanes as plain strings so replay stays deterministic.
Dispatcher Queue Model
DispatcherQueueModel.kt
Replay: real traced execution (multi-file project)
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine
suspend fun dispatch(lane: String, task: String): String {
return "$lane:$task"
}
fun main() {
val lane = "main"
val queue = mutableListOf("parse", "render", "publish")
val handled = mutableListOf<String>()
val work: suspend () -> String = {
for (task in queue) {
handled.add(dispatch(lane, task))
}
handled.joinToString(",")
}
work.startCoroutine(object : Continuation<String> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<String>) {
handled.add("complete")
}
})
println("lane=$lane")
println("handled=" + handled.joinToString(","))
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine
suspend fun dispatch(lane: String, task: String): String {
return "$lane:$task"
}
fun main() {
val lane = "io"
val queue = mutableListOf("parse", "render", "publish")
val handled = mutableListOf<String>()
val work: suspend () -> String = {
for (task in queue) {
handled.add(dispatch(lane, task))
}
handled.joinToString(",")
}
work.startCoroutine(object : Continuation<String> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<String>) {
handled.add("complete")
}
})
println("lane=$lane")
println("handled=" + handled.joinToString(","))
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine
suspend fun dispatch(lane: String, task: String): String {
return "$lane:$task"
}
fun main() {
val lane = "default"
val queue = mutableListOf("parse", "render", "publish")
val handled = mutableListOf<String>()
val work: suspend () -> String = {
for (task in queue) {
handled.add(dispatch(lane, task))
}
handled.joinToString(",")
}
work.startCoroutine(object : Continuation<String> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<String>) {
handled.add("complete")
}
})
println("lane=$lane")
println("handled=" + handled.joinToString(","))
}
lane ← main, queue ← [parse, render, publish], handled ← [], work ← () -> kotlin.String
9fun main() {10 val lane→ main = "main" //@lane="io", "default"11 val queue→ [parse, render, publish] = mutableListOf("parse", "render", "publish")12 val handled→ [] = mutableListOf<String>()1314 val work→ () -> kotlin.String: suspend () -> String = {15 for (task in queue) {16 handled.add(dispatch(lane, task))17 }18 handled.joinToString(",")19 }2021 work() -> kotlin.String.startCoroutine(object : Continuation<String> {22 override val context = EmptyCoroutineContext2324 override fun resumeWith(result: Result<String>) {25 handled.add("complete")26 }27 })suspend fun dispatch(lane: String, task: String): String
pass 1 of 35suspend fun dispatch(lanemain: String, taskparse: String): String {6 return "$lanemain:$taskparse"7}All 3 passes — pass 1 is the card above pass task1 parse 2 render 3 publish handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}override fun resumeWith(result: Result<String>)
21work() -> kotlin.String.startCoroutine(object : Continuation<String> {22 override val context = EmptyCoroutineContext2324 override fun resumeWith(resultSuccess(main:parse,main:render,main:publish): Result<String>) {25 handled[main:parse, main:render, main:publish].add("complete")26 }27})println("lane=$lane")
29 println("lane=$lanemain")30 println("handled=" + handled[main:parse, main:render, main:publish, complete].joinToString(","))31}outputlane=main handled=main:parse,main:render,main:publish,complete
lane ← io, queue ← [parse, render, publish], handled ← [], work ← () -> kotlin.String
9fun main() {10 val lane→ io = "io"11 val queue→ [parse, render, publish] = mutableListOf("parse", "render", "publish")12 val handled→ [] = mutableListOf<String>()1314 val work→ () -> kotlin.String: suspend () -> String = {15 for (task in queue) {16 handled.add(dispatch(lane, task))17 }18 handled.joinToString(",")19 }2021 work() -> kotlin.String.startCoroutine(object : Continuation<String> {22 override val context = EmptyCoroutineContext2324 override fun resumeWith(result: Result<String>) {25 handled.add("complete")26 }27 })suspend fun dispatch(lane: String, task: String): String
pass 1 of 35suspend fun dispatch(laneio: String, taskparse: String): String {6 return "$laneio:$taskparse"7}All 3 passes — pass 1 is the card above pass task1 parse 2 render 3 publish handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}override fun resumeWith(result: Result<String>)
21work() -> kotlin.String.startCoroutine(object : Continuation<String> {22 override val context = EmptyCoroutineContext2324 override fun resumeWith(resultSuccess(io:parse,io:render,io:publish): Result<String>) {25 handled[io:parse, io:render, io:publish].add("complete")26 }27})println("lane=$lane")
29 println("lane=$laneio")30 println("handled=" + handled[io:parse, io:render, io:publish, complete].joinToString(","))31}outputlane=io handled=io:parse,io:render,io:publish,complete
lane ← default, queue ← [parse, render, publish], handled ← []
9fun main() {10 val lane→ default = "default"11 val queue→ [parse, render, publish] = mutableListOf("parse", "render", "publish")12 val handled→ [] = mutableListOf<String>()1314 val work→ () -> kotlin.String: suspend () -> String = {15 for (task in queue) {16 handled.add(dispatch(lane, task))17 }18 handled.joinToString(",")19 }2021 work() -> kotlin.String.startCoroutine(object : Continuation<String> {22 override val context = EmptyCoroutineContext2324 override fun resumeWith(result: Result<String>) {25 handled.add("complete")26 }27 })suspend fun dispatch(lane: String, task: String): String
pass 1 of 35suspend fun dispatch(lanedefault: String, taskparse: String): String {6 return "$lanedefault:$taskparse"7}All 3 passes — pass 1 is the card above pass task1 parse 2 render 3 publish handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}handled.add(dispatch(lane, task))
15for (task in queue) {16 handled.add(dispatch(lane, task))17}override fun resumeWith(result: Result<String>)
21work() -> kotlin.String.startCoroutine(object : Continuation<String> {22 override val context = EmptyCoroutineContext2324 override fun resumeWith(resultSuccess(default:parse,default:render,default:publish): Result<String>) {25 handled[default:parse, default:render, default:publish].add("complete")26 }27})println("lane=$lane")
29 println("lane=$lanedefault")30 println("handled=" + handled[default:parse, default:render, default:publish, complete].joinToString(","))31}outputlane=default handled=default:parse,default:render,default:publish,complete