introduction to coroutines @ kotlinconf 2017
TRANSCRIPT
![Page 1: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/1.jpg)
elizarov at JetBrainsRoman Elizarov
Introduction to Coroutines
![Page 2: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/2.jpg)
Asynchronous programming
![Page 3: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/3.jpg)
How do we write code that waits for something most of the time?
![Page 4: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/4.jpg)
A toy problemKotlin fun requestToken(): Token {
// makes request for a token & waitsreturn token // returns result when received
}
1
![Page 5: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/5.jpg)
fun requestToken(): Token { … }fun createPost(token: Token, item: Item): Post {
// sends item to the server & waits return post // returns resulting post
}
A toy problem2
Kotlin
![Page 6: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/6.jpg)
fun requestToken(): Token { … }fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) {
// does some local processing of result}
A toy problem
3
Kotlin
![Page 7: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/7.jpg)
fun requestToken(): Token { … }fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
A toy problem
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
123
Can be done with threads!
Kotlin
![Page 8: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/8.jpg)
fun requestToken(): Token {// makes request for a token // blocks the thread waiting for resultreturn token // returns result when received
}fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
Threads
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Is anything wrong with it?
![Page 9: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/9.jpg)
How many threads we can have?
100 🙂
![Page 10: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/10.jpg)
How many threads we can have?
1000 😅
![Page 11: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/11.jpg)
How many threads we can have?
10 000 😩
![Page 12: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/12.jpg)
How many threads we can have?
100 000 😵
![Page 13: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/13.jpg)
Callbacks to the rescueSort of …
![Page 14: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/14.jpg)
Callbacks: beforefun requestToken(): Token {
// makes request for a token & waitsreturn token // returns result when received
}
1
![Page 15: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/15.jpg)
Callbacks: afterfun requestTokenAsync(cb: (Token) -> Unit) {
// makes request for a token, invokes callback when done// returns immediately
}
1callback
![Page 16: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/16.jpg)
Callbacks: beforefun requestTokenAsync(cb: (Token) -> Unit) { … }fun createPost(token: Token, item: Item): Post {
// sends item to the server & waits return post // returns resulting post
}
2
![Page 17: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/17.jpg)
Callbacks: afterfun requestTokenAsync(cb: (Token) -> Unit) { … }fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) {// sends item to the server, invokes callback when done// returns immediately
}
2callback
![Page 18: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/18.jpg)
Callbacks: beforefun requestTokenAsync(cb: (Token) -> Unit) { … }fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
![Page 19: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/19.jpg)
Callbacks: afterfun requestTokenAsync(cb: (Token) -> Unit) { … }fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {requestTokenAsync { token ->
createPostAsync(token, item) { post ->processPost(post)
}}
} aka “callback hell”
This is simplified. Handling exceptions makes it a real mess
![Page 20: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/20.jpg)
Futures/Promises/Rx to the rescue
Sort of …
![Page 21: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/21.jpg)
Futures: beforefun requestTokenAsync(cb: (Token) -> Unit) {
// makes request for a token, invokes callback when done// returns immediately
}
1
![Page 22: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/22.jpg)
Futures: afterfun requestTokenAsync(): Promise<Token> {
// makes request for a token// returns promise for a future result immediately
}
1future
![Page 23: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/23.jpg)
Futures: beforefun requestTokenAsync(): Promise<Token> { … }fun createPostAsync(token: Token, item: Item,
cb: (Post) -> Unit) {// sends item to the server, invokes callback when done// returns immediately
}
2
![Page 24: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/24.jpg)
Futures: afterfun requestTokenAsync(): Promise<Token> { … }fun createPostAsync(token: Token, item: Item): Promise<Post> {
// sends item to the server // returns promise for a future result immediately
}
future2
![Page 25: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/25.jpg)
Futures: beforefun requestTokenAsync(): Promise<Token> { … }fun createPostAsync(token: Token, item: Item): Promise<Post> …fun processPost(post: Post) { … }
fun postItem(item: Item) {requestTokenAsync { token ->
createPostAsync(token, item) { post ->processPost(post)
}}
}
![Page 26: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/26.jpg)
Futures: afterfun requestTokenAsync(): Promise<Token> { … }fun createPostAsync(token: Token, item: Item): Promise<Post> …fun processPost(post: Post) { … }
fun postItem(item: Item) {requestTokenAsync()
.thenCompose { token -> createPostAsync(token, item) }
.thenAccept { post -> processPost(post) }}
Composable &propagates exceptions
No nesting indentation
![Page 27: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/27.jpg)
Futures: afterfun requestTokenAsync(): Promise<Token> { … }fun createPostAsync(token: Token, item: Item): Promise<Post> …fun processPost(post: Post) { … }
fun postItem(item: Item) {requestTokenAsync()
.thenCompose { token -> createPostAsync(token, item) }
.thenAccept { post -> processPost(post) }}
But all those combinators…
![Page 28: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/28.jpg)
Kotlin coroutines to the rescueLet’s get real
![Page 29: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/29.jpg)
Coroutines: beforefun requestTokenAsync(): Promise<Token> {
// makes request for a token// returns promise for a future result immediately
}
1
![Page 30: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/30.jpg)
Coroutines: aftersuspend fun requestToken(): Token {
// makes request for a token & suspendsreturn token // returns result when received
}
1
![Page 31: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/31.jpg)
Coroutines: aftersuspend fun requestToken(): Token {
// makes request for a token & suspendsreturn token // returns result when received
}
1natural signature
![Page 32: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/32.jpg)
Coroutines: beforesuspend fun requestToken(): Token { … }fun createPostAsync(token: Token, item: Item): Promise<Post> {
// sends item to the server // returns promise for a future result immediately
}
2
![Page 33: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/33.jpg)
Coroutines: aftersuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post {
// sends item to the server & suspendsreturn post // returns result when received
}
2
![Page 34: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/34.jpg)
Coroutines: beforesuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {requestTokenAsync()
.thenCompose { token -> createPostAsync(token, item) }
.thenAccept { post -> processPost(post) }}
![Page 35: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/35.jpg)
Coroutines: aftersuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
![Page 36: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/36.jpg)
Coroutines: aftersuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Like regular code
![Page 37: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/37.jpg)
Coroutines: aftersuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
suspension points
![Page 38: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/38.jpg)
• Regular loops
Bonus features
for ((token, item) in list) {createPost(token, item)
}
![Page 39: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/39.jpg)
• Regular exception handing
Bonus features
try { createPost(token, item)
} catch (e: BadTokenException) { …
}
![Page 40: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/40.jpg)
• Regular higher-order functions
• forEach, let, apply, repeat, filter, map, use, etc
Bonus features
file.readLines().forEach { line ->createPost(token, line.toItem())
}
Everything like in blocking code
![Page 41: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/41.jpg)
Suspending functions
![Page 42: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/42.jpg)
Retrofit asyncinterface Service {
fun createPost(token: Token, item: Item): Call<Post>}
![Page 43: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/43.jpg)
Retrofit asyncinterface Service {
fun createPost(token: Token, item: Item): Call<Post>}
future
![Page 44: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/44.jpg)
Retrofit asyncinterface Service {
fun createPost(token: Token, item: Item): Call<Post>}
suspend fun createPost(token: Token, item: Item): Post =serviceInstance.createPost(token, item).await()
![Page 45: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/45.jpg)
Retrofit asyncinterface Service {
fun createPost(token: Token, item: Item): Call<Post>}
suspend fun createPost(token: Token, item: Item): Post =serviceInstance.createPost(token, item).await()
natural signature
![Page 46: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/46.jpg)
Retrofit asyncinterface Service {
fun createPost(token: Token, item: Item): Call<Post>}
suspend fun createPost(token: Token, item: Item): Post =serviceInstance.createPost(token, item).await()
Suspending extension function from integration library
![Page 47: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/47.jpg)
CompositionBeyond sequential
![Page 48: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/48.jpg)
val post = createPost(token, item)
![Page 49: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/49.jpg)
Higher-order functions
val post = retryIO {createPost(token, item)
}
![Page 50: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/50.jpg)
Higher-order functionsval post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {var curDelay = 1000L // start with 1 secwhile (true) {
try {return block()
} catch (e: IOException) {e.printStackTrace() // log the error
}delay(curDelay)curDelay = (curDelay * 2).coerceAtMost(60000L)
}}
![Page 51: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/51.jpg)
Higher-order functionsval post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {var curDelay = 1000L // start with 1 secwhile (true) {
try {return block()
} catch (e: IOException) {e.printStackTrace() // log the error
}delay(curDelay)curDelay = (curDelay * 2).coerceAtMost(60000L)
}}
![Page 52: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/52.jpg)
Higher-order functionsval post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {var curDelay = 1000L // start with 1 secwhile (true) {
try {return block()
} catch (e: IOException) {e.printStackTrace() // log the error
}delay(curDelay)curDelay = (curDelay * 2).coerceAtMost(60000L)
}}
suspending lambda
![Page 53: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/53.jpg)
Higher-order functionsval post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {var curDelay = 1000L // start with 1 secwhile (true) {
try {return block()
} catch (e: IOException) {e.printStackTrace() // log the error
}delay(curDelay)curDelay = (curDelay * 2).coerceAtMost(60000L)
}}
Everything like in blocking code
![Page 54: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/54.jpg)
Higher-order functionsval post = retryIO { createPost(token, item) }
suspend fun <T> retryIO(block: suspend () -> T): T {var curDelay = 1000L // start with 1 secwhile (true) {
try {return block()
} catch (e: IOException) {e.printStackTrace() // log the error
}delay(curDelay)curDelay = (curDelay * 2).coerceAtMost(60000L)
}}
![Page 55: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/55.jpg)
Coroutine builders
![Page 56: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/56.jpg)
Coroutines revisitedsuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
![Page 57: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/57.jpg)
Coroutines revisitedsuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
![Page 58: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/58.jpg)
Coroutines revisitedsuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Error: Suspend function 'requestToken' should be called only from a coroutine or another suspend function
![Page 59: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/59.jpg)
Coroutines revisitedsuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Can suspend execution
![Page 60: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/60.jpg)
Coroutines revisitedsuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Can suspend execution A regular function cannot
![Page 61: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/61.jpg)
Coroutines revisitedsuspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Can suspend execution A regular function cannot
One cannot simply invoke a suspending function
![Page 62: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/62.jpg)
Launch
fun postItem(item: Item) {launch {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
coroutine builder
![Page 63: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/63.jpg)
fun postItem(item: Item) {launch {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
Fire and forget!
Returns immediately, coroutine works in background thread pool
![Page 64: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/64.jpg)
fun postItem(item: Item) {launch {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
![Page 65: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/65.jpg)
fun postItem(item: Item) {launch(UI) {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
UI ContextJust specify the context
![Page 66: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/66.jpg)
fun postItem(item: Item) {launch(UI) {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
UI Context
And it gets executed on UI thread
![Page 67: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/67.jpg)
Where’s the magic of launch?
![Page 68: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/68.jpg)
fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit
): Job { … }
A regular function
![Page 69: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/69.jpg)
fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit
): Job { … } suspending lambda
![Page 70: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/70.jpg)
fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit
): Job { … }
![Page 71: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/71.jpg)
async / await
![Page 72: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/72.jpg)
Kotlin-way
suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
Kotlin
suspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
![Page 73: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/73.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
C# approach to the same problem (also Python, TS, Dart, coming to JS)
C#
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
![Page 74: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/74.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
mark with asyncC#
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
![Page 75: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/75.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
use await to suspend
C#
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
![Page 76: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/76.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
C#returns a future
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
![Page 77: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/77.jpg)
Why no await keyword in Kotlin?The problem with async
requestToken() VALID –> produces Task<Token>
await requestToken() VALID –> produces Token
concurrent behavior
sequential behavior
C#
C#
default
![Page 78: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/78.jpg)
Kotlin suspending functions are designed to imitate
sequential behavior by default
Concurrency is hardConcurrency has to be explicit
![Page 79: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/79.jpg)
Kotlin approach to asyncConcurrency where you need it
![Page 80: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/80.jpg)
Use-case for asyncasync Task<Image> loadImageAsync(String name) { … } C#
![Page 81: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/81.jpg)
Use-case for async
var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);
async Task<Image> loadImageAsync(String name) { … }
Start multiple operations concurrently
C#
![Page 82: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/82.jpg)
Use-case for async
var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);
var image1 = await promise1;var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … }
and then wait for them
C#
![Page 83: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/83.jpg)
Use-case for async
var result = combineImages(image1, image2);
C#
var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);
var image1 = await promise1;var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … }
![Page 84: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/84.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }Kotlin
![Page 85: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/85.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }Kotlin
A regular function
![Page 86: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/86.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }
Kotlin’s future type
Kotlin
![Page 87: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/87.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }
async coroutine builder
Kotlin
![Page 88: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/88.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }
val deferred1 = loadImageAsync(name1)val deferred2 = loadImageAsync(name2)
Start multiple operations concurrently
Kotlin
![Page 89: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/89.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }
val deferred1 = loadImageAsync(name1)val deferred2 = loadImageAsync(name2)
val image1 = deferred1.await()val image2 = deferred2.await() and then wait for them
await function
Suspends until deferred is complete
Kotlin
![Page 90: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/90.jpg)
Kotlin async functionfun loadImageAsync(name: String): Deferred<Image> =
async { … }
val deferred1 = loadImageAsync(name1)val deferred2 = loadImageAsync(name2)
val image1 = deferred1.await()val image2 = deferred2.await()
val result = combineImages(image1, image2)
Kotlin
![Page 91: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/91.jpg)
Using async function when needed
suspend fun loadImage(name: String): Image { … }
Is defined as suspending function, not async
![Page 92: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/92.jpg)
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) }val deferred2 = async { loadImage(name2) }return combineImages(deferred1.await(), deferred2.await())
}
![Page 93: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/93.jpg)
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) }val deferred2 = async { loadImage(name2) }return combineImages(deferred1.await(), deferred2.await())
}
![Page 94: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/94.jpg)
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) }val deferred2 = async { loadImage(name2) }return combineImages(deferred1.await(), deferred2.await())
}
![Page 95: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/95.jpg)
Using async function when needed
suspend fun loadImage(name: String): Image { … }
suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = async { loadImage(name1) }val deferred2 = async { loadImage(name2) }return combineImages(deferred1.await(), deferred2.await())
}
![Page 96: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/96.jpg)
Kotlin approach to async
requestToken() VALID –> produces Token
async { requestToken() } VALID –> produces Deferred<Token>
sequential behavior
concurrent behavior
Kotlin
Kotlin
default
![Page 97: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/97.jpg)
Coroutines
![Page 98: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/98.jpg)
What are coroutines conceptually?
![Page 99: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/99.jpg)
What are coroutines conceptually?
Coroutines are like very light-weight threads
![Page 100: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/100.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 101: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/101.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
ExampleThis coroutine builder runs coroutine
in the context of invoker thread
![Page 102: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/102.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 103: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/103.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 104: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/104.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
Suspends for 1 second
![Page 105: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/105.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
We can join a job just like a thread
![Page 106: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/106.jpg)
Demo
![Page 107: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/107.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
Try that with 100k threads!
Prints 100k dots after one second delay
![Page 108: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/108.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 109: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/109.jpg)
fun main(args: Array<String>) {val jobs = List(100_000) {
thread {Thread.sleep(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 110: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/110.jpg)
Demo
![Page 111: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/111.jpg)
fun main(args: Array<String>) {val jobs = List(100_000) {
thread {Thread.sleep(1000L)print(".")
}}jobs.forEach { it.join() }
}
ExampleException in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
![Page 112: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/112.jpg)
Java interop
![Page 113: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/113.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }Java
![Page 114: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/114.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1, String name2)
Imagine implementing it in Java…
Java
![Page 115: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/115.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1,String name2)
{CompletableFuture<Image> future1 = loadImageAsync(name1);CompletableFuture<Image> future2 = loadImageAsync(name2);return future1.thenCompose(image1 ->
future2.thenCompose(image2 ->CompletableFuture.supplyAsync(() ->
combineImages(image1, image2))));}
Java
![Page 116: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/116.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1,String name2)
{CompletableFuture<Image> future1 = loadImageAsync(name1);CompletableFuture<Image> future2 = loadImageAsync(name2);return future1.thenCompose(image1 ->
future2.thenCompose(image2 ->CompletableFuture.supplyAsync(() ->
combineImages(image1, image2))));}
Java
![Page 117: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/117.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlin
Java
![Page 118: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/118.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlin
Java
![Page 119: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/119.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
future coroutine builderKotlin
Java
![Page 120: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/120.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlin
Java
![Page 121: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/121.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}Extension for Java’s CompletableFuture
Kotlin
Java
![Page 122: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/122.jpg)
Beyond asynchronous code
![Page 123: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/123.jpg)
Fibonacci sequenceval fibonacci = buildSequence {
var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
![Page 124: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/124.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
A coroutine builder with restricted suspension
![Page 125: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/125.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
A suspending function
![Page 126: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/126.jpg)
The same building blocksfun <T> buildSequence(
builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T> { … }
![Page 127: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/127.jpg)
fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Result is a synchronous sequence
![Page 128: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/128.jpg)
fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }Suspending lambda with receiver
![Page 129: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/129.jpg)
fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
@RestrictsSuspensionabstract class SequenceBuilder<in T> {
abstract suspend fun yield(value: T)}
Coroutine is restricted only to suspending functions defined here
![Page 130: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/130.jpg)
Synchronousval fibonacci = buildSequence {
var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()
![Page 131: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/131.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next())
![Page 132: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/132.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next())
![Page 133: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/133.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next()) // 1
![Page 134: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/134.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next()) // 1println(iter.next())
![Page 135: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/135.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next()) // 1println(iter.next())
![Page 136: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/136.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next()) // 1println(iter.next()) // 1
![Page 137: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/137.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next()) // 1println(iter.next()) // 1println(iter.next()) // 2
![Page 138: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/138.jpg)
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
val iter = fibonacci.iterator()println(iter.next()) // 1println(iter.next()) // 1println(iter.next()) // 2
Synchronous with invoker
![Page 139: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/139.jpg)
Library vs Language
![Page 140: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/140.jpg)
Classic async
async/awaitgenerate/yield Keywords
![Page 141: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/141.jpg)
Kotlin coroutines
suspend Modifier
![Page 142: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/142.jpg)
Kotlin coroutines
Standardlibrary
![Page 143: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/143.jpg)
Kotlin coroutines
Standardlibrary
kotlinx-coroutines
launch, async, runBlocking, future, delay,
Job, Deferred, etc
http://github.com/kotlin/kotlinx.coroutines
![Page 144: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/144.jpg)
Experimental statusCoroutines are here to stay
Backwards compatible inside 1.1 & 1.2
To be finalized in the future
![Page 145: Introduction to Coroutines @ KotlinConf 2017](https://reader034.vdocuments.net/reader034/viewer/2022052318/5a6487337f8b9a27568b5aff/html5/thumbnails/145.jpg)
#kotlinconf17
relizarovelizarov at JetBrains
Roman Elizarov
Thank you
Any questions?