fresh async with kotlin @ qconsf 2017
TRANSCRIPT
![Page 1: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/1.jpg)
FreshAsyncWithKotlin
PresentedatQCon SF,2017/RomanElizarov@JetBrains
![Page 2: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/2.jpg)
Speaker:RomanElizarov
• 16+yearsexperience• Previouslydevelopedhigh-perftradingsoftware@Devexperts• Teachconcurrent&[email protected]• Chiefjudge@NorthernEurasiaContest/ACMICPC• NowteamleadinKotlinLibraries@JetBrains
![Page 3: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/3.jpg)
Pragmatic.Concise.Modern.InteroperablewithJava.
![Page 4: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/4.jpg)
AsynchronousProgramming
![Page 5: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/5.jpg)
Howdowewritecodethatwaitsforsomethingmostofthetime?
![Page 6: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/6.jpg)
AtoyproblemKotlin fun requestToken(): Token {
// makes request for a token & waitsreturn token // returns result when received
}
1
![Page 7: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/7.jpg)
fun requestToken(): Token { … }fun createPost(token: Token, item: Item): Post {
// sends item to the server & waits return post // returns resulting post
}
AtoyproblemKotlin
2
![Page 8: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/8.jpg)
fun requestToken(): Token { … }fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) {
// does some local processing of result}
AtoyproblemKotlin
3
![Page 9: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/9.jpg)
fun requestToken(): Token { … }fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
AtoyproblemKotlin
fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
123
Canbedonewiththreads!
![Page 10: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/10.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)
}
Isanythingwrongwithit?
![Page 11: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/11.jpg)
Howmanythreadswecanhave?
100🙂
![Page 12: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/12.jpg)
Howmanythreadswecanhave?
1000😅
![Page 13: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/13.jpg)
Howmanythreadswecanhave?
10000😩
![Page 14: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/14.jpg)
Howmanythreadswecanhave?
100000😵
![Page 15: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/15.jpg)
CallbackstotherescueSortof…
![Page 16: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/16.jpg)
Callbacks:beforefun requestToken(): Token {
// makes request for a token & waitsreturn token // returns result when received
}
1
![Page 17: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/17.jpg)
Callbacks:afterfun requestTokenAsync(cb: (Token) -> Unit) {
// makes request for a token, invokes callback when done// returns immediately
}
1callback
![Page 18: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/18.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 19: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/19.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 20: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/20.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 21: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/21.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“callbackhell”
Thisissimplified.Handlingexceptionsmakesitarealmess
![Page 22: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/22.jpg)
Futures/Promises/RxtotherescueSortof…
![Page 23: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/23.jpg)
Futures:beforefun requestTokenAsync(cb: (Token) -> Unit) {
// makes request for a token, invokes callback when done// returns immediately
}
1
![Page 24: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/24.jpg)
Futures:afterfun requestTokenAsync(): Promise<Token> {
// makes request for a token// returns promise for a future result immediately
}
1future
![Page 25: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/25.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 26: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/26.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 27: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/27.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 28: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/28.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 &propagatesexceptions
Nonestingindentation
![Page 29: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/29.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) }}
Butallthosecombinators…
![Page 30: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/30.jpg)
KotlincoroutinestotherescueLet’sgetreal
![Page 31: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/31.jpg)
Coroutines:beforefun requestTokenAsync(): Promise<Token> {
// makes request for a token// returns promise for a future result immediately
}
1
![Page 32: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/32.jpg)
Coroutines:aftersuspend fun requestToken(): Token {
// makes request for a token & suspendsreturn token // returns result when received
}
1naturalsignature
![Page 33: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/33.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 34: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/34.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
}
2naturalsignature
![Page 35: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/35.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 36: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/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)
}
![Page 37: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/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)
}
Likeregular code
![Page 38: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/38.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)
}
suspensionpoints
![Page 39: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/39.jpg)
• Regularloops
Bonusfeatures
for ((token, item) in list) {createPost(token, item)
}
![Page 40: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/40.jpg)
• Regularexceptionhanding
Bonusfeatures
try { createPost(token, item)
} catch (e: BadTokenException) { …
}
![Page 41: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/41.jpg)
• Regularhigher-orderfunctions
• forEach,let,apply,repeat,filter,map,use,etc
Bonusfeatures
file.readLines().forEach { line ->createPost(token, line.toItem())
}
![Page 42: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/42.jpg)
• Customhigher-orderfunctions
Bonusfeatures
val post = retryIO {createPost(token, item)
}
Everythinglikeinblockingcode
![Page 43: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/43.jpg)
Howdoesitwork?Aquickpeekbehindthescenes
![Page 44: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/44.jpg)
Kotlinsuspendingfunctions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
![Page 45: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/45.jpg)
Kotlinsuspendingfunctions
callback
Kotlin
Java/JVM
Continuationisagenericcallbackinterface
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {val context: CoroutineContextfun resume(value: T)fun resumeWithException(exception: Throwable)
}
![Page 46: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/46.jpg)
Kotlinsuspendingfunctions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {val context: CoroutineContextfun resume(value: T)fun resumeWithException(exception: Throwable)
}
![Page 47: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/47.jpg)
Kotlinsuspendingfunctions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {val context: CoroutineContextfun resume(value: T)fun resumeWithException(exception: Throwable)
}
![Page 48: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/48.jpg)
Kotlinsuspendingfunctions
callback
Kotlin
Java/JVM
suspend fun createPost(token: Token, item: Item): Post { … }
Object createPost(Token token, Item item, Continuation<Post> cont) { … }
interface Continuation<in T> {val context: CoroutineContextfun resume(value: T)fun resumeWithException(exception: Throwable)
}
![Page 49: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/49.jpg)
CodewithsuspensionpointsKotlin
Java/JVMCompilestostatemachine(simplifiedcodeshown)
val token = requestToken()val post = createPost(token, item)processPost(post)
switch (cont.label) {case 0:
cont.label = 1;requestToken(cont);break;
case 1:Token token = (Token) prevResult;cont.label = 2;createPost(token, item, cont);break;
case 2:Post post = (Post) prevResult;processPost(post);break;
}
![Page 50: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/50.jpg)
CodewithsuspensionpointsKotlin
Java/JVM
val token = requestToken()val post = createPost(token, item)processPost(post)
switch (cont.label) {case 0:
cont.label = 1;requestToken(cont);break;
case 1:Token token = (Token) prevResult;cont.label = 2;createPost(token, item, cont);break;
case 2:Post post = (Post) prevResult;processPost(post);break;
}
![Page 51: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/51.jpg)
IntegrationZoooffuturesonJVM
![Page 52: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/52.jpg)
interface Service {fun createPost(token: Token, item: Item): Call<Post>
}
Retrofitasync
![Page 53: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/53.jpg)
interface Service {fun createPost(token: Token, item: Item): Call<Post>
}
suspend fun createPost(token: Token, item: Item): Post =serviceInstance.createPost(token, item).await()
naturalsignature
![Page 54: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/54.jpg)
interface Service {fun createPost(token: Token, item: Item): Call<Post>
}
suspend fun createPost(token: Token, item: Item): Post =serviceInstance.createPost(token, item).await()
Suspendingextensionfunctionfromintegrationlibrary
![Page 55: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/55.jpg)
suspend fun <T> Call<T>.await(): T {…
}
![Page 56: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/56.jpg)
Callbackseverywhere
suspend fun <T> Call<T>.await(): T {enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {// todo
}
override fun onFailure(call: Call<T>, t: Throwable) {// todo
}})
}
![Page 57: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/57.jpg)
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {if (response.isSuccessful)
cont.resume(response.body()!!)else
cont.resumeWithException(ErrorResponse(response))}
override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)
}})
}
![Page 58: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/58.jpg)
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T
![Page 59: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/59.jpg)
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T
![Page 60: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/60.jpg)
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T
Regularfunction
Inspiredbycall/cc fromScheme
![Page 61: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/61.jpg)
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {if (response.isSuccessful)
cont.resume(response.body()!!)else
cont.resumeWithException(ErrorResponse(response))}
override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)
}})
}
![Page 62: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/62.jpg)
Installcallback
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {if (response.isSuccessful)
cont.resume(response.body()!!)else
cont.resumeWithException(ErrorResponse(response))}
override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)
}})
}
![Page 63: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/63.jpg)
Installcallback
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {if (response.isSuccessful)
cont.resume(response.body()!!)else
cont.resumeWithException(ErrorResponse(response))}
override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)
}})
}
![Page 64: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/64.jpg)
Analyzeresponse
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {if (response.isSuccessful)
cont.resume(response.body()!!)else
cont.resumeWithException(ErrorResponse(response))}
override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)
}})
}
![Page 65: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/65.jpg)
Analyzeresponse
suspend fun <T> Call<T>.await(): T = suspendCoroutine { cont ->enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {if (response.isSuccessful)
cont.resume(response.body()!!)else
cont.resumeWithException(ErrorResponse(response))}
override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)
}})
}That’sall
![Page 66: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/66.jpg)
Out-of-theboxintegrations
kotlinx-coroutines-core
jdk8
guava
nio
reactor
rx1
rx2
![Page 67: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/67.jpg)
CoroutinebuildersHowcanwestartacoroutine?
![Page 68: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/68.jpg)
Coroutinesrevisitedsuspend 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 69: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/69.jpg)
Coroutinesrevisitedsuspend 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 70: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/70.jpg)
Coroutinesrevisitedsuspend 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: Suspendfunction'requestToken'shouldbecalledonlyfromacoroutineoranothersuspendfunction
![Page 71: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/71.jpg)
Coroutinesrevisitedsuspend 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)
}
Cansuspend execution
![Page 72: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/72.jpg)
Coroutinesrevisitedsuspend 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)
}
Cansuspend executionAregularfunctioncannot
![Page 73: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/73.jpg)
Coroutinesrevisitedsuspend 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)
}
Cansuspend executionAregularfunctioncannot
Onecannotsimplyinvokeasuspendingfunction
![Page 74: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/74.jpg)
Launch
fun postItem(item: Item) {launch {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
coroutinebuilder
![Page 75: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/75.jpg)
fun postItem(item: Item) {launch {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
Fireandforget!
Returnsimmediately,coroutineworksinbackgroundthreadpool
![Page 76: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/76.jpg)
fun postItem(item: Item) {launch {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
![Page 77: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/77.jpg)
fun postItem(item: Item) {launch(UI) {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
UIContext
Justspecifythecontext
![Page 78: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/78.jpg)
fun postItem(item: Item) {launch(UI) {
val token = requestToken()val post = createPost(token, item)processPost(post)
}}
UIContext
AnditgetsexecutedonUIthread
![Page 79: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/79.jpg)
Where’sthemagicoflaunch?
![Page 80: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/80.jpg)
fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit
): Job { … }
Aregularfunction
![Page 81: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/81.jpg)
fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit
): Job { … } suspendinglambda
![Page 82: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/82.jpg)
fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit
): Job { … }
![Page 83: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/83.jpg)
async /awaitTheclassicapproach
![Page 84: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/84.jpg)
Kotlin-way
suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)
}
suspend fun requestToken(): Token { … }suspend fun createPost(token: Token, item: Item): Post { … }fun processPost(post: Post) { … }
Kotlin
![Page 85: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/85.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
C#approachtothesameproblem(alsoPython,TS,Dart,comingtoJS)
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
C#
![Page 86: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/86.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
markwithasync
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
C#
![Page 87: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/87.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
useawaittosuspend
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
C#
![Page 88: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/88.jpg)
async Task postItem(Item item) { var token = await requestToken(); var post = await createPost(token, item); processPost(post);
}
Classic-way
returnsafuture
async Task<Token> requestToken() { … }async Task<Post> createPost(Token token, Item item) { … }void processPost(Post post) { … }
C#
![Page 89: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/89.jpg)
Whynoawait keywordinKotlin?
Theproblemwithasync
requestToken() VALID –>producesTask<Token>
await requestToken() VALID –>producesToken
concurrentbehavior
sequentialbehavior
C#
C#
default
ConcurrencyishardConcurrencyhastobeexplicit
![Page 90: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/90.jpg)
Kotlinsuspendingfunctionsaredesignedtoimitatesequential behavior
bydefault
ConcurrencyishardConcurrencyhastobeexplicit
![Page 91: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/91.jpg)
KotlinapproachtoasyncConcurrencywhereyouneedit
![Page 92: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/92.jpg)
Use-caseforasync
async Task<Image> loadImageAsync(String name) { … } C#
![Page 93: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/93.jpg)
Use-caseforasync
var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);
async Task<Image> loadImageAsync(String name) { … }
Startmultipleoperationsconcurrently
C#
![Page 94: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/94.jpg)
Use-caseforasync
var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);
var image1 = await promise1;var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … }
andthenwaitforthem
C#
![Page 95: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/95.jpg)
Use-caseforasync
var result = combineImages(image1, image2);
var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);
var image1 = await promise1;var image2 = await promise2;
async Task<Image> loadImageAsync(String name) { … } C#
![Page 96: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/96.jpg)
Kotlinasync function
fun loadImageAsync(name: String): Deferred<Image> = async { … }
Kotlin
![Page 97: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/97.jpg)
Kotlinasync function
fun loadImageAsync(name: String): Deferred<Image> = async { … }
Aregularfunction
Kotlin
![Page 98: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/98.jpg)
Kotlinasync function
fun loadImageAsync(name: String): Deferred<Image> = async { … }
Kotlin’s futuretype
Kotlin
![Page 99: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/99.jpg)
Kotlinasync function
fun loadImageAsync(name: String): Deferred<Image> = async { … }
async coroutinebuilder
Kotlin
![Page 100: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/100.jpg)
Kotlinasync function
fun loadImageAsync(name: String): Deferred<Image> = async { … }
val deferred1 = loadImageAsync(name1)val deferred2 = loadImageAsync(name2)
Startmultipleoperationsconcurrently
Kotlin
![Page 101: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/101.jpg)
Kotlinasync function
fun loadImageAsync(name: String): Deferred<Image> = async { … }
val deferred1 = loadImageAsync(name1)val deferred2 = loadImageAsync(name2)
val image1 = deferred1.await()val image2 = deferred2.await() andthenwaitforthem
awaitfunction
Suspendsuntildeferrediscomplete
Kotlin
![Page 102: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/102.jpg)
Kotlinasync function
fun 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 103: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/103.jpg)
Usingasync functionwhenneeded
suspend fun loadImage(name: String): Image { … }
Isdefinedassuspendingfunction,notasync
![Page 104: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/104.jpg)
Usingasync functionwhenneeded
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 105: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/105.jpg)
Usingasync functionwhenneeded
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 106: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/106.jpg)
Usingasync functionwhenneeded
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 107: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/107.jpg)
Usingasync functionwhenneeded
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 108: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/108.jpg)
Kotlin approachtoasync
requestToken() VALID –>producesToken
async { requestToken() } VALID –>producesDeferred<Token>
sequentialbehavior
concurrentbehavior
Kotlin
Kotlin
default
![Page 109: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/109.jpg)
Whatarecoroutinesconceptually?
![Page 110: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/110.jpg)
Whatarecoroutinesconceptually?Coroutinesarelikevery light-weightthreads
![Page 111: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/111.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 112: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/112.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example Thiscoroutinebuilderrunscoroutineinthecontextofinvokerthread
![Page 113: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/113.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 114: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/114.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 115: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/115.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
Suspendsfor1second
![Page 116: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/116.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
Wecanjoinajobjustlikeathread
![Page 117: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/117.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
Trythatwith100kthreads!
Prints100kdotsafteroneseconddelay
![Page 118: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/118.jpg)
fun main(args: Array<String>) = runBlocking<Unit> {val jobs = List(100_000) {
launch {delay(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 119: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/119.jpg)
fun main(args: Array<String>) {val jobs = List(100_000) {
thread {Thread.sleep(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
![Page 120: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/120.jpg)
fun main(args: Array<String>) {val jobs = List(100_000) {
thread {Thread.sleep(1000L)print(".")
}}jobs.forEach { it.join() }
}
Example
Exceptioninthread"main"java.lang.OutOfMemoryError:unabletocreatenewnativethread
![Page 121: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/121.jpg)
JavainteropCanweuseKotlincoroutineswithJavacode?
![Page 122: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/122.jpg)
Javainterop
CompletableFuture<Image> loadImageAsync(String name) { … }Java
![Page 123: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/123.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }
CompletableFuture<Image> loadAndCombineAsync(String name1, String name2)
Java
ImagineimplementingitinJava…
![Page 124: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/124.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 125: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/125.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =…
Kotlin
![Page 126: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/126.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlin
![Page 127: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/127.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlinfuturecoroutinebuilder
![Page 128: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/128.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlin
![Page 129: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/129.jpg)
CompletableFuture<Image> loadImageAsync(String name) { … }Java
fun loadAndCombineAsync(name1: String, name2: String
): CompletableFuture<Image> =future {
val future1 = loadImageAsync(name1)val future2 = loadImageAsync(name2)combineImages(future1.await(), future2.await())
}
Kotlin
![Page 130: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/130.jpg)
BeyondasynchronouscodeKotlin’s approachtogenerate/yield– synchronouscoroutines
![Page 131: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/131.jpg)
Fibonaccisequence
val fibonacci: Sequence<Int> = …
![Page 132: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/132.jpg)
Fibonaccisequence
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
![Page 133: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/133.jpg)
Fibonaccisequence
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
Acoroutinebuilderwithrestrictedsuspension
![Page 134: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/134.jpg)
Fibonaccisequence
val fibonacci = buildSequence {var cur = 1var next = 1while (true) {
yield(cur) val tmp = cur + nextcur = nextnext = tmp
}}
Asuspendingfunction
![Page 135: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/135.jpg)
Thesamebuildingblocks
public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
![Page 136: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/136.jpg)
Thesamebuildingblocks
public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Resultisasynchronous sequence
![Page 137: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/137.jpg)
Thesamebuildingblocks
public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
Suspendinglambdawithreceiver
![Page 138: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/138.jpg)
Thesamebuildingblocks
public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit
): Sequence<T> { … }
@RestrictsSuspensionabstract class SequenceBuilder<in T> {
abstract suspend fun yield(value: T)}
Coroutineisrestrictedonlytosuspendingfunctionsdefinedhere
![Page 139: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/139.jpg)
LibraryvsLanguageKeepingthecorelanguagesmall
![Page 140: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/140.jpg)
Classicasync
async/awaitgenerate/yield Keywords
![Page 141: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/141.jpg)
Kotlincoroutines
suspend Modifier
![Page 142: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/142.jpg)
Kotlincoroutines
Standardlibrary
![Page 143: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/143.jpg)
Kotlincoroutines
Standardlibrary
kotlinx-coroutines
launch,async,runBlocking,future,delay,
Job,Deferred,etc
http://github.com/kotlin/kotlinx.coroutines
![Page 144: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/144.jpg)
ExperimentalinKotlin1.1&1.2
Coroutinescanbeused inproduction
Backwardscompatibleinside1.1&1.2
Tobefinalizedinthefuture
![Page 145: Fresh Async with Kotlin @ QConSF 2017](https://reader033.vdocuments.us/reader033/viewer/2022042707/5a6487337f8b9a27568b5b01/html5/thumbnails/145.jpg)
Thankyou
Anyquestions?
Slidesareavailableatwww.slideshare.net/elizarovemailmetoelizarov atgmail
relizarov