SlideShare a Scribd company logo
1 of 36
Download to read offline
Dip into Coroutines
A story full of suspends
Software Engineer @ Gradle
Formerly @ dxFeed
Twitter @alllexist — GitHub @alllex
Alex Semin
Awesome Kotlin coroutines
fun main() = runBlocking {
val jobs: List<Deferred<Boolean?> = List(100_000) {
async { request(it) }
}
val evenCount = jobs.count { it.await() }
println("There $evenCount even numbers")
}
suspend fun request(id: Int): Boolean {
delay(1.seconds)
return id % 2 ?= 0
}
fun main() = runBlocking {
val jobs: List<Deferred<Boolean?> = List(100_000) {
async { request(it) }
}
val evenCount = jobs.count { it.await() }
println("There $evenCount even numbers")
}
suspend fun request(id: Int): Boolean {
delay(1.seconds)
return id % 2 ?= 0
}
fun main() = runBlocking {
val jobs: List<Deferred<Boolean?> = List(100_000) {
async { request(it) }
}
val evenCount = jobs.count { it.await() }
println("There $evenCount even numbers")
}
suspend fun request(id: Int): Boolean {
delay(1.seconds)
return id % 2 ?= 0
}
import kotlinx.coroutines.*
What’s where?
kotlinx.coroutines kotlin.coroutines
launch
async await
…
Job
runBlocking coroutineScope
Deferred
withTimeout
Continuation
CoroutineContext
createCoroutine* suspendCoroutine*
COROUTINE_SUSPENDED
ContinuationInterceptor
delay
…
…
Awesome Sequence Builders
Sequences
list.asSequence()
.filter { … }
.map { … }
.filter { … }
// 1, 2, 4, 8, //.
val seq = generateSequence(1) { it * 2 }
for (item in seq) {
println(item)
}
interface Sequence<out T> {
operator fun iterator(): Iterator<T>
}
interface Iterator<out T> {
operator fun next(): T
operator fun hasNext(): Boolean
}
val iter = seq.iterator()
while (iter.hasNext()) {
val item = iter.next()
println(item)
}
Sequence builders
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
fib.take(4).forEach { print("$it ") }
// Start 1 Next 1 Next 2 Next 3
fun <T> sequence(
block: suspend SequenceScope<T>.() ?> Unit
): Sequence<T>
abstract class SequenceScope<in T> {
abstract suspend fun yield(value: T)
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {
…
}
override fun hasNext(): Boolean {
…
}
override suspend fun yield(value: T) {
…
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {
State.NotReady ?> if (hasNext()) next() else error("oops")
State.Ready ?> {
state = State.NotReady
nextValue as T
}
else ?> error("oops")
}
override fun hasNext(): Boolean {
…
}
override suspend fun yield(value: T) {
…
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {}
override fun hasNext(): Boolean {
while (true) {
when (state) {
State.NotReady ?> {
state = State.Done
nextStep?!.resume(Unit)
}
State.Done ?> return false
State.Ready ?> return true
}
}
}
override suspend fun yield(value: T) {
…
}
}
interface Continuation<in T> {
val context: CoroutineContext
fun resumeWith(result: Result<T>)
}
fun <T> Continuation<T>.resume(value: T) =
resumeWith(Result.success(value))
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun next(): T = when (state) {}
override fun hasNext(): Boolean {
while (true) {
when (state) {
State.NotReady ?> {
state = State.Done
nextStep?!.resume(Unit)
}
State.Done ?> return false
State.Ready ?> return true
}
}
}
override suspend fun yield(value: T) {
…
}
}
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun hasNext(): Boolean {
…
}
override fun next(): T = when (state) {
…
}
override suspend fun yield(value: T) {
nextValue = value
state = State.Ready
}
}
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> {
var state: State = State.NotReady // enum NotReady, Ready, Done
var nextValue: T? = null
var nextStep: Continuation<Unit>? = null
override fun hasNext(): Boolean {
…
}
override fun next(): T = when (state) {
…
}
override suspend fun yield(value: T) {
nextValue = value
state = State.Ready
return suspendCoroutineUninterceptedOrReturn { c ->
nextStep = c
COROUTINE_SUSPENDED
}
}
}
val fib = sequence {
print("Start ")
yield(1)
// Label 1
var cur = 1
var next = 1
while (true) {
print("Next ")
yield(next)
// Label 2
val tmp = cur + next
cur = next
next = tmp
}
}
Continuation Passing Style
T | COROUTINE_SUSPENDED
suspend fun yield(value: T): Unit
source code
fun yield(value: T, cont: Continuation<Unit>): Any?
compiled code
Continuation Passing Style
override suspend fun yield(value: T) {
nextValue = value
state = State.Ready
return suspendCoroutineUninterceptedOrReturn { cont ->
nextStep = cont
COROUTINE_SUSPENDED
}
}
override suspend fun yield(value: T, cont: Continuation<Unit>): Any? {
nextValue = value
state = State.Ready
nextStep = cont
return COROUTINE_SUSPENDED
}
Awesome Deep Recursion
Deeply recursive functions
fun depth(t: Tree?): Int =
if (t ?= null) 0 else maxOf(depth(t.left), depth(t.right)) + 1
println(depth(deepTree)) // StackOverflowError
class Tree(val left: Tree? = null, val right: Tree? = null)
val deepTree = generateSequence(Tree()) { Tree(left = it) }.take(100_000).last()
val depth = DeepRecursiveFunction<Tree?, Int> { t ->
if (t ?= null) 0 else maxOf(
callRecursive(t.left),
callRecursive(t.right)
) + 1
}
println(depth(deepTree)) // Ok
Deeply recursive functions
sealed class DeepRecursiveScope<T, R> {
abstract suspend fun callRecursive(value: T): R
}
override suspend fun callRecursive(value: T): R {
return suspendCoroutineUninterceptedOrReturn { c ->
this.cont = c as Continuation<Any?>
this.value = value
COROUTINE_SUSPENDED
}
}
fun runCallLoop(): R {
while (true) {
val result = this.result
val cont = this.cont
?: return result.getOrThrow()
if (UNDEFINED_RESULT ?= result) {
val r = try {
function(this, value, cont)
} catch (e: Throwable) {
cont.resumeWithException(e)
continue
}
if (r ??= COROUTINE_SUSPENDED)
cont.resume(r as R)
} else {
this.result = UNDEFINED_RESULT
cont.resumeWith(result)
}
}
}
Deeply recursive functions
sealed class DeepRecursiveScope<T, R> {
abstract suspend fun callRecursive(value: T): R
}
override suspend fun callRecursive(value: T): R {
return suspendCoroutineUninterceptedOrReturn { c ->
this.cont = c as Continuation<Any?>
this.value = value
COROUTINE_SUSPENDED
}
}
fun runCallLoop(): R {
while (true) {
val result = this.result
val cont = this.cont
?: return result.getOrThrow()
if (UNDEFINED_RESULT ?= result) {
val r = try {
function(this, value, cont)
} catch (e: Throwable) {
cont.resumeWithException(e)
continue
}
if (r ??= COROUTINE_SUSPENDED)
cont.resume(r as R)
} else {
this.result = UNDEFINED_RESULT
cont.resumeWith(result)
}
}
}
Awesome Parser Combinators
Parsing expressions
sealed class Expr {
object TRUE : Expr()
object FALSE : Expr()
data class Var(val name: String) : Expr()
data class Not(val body: Expr) : Expr()
data class And(val left: Expr, val right: Expr) : Expr()
data class Or(val left: Expr, val right: Expr) : Expr()
data class Impl(val left: Expr, val right: Expr) : Expr()
}
val expr = "a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
object BooleanGrammar : Grammar<Expr>() {
init { register(regexToken("s+", ignored = true)) }
val tru by literalToken("true")
val fal by literalToken("false")
val id by regexToken("w+")
val lpar by literalToken("(")
val rpar by literalToken(")")
val not by literalToken("!")
val and by literalToken("&")
val or by literalToken("|")
val impl by literalToken("?>")
val negation by parser { -not * term() } map { Not(it) }
val braced by parser { -lpar * expr() * -rpar }
val term: Parser<Expr> by
(tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced
val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } }
val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } }
val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } }
val expr by implChain
override val root by expr
}
"a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
object BooleanGrammar : Grammar<Expr>() {
init { register(regexToken("s+", ignored = true)) }
val tru by literalToken("true")
val fal by literalToken("false")
val id by regexToken("w+")
val lpar by literalToken("(")
val rpar by literalToken(")")
val not by literalToken("!")
val and by literalToken("&")
val or by literalToken("|")
val impl by literalToken("?>")
val negation by parser { -not * term() } map { Not(it) }
val braced by parser { -lpar * expr() * -rpar }
val term: Parser<Expr> by
(tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced
val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } }
val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } }
val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } }
val expr by implChain
override val root by expr
}
suspend fun <T : Any, S : Any> ParsingScope.leftAssociative(
term: Parser<T>,
operator: Parser<S>,
transform: (T, S, T) ?> T
): T {
var l: T = term()
while (true) {
val (o, r) = maybe(parser { operator() to term() }) ?: break
l = transform(l, o, r)
}
return l
}
val input = "K | o | t | l | i | n | i | s | a | w | e | s | o | m | e"
parser { leftAssociative(id, "|") { l, _, r -> "$l$r" } }
https://github.com/alllex/parsus
Awesome Arrow Kt
https://arrow-kt.io/
Awesome! How to learn more?
More watching
More reading
https://kotlinlang.org/docs/coroutines-guide.html https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md
More tinkering
Than you!
Twitter @alllexist — GitHub @alllex

More Related Content

Similar to Dip into Coroutines - KTUG Munich 202303

Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For GoogleEleanor McHugh
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kirill Rozov
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }John De Goes
 
I wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdfI wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdfrishteygallery
 
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxjava compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxpriestmanmable
 
Kotlinify Your Project!
Kotlinify Your Project!Kotlinify Your Project!
Kotlinify Your Project!OrNoyman
 
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdfb. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdfakanshanawal
 
3 kotlin vs. java- what kotlin has that java does not
3  kotlin vs. java- what kotlin has that java does not3  kotlin vs. java- what kotlin has that java does not
3 kotlin vs. java- what kotlin has that java does notSergey Bandysik
 
Shapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptShapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptkinan keshkeh
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
Implement the following sorting algorithms Bubble Sort Insertion S.pdf
Implement the following sorting algorithms  Bubble Sort  Insertion S.pdfImplement the following sorting algorithms  Bubble Sort  Insertion S.pdf
Implement the following sorting algorithms Bubble Sort Insertion S.pdfkesav24
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesAnh Vu
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 

Similar to Dip into Coroutines - KTUG Munich 202303 (20)

VTU Data Structures Lab Manual
VTU Data Structures Lab ManualVTU Data Structures Lab Manual
VTU Data Structures Lab Manual
 
week-18x
week-18xweek-18x
week-18x
 
week-17x
week-17xweek-17x
week-17x
 
Simpler java
Simpler javaSimpler java
Simpler java
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For Google
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }
 
I wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdfI wrote the following change it to having a header, main and cpp fi.pdf
I wrote the following change it to having a header, main and cpp fi.pdf
 
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docxjava compilerCompiler1.javajava compilerCompiler1.javaimport.docx
java compilerCompiler1.javajava compilerCompiler1.javaimport.docx
 
Kotlinify Your Project!
Kotlinify Your Project!Kotlinify Your Project!
Kotlinify Your Project!
 
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdfb. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
b. (10 pts) Implement the rotate left method for AVL trees.c. (10 .pdf
 
3 kotlin vs. java- what kotlin has that java does not
3  kotlin vs. java- what kotlin has that java does not3  kotlin vs. java- what kotlin has that java does not
3 kotlin vs. java- what kotlin has that java does not
 
Shapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptShapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop concept
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Implement the following sorting algorithms Bubble Sort Insertion S.pdf
Implement the following sorting algorithms  Bubble Sort  Insertion S.pdfImplement the following sorting algorithms  Bubble Sort  Insertion S.pdf
Implement the following sorting algorithms Bubble Sort Insertion S.pdf
 
Kotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenesKotlin coroutine - behind the scenes
Kotlin coroutine - behind the scenes
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 

Recently uploaded

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 

Recently uploaded (20)

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 

Dip into Coroutines - KTUG Munich 202303

  • 1. Dip into Coroutines A story full of suspends
  • 2. Software Engineer @ Gradle Formerly @ dxFeed Twitter @alllexist — GitHub @alllex Alex Semin
  • 4. fun main() = runBlocking { val jobs: List<Deferred<Boolean?> = List(100_000) { async { request(it) } } val evenCount = jobs.count { it.await() } println("There $evenCount even numbers") } suspend fun request(id: Int): Boolean { delay(1.seconds) return id % 2 ?= 0 }
  • 5. fun main() = runBlocking { val jobs: List<Deferred<Boolean?> = List(100_000) { async { request(it) } } val evenCount = jobs.count { it.await() } println("There $evenCount even numbers") } suspend fun request(id: Int): Boolean { delay(1.seconds) return id % 2 ?= 0 }
  • 6. fun main() = runBlocking { val jobs: List<Deferred<Boolean?> = List(100_000) { async { request(it) } } val evenCount = jobs.count { it.await() } println("There $evenCount even numbers") } suspend fun request(id: Int): Boolean { delay(1.seconds) return id % 2 ?= 0 } import kotlinx.coroutines.*
  • 7. What’s where? kotlinx.coroutines kotlin.coroutines launch async await … Job runBlocking coroutineScope Deferred withTimeout Continuation CoroutineContext createCoroutine* suspendCoroutine* COROUTINE_SUSPENDED ContinuationInterceptor delay … …
  • 9. Sequences list.asSequence() .filter { … } .map { … } .filter { … } // 1, 2, 4, 8, //. val seq = generateSequence(1) { it * 2 } for (item in seq) { println(item) } interface Sequence<out T> { operator fun iterator(): Iterator<T> } interface Iterator<out T> { operator fun next(): T operator fun hasNext(): Boolean } val iter = seq.iterator() while (iter.hasNext()) { val item = iter.next() println(item) }
  • 10. Sequence builders val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } } fib.take(4).forEach { print("$it ") } // Start 1 Next 1 Next 2 Next 3 fun <T> sequence( block: suspend SequenceScope<T>.() ?> Unit ): Sequence<T> abstract class SequenceScope<in T> { abstract suspend fun yield(value: T) }
  • 11. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) { … } override fun hasNext(): Boolean { … } override suspend fun yield(value: T) { … } }
  • 12. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) { State.NotReady ?> if (hasNext()) next() else error("oops") State.Ready ?> { state = State.NotReady nextValue as T } else ?> error("oops") } override fun hasNext(): Boolean { … } override suspend fun yield(value: T) { … } }
  • 13. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) {} override fun hasNext(): Boolean { while (true) { when (state) { State.NotReady ?> { state = State.Done nextStep?!.resume(Unit) } State.Done ?> return false State.Ready ?> return true } } } override suspend fun yield(value: T) { … } } interface Continuation<in T> { val context: CoroutineContext fun resumeWith(result: Result<T>) } fun <T> Continuation<T>.resume(value: T) = resumeWith(Result.success(value))
  • 14. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun next(): T = when (state) {} override fun hasNext(): Boolean { while (true) { when (state) { State.NotReady ?> { state = State.Done nextStep?!.resume(Unit) } State.Done ?> return false State.Ready ?> return true } } } override suspend fun yield(value: T) { … } } val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } }
  • 15. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun hasNext(): Boolean { … } override fun next(): T = when (state) { … } override suspend fun yield(value: T) { nextValue = value state = State.Ready } } val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } }
  • 16. class SequenceBuilder<T> : SequenceScope<T>(), Iterator<T> { var state: State = State.NotReady // enum NotReady, Ready, Done var nextValue: T? = null var nextStep: Continuation<Unit>? = null override fun hasNext(): Boolean { … } override fun next(): T = when (state) { … } override suspend fun yield(value: T) { nextValue = value state = State.Ready return suspendCoroutineUninterceptedOrReturn { c -> nextStep = c COROUTINE_SUSPENDED } } } val fib = sequence { print("Start ") yield(1) // Label 1 var cur = 1 var next = 1 while (true) { print("Next ") yield(next) // Label 2 val tmp = cur + next cur = next next = tmp } }
  • 17. Continuation Passing Style T | COROUTINE_SUSPENDED suspend fun yield(value: T): Unit source code fun yield(value: T, cont: Continuation<Unit>): Any? compiled code
  • 18. Continuation Passing Style override suspend fun yield(value: T) { nextValue = value state = State.Ready return suspendCoroutineUninterceptedOrReturn { cont -> nextStep = cont COROUTINE_SUSPENDED } } override suspend fun yield(value: T, cont: Continuation<Unit>): Any? { nextValue = value state = State.Ready nextStep = cont return COROUTINE_SUSPENDED }
  • 19.
  • 21. Deeply recursive functions fun depth(t: Tree?): Int = if (t ?= null) 0 else maxOf(depth(t.left), depth(t.right)) + 1 println(depth(deepTree)) // StackOverflowError class Tree(val left: Tree? = null, val right: Tree? = null) val deepTree = generateSequence(Tree()) { Tree(left = it) }.take(100_000).last() val depth = DeepRecursiveFunction<Tree?, Int> { t -> if (t ?= null) 0 else maxOf( callRecursive(t.left), callRecursive(t.right) ) + 1 } println(depth(deepTree)) // Ok
  • 22. Deeply recursive functions sealed class DeepRecursiveScope<T, R> { abstract suspend fun callRecursive(value: T): R } override suspend fun callRecursive(value: T): R { return suspendCoroutineUninterceptedOrReturn { c -> this.cont = c as Continuation<Any?> this.value = value COROUTINE_SUSPENDED } } fun runCallLoop(): R { while (true) { val result = this.result val cont = this.cont ?: return result.getOrThrow() if (UNDEFINED_RESULT ?= result) { val r = try { function(this, value, cont) } catch (e: Throwable) { cont.resumeWithException(e) continue } if (r ??= COROUTINE_SUSPENDED) cont.resume(r as R) } else { this.result = UNDEFINED_RESULT cont.resumeWith(result) } } }
  • 23. Deeply recursive functions sealed class DeepRecursiveScope<T, R> { abstract suspend fun callRecursive(value: T): R } override suspend fun callRecursive(value: T): R { return suspendCoroutineUninterceptedOrReturn { c -> this.cont = c as Continuation<Any?> this.value = value COROUTINE_SUSPENDED } } fun runCallLoop(): R { while (true) { val result = this.result val cont = this.cont ?: return result.getOrThrow() if (UNDEFINED_RESULT ?= result) { val r = try { function(this, value, cont) } catch (e: Throwable) { cont.resumeWithException(e) continue } if (r ??= COROUTINE_SUSPENDED) cont.resume(r as R) } else { this.result = UNDEFINED_RESULT cont.resumeWith(result) } } }
  • 24.
  • 26. Parsing expressions sealed class Expr { object TRUE : Expr() object FALSE : Expr() data class Var(val name: String) : Expr() data class Not(val body: Expr) : Expr() data class And(val left: Expr, val right: Expr) : Expr() data class Or(val left: Expr, val right: Expr) : Expr() data class Impl(val left: Expr, val right: Expr) : Expr() } val expr = "a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
  • 27. object BooleanGrammar : Grammar<Expr>() { init { register(regexToken("s+", ignored = true)) } val tru by literalToken("true") val fal by literalToken("false") val id by regexToken("w+") val lpar by literalToken("(") val rpar by literalToken(")") val not by literalToken("!") val and by literalToken("&") val or by literalToken("|") val impl by literalToken("?>") val negation by parser { -not * term() } map { Not(it) } val braced by parser { -lpar * expr() * -rpar } val term: Parser<Expr> by (tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } } val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } } val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } } val expr by implChain override val root by expr } "a & (b1 ?> c1) | a1 & !b | !(a1 ?> a2) ?> a"
  • 28. object BooleanGrammar : Grammar<Expr>() { init { register(regexToken("s+", ignored = true)) } val tru by literalToken("true") val fal by literalToken("false") val id by regexToken("w+") val lpar by literalToken("(") val rpar by literalToken(")") val not by literalToken("!") val and by literalToken("&") val or by literalToken("|") val impl by literalToken("?>") val negation by parser { -not * term() } map { Not(it) } val braced by parser { -lpar * expr() * -rpar } val term: Parser<Expr> by (tru map TRUE) or (fal map FALSE) or (id map { Var(it.text) }) or negation or braced val andChain by parser { leftAssociative(term, and) { a, _, b -> And(a, b) } } val orChain by parser { leftAssociative(andChain, or) { a, _, b -> Or(a, b) } } val implChain by parser { rightAssociative(orChain, impl) { a, _, b -> Impl(a, b) } } val expr by implChain override val root by expr }
  • 29. suspend fun <T : Any, S : Any> ParsingScope.leftAssociative( term: Parser<T>, operator: Parser<S>, transform: (T, S, T) ?> T ): T { var l: T = term() while (true) { val (o, r) = maybe(parser { operator() to term() }) ?: break l = transform(l, o, r) } return l } val input = "K | o | t | l | i | n | i | s | a | w | e | s | o | m | e" parser { leftAssociative(id, "|") { l, _, r -> "$l$r" } }
  • 32. Awesome! How to learn more?
  • 36. Than you! Twitter @alllexist — GitHub @alllex