Coroutines Concepts
Cancellation Flag Model
Real coroutine cancellation is cooperative; this static example models the same idea with a checked flag.
cooperative cancellation
Cooperative code checks whether it should continue before doing the next unit of work.
Cancellation Flag Model
CancellationFlagModel.kt
Replay: real traced execution (multi-file project)
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine
suspend fun runStep(active: Boolean, name: String): String {
return if (active) "ran:$name" else "skipped:$name"
}
fun main() {
val active = true
val log = mutableListOf<String>()
val work: suspend () -> String = {
log.add(runStep(active, "load"))
log.add(runStep(active, "save"))
log.joinToString("|")
}
work.startCoroutine(object : Continuation<String> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<String>) {
log.add("done")
}
})
println("active=$active")
println("log=" + log.joinToString("|"))
}
import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine
suspend fun runStep(active: Boolean, name: String): String {
return if (active) "ran:$name" else "skipped:$name"
}
fun main() {
val active = false
val log = mutableListOf<String>()
val work: suspend () -> String = {
log.add(runStep(active, "load"))
log.add(runStep(active, "save"))
log.joinToString("|")
}
work.startCoroutine(object : Continuation<String> {
override val context = EmptyCoroutineContext
override fun resumeWith(result: Result<String>) {
log.add("done")
}
})
println("active=$active")
println("log=" + log.joinToString("|"))
}
active ← true, log ← [], work ← () -> kotlin.String
9fun main() {10 val active→ true = true //@active=false11 val log→ [] = mutableListOf<String>()1213 val work→ () -> kotlin.String: suspend () -> String = {14 log.add(runStep(active, "load"))15 log.add(runStep(active, "save"))16 log.joinToString("|")17 }1819 work() -> kotlin.String.startCoroutine(object : Continuation<String> {20 override val context = EmptyCoroutineContext2122 override fun resumeWith(result: Result<String>) {23 log.add("done")24 }25 })suspend fun runStep(active: Boolean, name: String): String
pass 1 of 25suspend fun runStep(activetrue: Boolean, nameload: String): String {6 return if (activetrue) "ran:$nameload" else "skipped:$name"7}log.add(runStep(active, "load"))
13val work: suspend () -> String = {14 log.add(runStep(active, "load"))15 log.add(runStep(active, "save"))16 log.joinToString("|")suspend fun runStep(active: Boolean, name: String): String
pass 2 of 25suspend fun runStep(activetrue: Boolean, namesave: String): String {6 return if (activetrue) "ran:$namesave" else "skipped:$name"7}log.add(runStep(active, "save"))
14log.add(runStep(active, "load"))15log.add(runStep(active, "save"))16log.joinToString("|")override fun resumeWith(result: Result<String>)
19work() -> kotlin.String.startCoroutine(object : Continuation<String> {20 override val context = EmptyCoroutineContext2122 override fun resumeWith(resultSuccess(ran:load|ran:save): Result<String>) {23 log[ran:load, ran:save].add("done")24 }25})println("active=$active")
27 println("active=$activetrue")28 println("log=" + log[ran:load, ran:save, done].joinToString("|"))29}outputactive=true log=ran:load|ran:save|done
active ← false, log ← [], work ← () -> kotlin.String
9fun main() {10 val active→ false = false11 val log→ [] = mutableListOf<String>()1213 val work→ () -> kotlin.String: suspend () -> String = {14 log.add(runStep(active, "load"))15 log.add(runStep(active, "save"))16 log.joinToString("|")17 }1819 work() -> kotlin.String.startCoroutine(object : Continuation<String> {20 override val context = EmptyCoroutineContext2122 override fun resumeWith(result: Result<String>) {23 log.add("done")24 }25 })suspend fun runStep(active: Boolean, name: String): String
pass 1 of 25suspend fun runStep(activefalse: Boolean, nameload: String): String {6 return if (activefalse) "ran:$nameload" else "skipped:$name"7}log.add(runStep(active, "load"))
13val work: suspend () -> String = {14 log.add(runStep(active, "load"))15 log.add(runStep(active, "save"))16 log.joinToString("|")suspend fun runStep(active: Boolean, name: String): String
pass 2 of 25suspend fun runStep(activefalse: Boolean, namesave: String): String {6 return if (activefalse) "ran:$namesave" else "skipped:$name"7}log.add(runStep(active, "save"))
14log.add(runStep(active, "load"))15log.add(runStep(active, "save"))16log.joinToString("|")override fun resumeWith(result: Result<String>)
19work() -> kotlin.String.startCoroutine(object : Continuation<String> {20 override val context = EmptyCoroutineContext2122 override fun resumeWith(resultSuccess(skipped:load|skipped:save): Result<String>) {23 log[skipped:load, skipped:save].add("done")24 }25})println("active=$active")
27 println("active=$activefalse")28 println("log=" + log[skipped:load, skipped:save, done].joinToString("|"))29}outputactive=false log=skipped:load|skipped:save|done