SlideShare a Scribd company logo
Coroutines in Kotlin:
In-depth review
Dmytro Zaitsev
Team Leader @ Lóhika
Blocking VS Non-blocking
Coroutines in Kotlin. UA Mobile 2017.
v1: Sequential
(Direct style)
fun postItem(item: Item) {

val token = prepareToken() // 1

val post = submitPost(token, item) // 2

processPost(post) // 3

}
v2: Callbacks
(Continuation-Passing style)
fun postItem(item: Item) {

prepareTokenAsync { token -> // 1

submitPostAsync(token, item) { post -> // 2

processPost(post) // 3

}

}

}
Continuation
v2: Callbacks
(Continuation-Passing style)
fun postItem(item: Item) {

prepareTokenAsync { token -> // 1

submitPostAsync(token, item) { post -> // 2

processPost(post) // 3

}

}

}
Callback hell
v3: Rx/Futures/Promises
fun postItem(item: Item) {

observeToken()

.concatMap { token -> observePost(token, item) }

.subscribe { post -> processPost(post) }

}
v4: Coroutines Direct Style
suspend fun postItem(item: Item) {

val token = prepareToken() // 1

val post = submitPost(token, item) // 2

processPost(post) // 3

}
v4: Coroutines Direct Style
suspend fun postItem(item: Item) {

val token = prepareToken() // 1

val post = submitPost(token, item) // 2

processPost(post) // 3

}
v4: Coroutines Direct Style
suspend fun postItem(item: Item) {

val token = prepareToken() // 1

val post = submitPost(token, item) // 2

processPost(post) // 3

}
Profit: try/catch, loops, std-lib
suspend fun postItems(items: List<Item>) {
try {
val token = prepareToken()
items.forEach { item ->
val post = submitPost(token, item)
processPost(post)
}
} catch (e: BadTokenException) { /*…*/ }
}
suspend fun
computation that can be suspended
Experimental status
Since Kotlin 1.1
-Xcoroutines=enable
kotlin.coroutines.experimental -> kotlin.coroutines (1.3)
Experimental != unstable
Can and should be used in production
Experimental status
New style of programming
The design is not final and expected to change
JetBrains still collects information and feedbacks
Backwards compatibility guaranteed
Terminology
coroutine
suspending functionsuspending lambda
suspending function type
coroutine builder
suspension point
continuation
Terminology
coroutine
suspending function
suspending lambda
suspending function type
coroutine builder
suspension pointcontinuation
A coroutine is…
an instance of suspendable computation
similar to a daemon thread, but very light-weight
similar to a future or promise
Why coroutines?
threads are expensive to keep and switch
your code is single threaded
you’ve got lots of mutable states
Patterns
• generators/yield: C#, Python, Scala
• async/await: C#, ECMAScript, Dart
• channels, select: Go
• actors: Scala
Standard API
• Language support (`suspend` keyword)
• low-level basic API (stdlib: kotlin.coroutines)
• high-level APIs that can be used in user code
Low-level API
(kotlin.coroutines)
• kotlin.coroutines.experimental
• create/start/suspendCoroutine()
• Continuation interface
• @RestrictSuspension annotation
• kotlin.coroutines.experimental.intrinsics
• suspendCoroutineOrReturn()
How does it work under the
hood?
Continuation
interface Continuation<in T> {

val context: CoroutineContext

fun resume(value: T)

fun resumeWithException(exception: Throwable)

}
Continuation
// Kotlin
suspend fun submitPost(
token: Token,
item: Item): Post {…}
// Java/JVM
Object submitPost(
Token token,
Item item,
Continuation<Post> cont) {…}
compiler magic
Continuations
suspend fun postItem(item: Item) {

val token = prepareToken()

val post = submitPost(token, item)

processPost(post)

}
Initial continuation
Continuations
suspend fun postItem(item: Item) {

val token = prepareToken()

val post = submitPost(token, item)

processPost(post)

}
Continuation
Continuations
suspend fun postItem(item: Item) {

val token = prepareToken()

val post = submitPost(token, item)

processPost(post)

}
Continuation
Labels
suspend fun postItem(item: Item) {
// LABEL 0

val token = prepareToken()
// LABEL 1

val post = submitPost(token, item)
// LABEL 2

processPost(post)

}
Labels
suspend fun postItem(item: Item) {
switch(label) {
case 0:
val token = prepareToken()
case 1:

val post = submitPost(token, item)
case 2:

processPost(post)
}

}
State
suspend fun postItem(item: Item) {
val stateMachine = object: CoroutineImpl {…}
switch(stateMachine.label) {
case 0:
val token = prepareToken()
case 1:

val post = submitPost(token, item)
case 2:

processPost(post)
}

}
CPS Transform
fun postItem(item: Item, cont: Continuation) {
val stateMachine = object: CoroutineImpl {…}
switch(stateMachine.label) {
case 0:
val token = prepareToken(stateMachine)
case 1:

val post = submitPost(token, item, stateMachine)
case 2:

processPost(post)
}

}
Save state
fun postItem(item: Item, cont: Continuation) {
val stateMachine = object: CoroutineImpl {…}
switch(stateMachine.label) {
case 0:
stateMachine.item = item
stateMachine.label = 1
prepareToken(stateMachine)
case 1:

…
}

}
Callback
fun postItem(item: Item, cont: Continuation) {
val stateMachine = cont as? ThisSM ?: object: ThisSM {
fun resume(…) {
postItem(null, this)
}
}
switch(stateMachine.label) {
case 0:
….
}

}
Restore state and continue
fun postItem(item: Item, cont: Continuation) {
…
case 0:
stateMachine.item = item
stateMachine.label = 1
prepareToken(stateMachine)
case 1:
val item = stateMachine.item
val token = stateMachine.result
stateMachine.label = 2

submitPost(token, item, stateMachine)
case 2:

…
How to create custom
coroutines?
Await for a Single
suspend fun <T> Single<T>.await(): T = TODO()
Suspend a coroutine
suspend fun <T> Single<T>.await(): T = suspendCancellableCoroutine { cont ->
// …
}
Subscribe
suspend fun <T> Single<T>.await(): T = suspendCancellableCoroutine { cont ->
subscribe(object : SingleObserver<T> {
override fun onSuccess(t: T) {
TODO()
}
override fun onError(error: Throwable) {
TODO()
}
override fun onSubscribe(d: Disposable) {
TODO()
}
})
}
Return a result, if successful
suspend fun <T> Single<T>.await(): T = suspendCancellableCoroutine { cont ->
subscribe(object : SingleObserver<T> {
override fun onSuccess(t: T) {
cont.resume(t)
}
override fun onError(error: Throwable) {
TODO()
}
override fun onSubscribe(d: Disposable) {
TODO()
}
})
}
Or resume with exception
suspend fun <T> Single<T>.await(): T = suspendCancellableCoroutine { cont ->
subscribe(object : SingleObserver<T> {
override fun onSuccess(t: T) {
cont.resume(t)
}
override fun onError(error: Throwable) {
cont.resumeWithException(error)
}
override fun onSubscribe(d: Disposable) {
TODO()
}
})
}
Don’t forget to dispose
suspend fun <T> Single<T>.await(): T = suspendCancellableCoroutine { cont ->
subscribe(object : SingleObserver<T> {
override fun onSuccess(t: T) {
cont.resume(t)
}
override fun onError(error: Throwable) {
cont.resumeWithException(error)
}
override fun onSubscribe(d: Disposable) {
cont.invokeOnCompletion { d.dispose() }
}
})
}
And this is it
suspend fun <T> Single<T>.await(): T = suspendCancellableCoroutine { cont ->
subscribe(object : SingleObserver<T> {
override fun onSuccess(t: T) {
cont.resume(t)
}
override fun onError(error: Throwable) {
cont.resumeWithException(error)
}
override fun onSubscribe(d: Disposable) {
cont.invokeOnCompletion { d.dispose() }
}
})
}
kotlinx.coroutines
Core
integration
Guava
JDK 8
NIO
Quasar
reactive
Reactor
RxJava 1.x
Reactive Streams
RxJava 2.x
UI
Android
JavaFX
Swing
async
promise returned
(Deferred + await)
async/await
// C# way
async Task ProcessImage(String url)

{

var image = await LoadImage(url);

imageCache.Add(image);

}
// Kotlin way
suspend fun processImage(url: String) {

val image = loadImageAsync(url).await()

imageCache.add(image)

}
Not idiomatic way
fun loadImageAsync(url: String): Deferred<Image> = async { TODO() }
suspend fun processImage(url: String) {
val image = loadImageAsync(url).await()
imageCache.add(image)
}
Don’t define async functions
in the first place
Idiomatic way
suspend fun loadImage(url: String): Image = TODO()
suspend fun processImage(url: String) {
val image = async { loadImage(url) }.await()
imageCache.add(image)
}
Keep concurrency explicit
Generators API in
kotlin.coroutines
kotlin.coroutines.experimental
buildIterator()
buildSequence()
buildSequence {

print(“Start: ")

var prev = 1; var cur = 1

while (true) {
print(“Next")

yield(prev) // suspension point
val next = prev + cur

prev = cur; cur = next

}

print("End") // unreachable code

}.take(6).forEach { print(" $it ") }

// Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
buildSequence {

print(“Start: ")

var prev = 1; var cur = 1

while (true) {
print(“Next")

yield(prev) // suspension point
val next = prev + cur

prev = cur; cur = next

}

print("End") // unreachable code

}.take(6).forEach { print(" $it ") }

// Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
buildSequence {

print(“Start: ")

var prev = 1; var cur = 1

while (true) {
print(“Next")

yield(prev) // suspension point
val next = prev + cur

prev = cur; cur = next

}

print("End") // unreachable code

}.take(6).forEach { print(" $it ") }

// Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
buildSequence {

print(“Start: ")

var prev = 1; var cur = 1

while (true) {
print(“Next")

yield(prev) // suspension point
val next = prev + cur

prev = cur; cur = next

}

print("End") // unreachable code

}.take(6).forEach { print(" $it ") }

// Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
buildSequence {

print(“Start: ")

var prev = 1; var cur = 1

while (true) {
print(“Next")

yield(prev) // suspension point
val next = prev + cur

prev = cur; cur = next

}

print("End") // unreachable code

}.take(6).forEach { print(" $it ") }

// Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
launch
fire and forget
(Job)
run,
runBlocking
for main functions
and tests
delay
like Thread.sleep(),
but non-blocking
Channel
transfers values
between coroutines
produce
produces a stream of values
by sending them to a channel
(ProducerJob)
actor
deals with it’s mailbox
(ActorJob)
select
waits for the result of
multiple suspending
functions
Job lifecycle
New Active
Cancelling
Completed
Cancelled
Job states
State isActive isCompleted isCancelled
New
- - -
Active ✔ - -
Completed
- ✔ -
Cancelling
- - ✔
Cancelled
- ✔ ✔
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
Memory leaks
WeakReference “life hack”
suspend operator fun <T> WeakReference<T>.invoke(): T
= suspendCoroutineOrReturn {
get() ?: throw CancellationException()
}
val activityRef = WeakReference(this)

launch(CommonPool) {

activityRef().expensiveComputation()

}
Demo
A lot more left…
Coroutine dispatchers
Cancellation
Mutable state and concurrency
UI programming
Reactive streams
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
We are hiring!
Thank you!
@DmitriyZaitsev

More Related Content

PDF
Coroutines in Kotlin
PDF
Clojure 1.1 And Beyond
ODP
Rust言語紹介
PDF
Rust Mozlando Tutorial
PDF
Rust concurrency tutorial 2015 12-02
PDF
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
PPTX
Grand Central Dispatch in Objective-C
Coroutines in Kotlin
Clojure 1.1 And Beyond
Rust言語紹介
Rust Mozlando Tutorial
Rust concurrency tutorial 2015 12-02
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
Grand Central Dispatch in Objective-C

What's hot (20)

PPTX
Project in programming
ODP
Anyevent
PDF
Introduction to Rust
PDF
Python meetup: coroutines, event loops, and non-blocking I/O
PDF
Any event intro
PDF
DevOpsCon 2021: Go Web Development 101
PDF
Welcome to Modern C++
PDF
entwickler.de Go Day: Go Web Development 101
PDF
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
PDF
Unbearable Test Code Smell
PDF
Pdr ppt
PDF
Ownership System in Rust
PPTX
Pro typescript.ch03.Object Orientation in TypeScript
PPTX
Go Concurrency Basics
PDF
ES2015 (ES6) Overview
PDF
Think Async: Asynchronous Patterns in NodeJS
PDF
JavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
ODP
Clojure: Practical functional approach on JVM
PDF
ES6 in Production [JSConfUY2015]
TXT
Source Code
Project in programming
Anyevent
Introduction to Rust
Python meetup: coroutines, event loops, and non-blocking I/O
Any event intro
DevOpsCon 2021: Go Web Development 101
Welcome to Modern C++
entwickler.de Go Day: Go Web Development 101
betterCode() Go: Einstieg in Go, Standard-Library und Ökosystem
Unbearable Test Code Smell
Pdr ppt
Ownership System in Rust
Pro typescript.ch03.Object Orientation in TypeScript
Go Concurrency Basics
ES2015 (ES6) Overview
Think Async: Asynchronous Patterns in NodeJS
JavaForum Nord 2021: Java to Go - Google Go für Java-Entwickler
Clojure: Practical functional approach on JVM
ES6 in Production [JSConfUY2015]
Source Code
Ad

Similar to Coroutines in Kotlin. UA Mobile 2017. (20)

PDF
Kotlin coroutine - behind the scenes
PDF
Current State of Coroutines
PDF
Kotlin coroutine - the next step for RxJava developer?
PDF
Job Queue in Golang
PPTX
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
PDF
JVMLS 2016. Coroutines in Kotlin
PDF
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
PDF
Kotlin : Advanced Tricks - Ubiratan Soares
PPTX
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
PDF
Kotlin Coroutines Reloaded
PDF
Asynchronní programování
PDF
ClojureScript loves React, DomCode May 26 2015
ODP
Concurrency on the JVM
PDF
Programação assíncrona utilizando Coroutines
PDF
Dip into Coroutines - KTUG Munich 202303
PPTX
Kotlin Coroutines and Rx
PDF
Kotlin Coroutines. Flow is coming
KEY
Unfiltered Unveiled
PDF
Fresh Async with Kotlin @ QConSF 2017
PPTX
Concurrent Application Development using Scala
Kotlin coroutine - behind the scenes
Current State of Coroutines
Kotlin coroutine - the next step for RxJava developer?
Job Queue in Golang
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
JVMLS 2016. Coroutines in Kotlin
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
Kotlin : Advanced Tricks - Ubiratan Soares
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
Kotlin Coroutines Reloaded
Asynchronní programování
ClojureScript loves React, DomCode May 26 2015
Concurrency on the JVM
Programação assíncrona utilizando Coroutines
Dip into Coroutines - KTUG Munich 202303
Kotlin Coroutines and Rx
Kotlin Coroutines. Flow is coming
Unfiltered Unveiled
Fresh Async with Kotlin @ QConSF 2017
Concurrent Application Development using Scala
Ad

More from UA Mobile (20)

PDF
Designing iOS+Android project without using multiplatform frameworks - UA Mob...
PDF
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
PDF
Leave your Room behind - UA Mobile 2019
PDF
OpenId and OAuth2: Rear, Medium, Well Done - UA Mobile 2019
PDF
Google Wear OS watch faces and applications development - UA Mobile 2019
PDF
Історія декількох проектів та що в них пішло не так - UA Mobile 2019
PDF
Working effectively with ViewModels and TDD - UA Mobile 2019
PDF
Managing State in Reactive applications - UA Mobile 2019
PDF
Ідіоматична ін'єкція залежностей на Kotlin без фреймворків - UA Mobile2019
PDF
Актуальні практики дизайну мобільних додатків - UA Mobile 2019
PDF
До чого прикладати Docker в Android? - UA Mobile 2019
PDF
Building your Flutter apps using Redux - UA Mobile 2019
PDF
Optional. Tips and Tricks - UA Mobile 2019
PDF
Designing iOS+Android project without using multiplatform frameworks - UA Mob...
PDF
Бібліотеки та Інструменти на сторожі коду - UA Mobile 2019
PDF
Flutter: No more boring apps! - UA Mobile 2019
PDF
Долаючи прірву між дизайнерами та розробниками - UA Mobile 2019
PDF
Multiplatform shared codebase with Kotlin/Native - UA Mobile 2019
PDF
Sceneform SDK на практиці - UA Mobile 2019
PDF
Augmented reality on Android. UA Mobile 2017.
Designing iOS+Android project without using multiplatform frameworks - UA Mob...
Декларативное программирование клиент-серверных приложений на андроид - UA Mo...
Leave your Room behind - UA Mobile 2019
OpenId and OAuth2: Rear, Medium, Well Done - UA Mobile 2019
Google Wear OS watch faces and applications development - UA Mobile 2019
Історія декількох проектів та що в них пішло не так - UA Mobile 2019
Working effectively with ViewModels and TDD - UA Mobile 2019
Managing State in Reactive applications - UA Mobile 2019
Ідіоматична ін'єкція залежностей на Kotlin без фреймворків - UA Mobile2019
Актуальні практики дизайну мобільних додатків - UA Mobile 2019
До чого прикладати Docker в Android? - UA Mobile 2019
Building your Flutter apps using Redux - UA Mobile 2019
Optional. Tips and Tricks - UA Mobile 2019
Designing iOS+Android project without using multiplatform frameworks - UA Mob...
Бібліотеки та Інструменти на сторожі коду - UA Mobile 2019
Flutter: No more boring apps! - UA Mobile 2019
Долаючи прірву між дизайнерами та розробниками - UA Mobile 2019
Multiplatform shared codebase with Kotlin/Native - UA Mobile 2019
Sceneform SDK на практиці - UA Mobile 2019
Augmented reality on Android. UA Mobile 2017.

Recently uploaded (6)

DOC
Camb毕业证学历认证,格罗斯泰斯特主教大学毕业证仿冒文凭毕业证
PPTX
ASMS Telecommunication company Profile
DOC
证书学历UoA毕业证,澳大利亚中汇学院毕业证国外大学毕业证
PDF
heheheueueyeyeyegehehehhehshMedia-Literacy.pdf
PDF
6-UseCfgfhgfhgfhgfhgfhfhhaseActivity.pdf
PDF
Lesson 13- HEREDITY _ pedSAWEREGFVCXZDSASEWFigree.pdf
Camb毕业证学历认证,格罗斯泰斯特主教大学毕业证仿冒文凭毕业证
ASMS Telecommunication company Profile
证书学历UoA毕业证,澳大利亚中汇学院毕业证国外大学毕业证
heheheueueyeyeyegehehehhehshMedia-Literacy.pdf
6-UseCfgfhgfhgfhgfhgfhfhhaseActivity.pdf
Lesson 13- HEREDITY _ pedSAWEREGFVCXZDSASEWFigree.pdf

Coroutines in Kotlin. UA Mobile 2017.