Slide 1

Slide 1 text

Grokking Coroutines @danlew42

Slide 2

Slide 2 text

“Essentially, coroutines are light-weight threads.” ~Kotlin Documentation

Slide 3

Slide 3 text

myScope.launch { val image = downloadImage() displayImage(image) } suspend fun downloadImage() = withContext(Dispatchers.IO) { … } fun displayImage(image: Image)

Slide 4

Slide 4 text

sequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } }

Slide 5

Slide 5 text

What are coroutines?

Slide 6

Slide 6 text

Subroutines fun sumSquaredValues(values: List): Int { return values.sumBy { value -> square(value) } } fun square(value: Int): Int = value * value

Slide 7

Slide 7 text

Routine Subroutine

Slide 8

Slide 8 text

Coroutine Coroutine

Slide 9

Slide 9 text

val iterator = sequence.iterator() while (iterator.hasNext()) { val next = iterator.next() println(next) } sequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } Consumer Producer

Slide 10

Slide 10 text

val iterator = sequence.iterator() while (iterator.hasNext()) { val next = iterator.next() println(next) } sequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } Consumer Producer

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

class Fibonacci { var cur = 1 var next = 1 fun next(): Int { val toReturn = cur val tmp = cur + next cur = next next = tmp return toReturn } } sequence { var cur = 1 var next = 1 while (true) { yield(cur) val tmp = cur + next cur = next next = tmp } } Versus

Slide 13

Slide 13 text

Multiple Suspend Points sequence { yield(1) // first Fibonacci number var cur = 1 var next = 1 while (true) { yield(next) // next Fibonacci number val tmp = cur + next cur = next next = tmp } }

Slide 14

Slide 14 text

Why use coroutines?

Slide 15

Slide 15 text

Why use coroutines? • Another tool for writing good code • Two ways to use tool: • Code Structure • Concurrency

Slide 16

Slide 16 text

https://www.flickr.com/photos/117693452@N04/12547460924

Slide 17

Slide 17 text

https://www.maxpixel.net/Lana-Frame-Threads-Thread-Handmade-Weaving-3019254

Slide 18

Slide 18 text

Blocking Functions fun main() { print(calculateMeaningOfLife()) } fun calculateMeaningOfLife(): Int { // Calculates for 7.5 million years, then... return 42 }

Slide 19

Slide 19 text

Non-Blocking Function suspend fun calculateMeaningOfLife(): Int { delay(7.5 million years) return 42 }

Slide 20

Slide 20 text

Blocking vs. Nonblocking Blocking Blocked During I/O Non-Blocking Waiting During I/O Doing other work

Slide 21

Slide 21 text

Two Tasks, One Thread suspend fun task(name: String, delay: Long) { joinAll( async { doSomething("First", 10) }, async { doSomething("Second", 5) } ) } suspend fun doSomething(name: String, delay: Long) { println("$name START (${Thread.currentThread().name})") delay(delay) println("$name END (${Thread.currentThread().name})") } First START (main) Second START (main) Second END (main) First END (main)

Slide 22

Slide 22 text

Threads == preemptive multitasking Coroutines == cooperative multitasking

Slide 23

Slide 23 text

Callback Hell requestRandomUrl { url -> downloadImage(url) { image -> displayImage(image) } } myScope.launch { val url = requestRandomUrl() val image = downloadImage(url) displayImage(image) } Vs

Slide 24

Slide 24 text

Why use coroutines? • Concurrency • Coroutines *are* like light-weight threads! • …In any language! • Code Structure • Coroutines enable simpler code

Slide 25

Slide 25 text

Kotlin Coroutines

Slide 26

Slide 26 text

kotlin.coroutines (stdlib) kotlinx.coroutines (library)

Slide 27

Slide 27 text

kotlin.coroutines (stdlib) kotlinx.coroutines (library)

Slide 28

Slide 28 text

Stdlib Basics • Suspending functions • A way to start suspending functions • Contexts

Slide 29

Slide 29 text

Suspend Keyword

Slide 30

Slide 30 text

Start Suspending Functions suspend fun mySuspendingFunction() fun (suspend () -> T).startCoroutine(completion: Continuation) fun main() { ::mySuspendingFunction.startCoroutine( Continuation(EmptyCoroutineContext) { } ) }

Slide 31

Slide 31 text

Coroutine Context • Store useful info about coroutine • Dispatcher • Job • Debug info

Slide 32

Slide 32 text

Coroutine Library

Slide 33

Slide 33 text

myScope.launch { val image = downloadImage() displayImage(image) } suspend fun downloadImage() = withContext(Dispatchers.IO) { … } fun displayImage(image: Image)

Slide 34

Slide 34 text

myScope.launch { val image = downloadImage() displayImage(image) } suspend fun downloadImage() = withContext(Dispatchers.IO) { … } fun displayImage(image: Image)

Slide 35

Slide 35 text

myScope.launch { val image = downloadImage() displayImage(image) } suspend fun downloadImage() = withContext(Dispatchers.IO) { … } fun displayImage(image: Image)

Slide 36

Slide 36 text

myScope.launch { val image = downloadImage() displayImage(image) } suspend fun downloadImage() = withContext(Dispatchers.IO) { … } fun displayImage(image: Image)

Slide 37

Slide 37 text

Review • Coroutines are suspending functions • Suspending functions are useful for concurrency • Kotlin stdlib provides coroutine support • Kotlin coroutine library adds practical functions for coroutines

Slide 38

Slide 38 text

More Info • Longer Talk: https://youtu.be/Axq8LdQqQGQ • Links: github.com/Kotlin/kotlinx.coroutines/#documentation • Roman Elizarov: medium.com/@elizarov • Android + Coroutines: medium.com/@objcode • Structured concurrency: vorpus.org/blog/notes-on-structured- concurrency-or-go-statement-considered-harmful/

Slide 39

Slide 39 text

@danlew42