Slide 1

Slide 1 text

Coroutines in Kotlin Dmytro Zaitsev Team Leader @ Lóhika

Slide 2

Slide 2 text

Blocking VS Non-blocking

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

v1: Sequential fun postItem(item: Item) {
 val token = prepareToken() / / 1
 val post = submitPost(token, item) / / 2
 processPost(post) / / 3
 }

Slide 5

Slide 5 text

v2: Async callbacks fun postItem(item: Item) {
 prepareTokenAsync { token -> / / 1
 submitPostAsync(token, item) { post -> / / 2
 processPost(post) / / 3
 }
 }
 }

Slide 6

Slide 6 text

Callback hell

Slide 7

Slide 7 text

v3: Reactive fun postItem(item: Item) {
 observeToken()
 .concatMap { token -> observePost(token, item) }
 .subscribe { post -> processPost(post) }
 }

Slide 8

Slide 8 text

v4: Coroutines fun postItem(item: Item) {
 launch(CommonPool) {
 val token = prepareToken() / / 1
 val post = submitPost(token, item) / / 2
 processPost(post) / / 3
 }
 }

Slide 9

Slide 9 text

Experimental status Kotlin 1.1 -Xcoroutines=enable kotlin.coroutines.experimental -> kotlin.coroutines

Slide 10

Slide 10 text

Terminology coroutine suspending function suspending lambda suspending function type coroutine builder suspension point continuation

Slide 11

Slide 11 text

A coroutine is… an instance of suspendable computation similar to a daemon thread, but very light-weight similar to a future or promise

Slide 12

Slide 12 text

Why coroutines? threads are expensive to keep and switch your code is single threaded you’ve got lots of mutable states

Slide 13

Slide 13 text

suspend fun computation that can be suspended

Slide 14

Slide 14 text

Standard API • Language support (`suspend` keyword) • low-level basic API (stdlib: kotlin.coroutines) • high-level APIs that can be used in user code

Slide 15

Slide 15 text

Low-level API (kotlin.coroutines) • kotlin.coroutines.experimental • create/start/suspendCoroutine() • Continuation interface • @RestrictSuspension annotation • kotlin.coroutines.experimental.intrinsics • suspendCoroutineOrReturn()

Slide 16

Slide 16 text

Continuation interface Continuation {
 val context: CoroutineContext
 fun resume(value: T)
 fun resumeWithException(exception: Throwable)
 }

Slide 17

Slide 17 text

Patterns • generators/yield: C#, Python, Scala • async/await: C#, ECMAScript, Dart • channels, select: Go • actors: Scala

Slide 18

Slide 18 text

Generators API in kotlin.coroutines kotlin.coroutines.experimental: • buildSequence() • buildIterator()

Slide 19

Slide 19 text

buildSequence {
 print("Start")
 yield(1) / / suspension point
 
 var prev = 0
 var cur = 1
 while (true) {
 print(“Next") val next = prev + cur
 yield(next) / / suspension point
 
 prev = cur
 cur = next
 }
 print("End") / / unreachable code
 }.take(8).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8 Next 13 Next 21

Slide 20

Slide 20 text

kotlinx.coroutines • kotlinx-coroutines-core • integration • guava, jdk8, nio, quasar • reactive • reactive, reactor, rx1, rx2 • ui • android, javafx, swing

Slide 21

Slide 21 text

runBlocking for main functions and tests

Slide 22

Slide 22 text

delay like Thread.sleep(), but non-blocking

Slide 23

Slide 23 text

launch fire and forget (Job)

Slide 24

Slide 24 text

async promise returned (Deferred + await)

Slide 25

Slide 25 text

Channel transfers values between coroutines

Slide 26

Slide 26 text

produce produces a stream of values by sending them to a channel (ProducerJob)

Slide 27

Slide 27 text

actor deals with it’s mailbox (ActorJob)

Slide 28

Slide 28 text

select waits for the result of multiple suspending functions

Slide 29

Slide 29 text

Job lifecycle New Active Cancelling Completed Cancelled

Slide 30

Slide 30 text

Job states State isActive isCompleted isCancelled New - - - Active + - - Completed - + - Cancelling - - + Cancelled - + +

Slide 31

Slide 31 text

val deferred = async(CommonPool) {
 throw SomeException("I'm thrown inside a coroutine")
 }
 try {
 deferred.await() / / re-throws
 } catch (e: SomeException) {
 log(e.message)
 } Exception handling

Slide 32

Slide 32 text

WeakReference “life hack” suspend operator fun WeakReference.invoke(): T = suspendCoroutineOrReturn { get() ?: throw CancellationException() } val activityRef = WeakReference(this)
 launch(CommonPool) {
 activityRef().expensiveComputation()
 }

Slide 33

Slide 33 text

Demo

Slide 34

Slide 34 text

A lot more left… Coroutine dispatchers Mutable state and concurrency UI programming Reactive streams

Slide 35

Slide 35 text

Links Andrey Breslav FAQ:
 https:/ /discuss.kotlinlang.org/t/experimental-status-of-coroutines-in-1-1-and- related-compatibility-concerns/2236 Design document (KEEP):
 https:/ /github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines- informal.md Full kotlinx.coroutines API:
 http:/ /kotlin.github.io/kotlinx.coroutines Coroutines guide by Roman ELizarov:
 https:/ /github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md

Slide 36

Slide 36 text

Thank you! @DmitriyZaitsev