Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Grokking Coroutines (MinneBar)

Daniel Lew
October 13, 2020

Grokking Coroutines (MinneBar)

What are coroutines, really?

Given at MinneBar 2020.

Daniel Lew

October 13, 2020
Tweet

More Decks by Daniel Lew

Other Decks in Programming

Transcript

  1. Grokking Coroutines
    @danlew42

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  5. What are coroutines?

    View Slide

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

    View Slide

  7. Routine Subroutine

    View Slide

  8. Coroutine Coroutine

    View Slide

  9. 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

    View Slide

  10. 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

    View Slide

  11. View Slide

  12. 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

    View Slide

  13. 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
    }
    }

    View Slide

  14. Why use coroutines?

    View Slide

  15. Why use coroutines?
    • Another tool for writing good code

    • Two ways to use tool:

    • Code Structure

    • Concurrency

    View Slide

  16. https://www.flickr.com/photos/[email protected]/12547460924

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. 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)

    View Slide

  22. Threads == preemptive multitasking
    Coroutines == cooperative multitasking

    View Slide

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

    View Slide

  24. Why use coroutines?
    • Concurrency

    • Coroutines *are* like light-weight threads!

    • …In any language!

    • Code Structure

    • Coroutines enable simpler code

    View Slide

  25. Kotlin Coroutines

    View Slide

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

    View Slide

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

    View Slide

  28. Stdlib Basics
    • Suspending functions

    • A way to start suspending functions

    • Contexts

    View Slide

  29. Suspend Keyword

    View Slide

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

    View Slide

  31. Coroutine Context
    • Store useful info about coroutine

    • Dispatcher

    • Job

    • Debug info

    View Slide

  32. Coroutine Library

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  37. Review
    • Coroutines are suspending functions

    • Suspending functions are useful for concurrency

    • Kotlin stdlib provides coroutine support

    • Kotlin coroutine library adds practical functions for coroutines

    View Slide

  38. 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/

    View Slide

  39. @danlew42

    View Slide