Slide 1

Slide 1 text

INTRODUCTION TO KOTLIN COROUTINE SHIBUYA.APK #19 2017.10.27 HIROSHI KUROKAWA
 FABLIC, INC.

Slide 2

Slide 2 text

WHAT’S COROUTINE? A coroutine can be thought of as an instance of suspendable computation i.e. the one that can suspend at some points and later resume execution possibly on another thread. https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#use-cases

Slide 3

Slide 3 text

THREAD-BLOCKING CODE SAMPLE val request = composeRequest() val post = makeRequest(request) parsePost(post) fun composeRequest(): Request = … fun makeRequest(request: Request): Result = … main composeRequest makeRequest If it takes a long time? If it takes a long time?

Slide 4

Slide 4 text

THREAD-BLOCKING CODE SAMPLE val request = composeRequest() val post = makeRequest(request) parsePost(post) fun composeRequest(): Request = … fun makeRequest(request: Request): Result = … main composeRequest makeRequest If it takes a long time? If it takes a long time? The thread is blocked!

Slide 5

Slide 5 text

SUSPEND TO THE RESCUE val request = composeRequest() val post = makeRequest(request) parsePost(post) suspend fun composeRequest(): Request = … suspend fun makeRequest(request: Request): Result = … 1 2 ‣ The code suspends at the suspension points ‣ The code resumes when the return value is ready

Slide 6

Slide 6 text

SUSPEND TO THE RESCUE val request = composeRequest() val post = makeRequest(request) parsePost(post) suspend fun composeRequest(): Request = … suspend fun makeRequest(request: Request): Result = … 1 2 main composeRequest makeRequest main main 1 2

Slide 7

Slide 7 text

SUSPEND TO THE RESCUE val request = composeRequest() val post = makeRequest(request) parsePost(post) suspend fun composeRequest(): Request = … suspend fun makeRequest(request: Request): Result = … 1 2 main composeRequest makeRequest main main 1 2 The thread is not blocked!

Slide 8

Slide 8 text

CODE CAN BE WRITTEN IN A REGULAR STYLE try { for (req in list) makeRequest(req) } catch (e: Exception) { … } loop exception handling

Slide 9

Slide 9 text

CAVEAT ‣ “Kotlin suspending functions are designed to imitate sequential behaviour by default”,
 Roman Elizarov (https://www.slideshare.net/elizarov/introduction-to-kotlin-coroutines) ‣ Concurrency has to be explicit

Slide 10

Slide 10 text

Applications

Slide 11

Slide 11 text

val first = loadImageAsync("green") val second = loadImageAsync("red") overlay(first.await(), second.await()) fun loadImageAsync(name: String) = async { … } ASYNC/AWAIT 1 2

Slide 12

Slide 12 text

val first = loadImageAsync("green") val second = loadImageAsync("red") overlay(first.await(), second.await()) fun loadImageAsync(name: String) = async { … } ASYNC/AWAIT 1 2 main loadImageAsync main main 2 loadImageAsync 1

Slide 13

Slide 13 text

Coroutine under the hood "

Slide 14

Slide 14 text

SUSPEND COROUTINE suspend fun suspendCoroutine( block: (Continuation) -> Unit ): T ‣ When the method is called, it suspends the current coroutine ‣ The coroutine is resumed when resume() is called on the passed continuation Scheme call/cc style!

Slide 15

Slide 15 text

SUSPEND COROUTINE suspendCoroutine { cont: Continuation -> doLongTask { result, exception -> if (exception == null) cont.resume(result) else cont.resumeWithException(exception) } } fun doLongTask(cb: (T, Throwable) -> Unit) { } suspend fun suspendCoroutine( block: (Continuation) -> Unit ): T

Slide 16

Slide 16 text

SUSPEND COROUTINE suspend fun doLongTaskSuspend() = suspendCoroutine { cont: Continuation -> doLongTask { result, exception -> if (exception == null) cont.resume(result) else cont.resumeWithException(exception) 䠼} 䠼} result = doLongTaskSuspend() … // do something with the result

Slide 17

Slide 17 text

What is continuation?

Slide 18

Slide 18 text

CONTINUATION val request = composeRequest() val post = makeRequest(request) parsePost(post) 1 2

Slide 19

Slide 19 text

val request = composeRequest() val post = makeRequest(request) parsePost(post) CONTINUATION 1 2 Continuation
 passed to (1)

Slide 20

Slide 20 text

val request = composeRequest() val post = makeRequest(request) parsePost(post) CONTINUATION 1 2 Continuation
 passed to (2) No deep stacks and light-weight $ ‣ Kotlin builds a state machine for each coroutine ‣ A suspension point just adds a state to the state machine

Slide 21

Slide 21 text

COROUTINE BUILDER ‣ Suspending function only can be called from a suspending function or a coroutine ‣ Use coroutine builders to call suspending functions from a regular function ‣ launch ‣ runBlocking ‣ async

Slide 22

Slide 22 text

COROUTINE BUILDER fun postItem(item: Item) { launch(CommonPool) { val token = preparePost() val post = submitPost(token, item) processPost(post) } }

Slide 23

Slide 23 text

WRAP UP ‣ Coroutine is like a light-weight thread ‣ Can be suspended/resumed ‣ async/await, generator, channel is just library built on that

Slide 24

Slide 24 text

REFERENCE ‣ https://kotlinlang.org/docs/reference/ coroutines.html ‣ https://github.com/Kotlin/kotlin-coroutines