145
Fresh Async With Kotlin Presented at QCon SF, 2017 /Roman Elizarov @ JetBrains

Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

  • Upload
    others

  • View
    28

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

FreshAsyncWithKotlin

PresentedatQCon SF,2017/RomanElizarov@JetBrains

Page 2: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Speaker:RomanElizarov

• 16+yearsexperience• Previouslydevelopedhigh-perftradingsoftware@Devexperts• Teachconcurrent&[email protected]• Chiefjudge@NorthernEurasiaContest/ACMICPC• NowteamleadinKotlinLibraries@JetBrains

Page 3: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Pragmatic.Concise.Modern.InteroperablewithJava.

Page 4: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

AsynchronousProgramming

Page 5: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Howdowewritecodethatwaitsforsomethingmostofthetime?

Page 6: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

AtoyproblemKotlin fun requestToken(): Token {

// makes request for a token & waitsreturn token // returns result when received

}

1

Page 7: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Howmanythreadswecanhave?

100🙂

Page 12: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Howmanythreadswecanhave?

1000😅

Page 13: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Howmanythreadswecanhave?

10000😩

Page 14: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Howmanythreadswecanhave?

100000😵

Page 15: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

CallbackstotherescueSortof…

Page 16: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Callbacks:beforefun requestToken(): Token {

// makes request for a token & waitsreturn token // returns result when received

}

1

Page 17: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Callbacks:afterfun requestTokenAsync(cb: (Token) -> Unit) {

// makes request for a token, invokes callback when done// returns immediately

}

1callback

Page 18: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Futures/Promises/RxtotherescueSortof…

Page 23: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Futures:beforefun requestTokenAsync(cb: (Token) -> Unit) {

// makes request for a token, invokes callback when done// returns immediately

}

1

Page 24: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Futures:afterfun requestTokenAsync(): Promise<Token> {

// makes request for a token// returns promise for a future result immediately

}

1future

Page 25: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

KotlincoroutinestotherescueLet’sgetreal

Page 31: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Coroutines:beforefun requestTokenAsync(): Promise<Token> {

// makes request for a token// returns promise for a future result immediately

}

1

Page 32: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Coroutines:aftersuspend fun requestToken(): Token {

// makes request for a token & suspendsreturn token // returns result when received

}

1naturalsignature

Page 33: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

• Regularloops

Bonusfeatures

for ((token, item) in list) {createPost(token, item)

}

Page 40: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

• Regularexceptionhanding

Bonusfeatures

try { createPost(token, item)

} catch (e: BadTokenException) { …

}

Page 41: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

• 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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

• Customhigher-orderfunctions

Bonusfeatures

val post = retryIO {createPost(token, item)

}

Everythinglikeinblockingcode

Page 43: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Howdoesitwork?Aquickpeekbehindthescenes

Page 44: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

IntegrationZoooffuturesonJVM

Page 52: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

interface Service {fun createPost(token: Token, item: Item): Call<Post>

}

Retrofitasync

Page 53: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

suspend fun <T> Call<T>.await(): T {…

}

Page 56: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T

Page 59: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T

Page 60: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T

Regularfunction

Inspiredbycall/cc fromScheme

Page 61: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Out-of-theboxintegrations

kotlinx-coroutines-core

jdk8

guava

nio

reactor

rx1

rx2

Page 67: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

CoroutinebuildersHowcanwestartacoroutine?

Page 68: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Launch

fun postItem(item: Item) {launch {

val token = requestToken()val post = createPost(token, item)processPost(post)

}}

coroutinebuilder

Page 75: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun postItem(item: Item) {launch {

val token = requestToken()val post = createPost(token, item)processPost(post)

}}

Fireandforget!

Returnsimmediately,coroutineworksinbackgroundthreadpool

Page 76: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun postItem(item: Item) {launch {

val token = requestToken()val post = createPost(token, item)processPost(post)

}}

Page 77: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun postItem(item: Item) {launch(UI) {

val token = requestToken()val post = createPost(token, item)processPost(post)

}}

UIContext

Justspecifythecontext

Page 78: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun postItem(item: Item) {launch(UI) {

val token = requestToken()val post = createPost(token, item)processPost(post)

}}

UIContext

AnditgetsexecutedonUIthread

Page 79: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Where’sthemagicoflaunch?

Page 80: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit

): Job { … }

Aregularfunction

Page 81: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit

): Job { … } suspendinglambda

Page 82: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

fun launch(context: CoroutineContext = DefaultDispatcher,block: suspend () -> Unit

): Job { … }

Page 83: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

async /awaitTheclassicapproach

Page 84: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Whynoawait keywordinKotlin?

Theproblemwithasync

requestToken() VALID –>producesTask<Token>

await requestToken() VALID –>producesToken

concurrentbehavior

sequentialbehavior

C#

C#

default

ConcurrencyishardConcurrencyhastobeexplicit

Page 90: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlinsuspendingfunctionsaredesignedtoimitatesequential behavior

bydefault

ConcurrencyishardConcurrencyhastobeexplicit

Page 91: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

KotlinapproachtoasyncConcurrencywhereyouneedit

Page 92: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Use-caseforasync

async Task<Image> loadImageAsync(String name) { … } C#

Page 93: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Use-caseforasync

var promise1 = loadImageAsync(name1);var promise2 = loadImageAsync(name2);

async Task<Image> loadImageAsync(String name) { … }

Startmultipleoperationsconcurrently

C#

Page 94: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlinasync function

fun loadImageAsync(name: String): Deferred<Image> = async { … }

Kotlin

Page 97: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlinasync function

fun loadImageAsync(name: String): Deferred<Image> = async { … }

Aregularfunction

Kotlin

Page 98: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlinasync function

fun loadImageAsync(name: String): Deferred<Image> = async { … }

Kotlin’s futuretype

Kotlin

Page 99: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlinasync function

fun loadImageAsync(name: String): Deferred<Image> = async { … }

async coroutinebuilder

Kotlin

Page 100: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Usingasync functionwhenneeded

suspend fun loadImage(name: String): Image { … }

Isdefinedassuspendingfunction,notasync

Page 104: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlin approachtoasync

requestToken() VALID –>producesToken

async { requestToken() } VALID –>producesDeferred<Token>

sequentialbehavior

concurrentbehavior

Kotlin

Kotlin

default

Page 109: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Whatarecoroutinesconceptually?

Page 110: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Whatarecoroutinesconceptually?Coroutinesarelikevery light-weightthreads

Page 111: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

JavainteropCanweuseKotlincoroutineswithJavacode?

Page 122: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Javainterop

CompletableFuture<Image> loadImageAsync(String name) { … }Java

Page 123: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

CompletableFuture<Image> loadImageAsync(String name) { … }

CompletableFuture<Image> loadAndCombineAsync(String name1, String name2)

Java

ImagineimplementingitinJava…

Page 124: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

CompletableFuture<Image> loadImageAsync(String name) { … }Java

fun loadAndCombineAsync(name1: String, name2: String

): CompletableFuture<Image> =…

Kotlin

Page 126: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

BeyondasynchronouscodeKotlin’s approachtogenerate/yield– synchronouscoroutines

Page 131: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Fibonaccisequence

val fibonacci: Sequence<Int> = …

Page 132: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Fibonaccisequence

val fibonacci = buildSequence {var cur = 1var next = 1while (true) {

yield(cur) val tmp = cur + nextcur = nextnext = tmp

}}

Page 133: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Thesamebuildingblocks

public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit

): Sequence<T> { … }

Page 136: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Thesamebuildingblocks

public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit

): Sequence<T> { … }

Resultisasynchronous sequence

Page 137: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Thesamebuildingblocks

public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit

): Sequence<T> { … }

Suspendinglambdawithreceiver

Page 138: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

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 - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

LibraryvsLanguageKeepingthecorelanguagesmall

Page 140: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Classicasync

async/awaitgenerate/yield Keywords

Page 141: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlincoroutines

suspend Modifier

Page 142: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlincoroutines

Standardlibrary

Page 143: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Kotlincoroutines

Standardlibrary

kotlinx-coroutines

launch,async,runBlocking,future,delay,

Job,Deferred,etc

http://github.com/kotlin/kotlinx.coroutines

Page 144: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

ExperimentalinKotlin1.1&1.2

Coroutinescanbeused inproduction

Backwardscompatibleinside1.1&1.2

Tobefinalizedinthefuture

Page 145: Fresh Async With Kotlin - QCon San Francisco · Fresh Async With Kotlin Presented at QConSF, 2017 /Roman Elizarov @ JetBrains. Speaker: Roman Elizarov •16+ years experience •Previously

Thankyou

Anyquestions?

Slidesareavailableatwww.slideshare.net/elizarovemailmetoelizarov atgmail

relizarov