deep dive into coroutines on jvm @ kotlinconf 2017

107
elizarov at JetBrains Roman Elizarov Deep dive into Coroutines on JVM

Upload: roman-elizarov

Post on 21-Jan-2018

567 views

Category:

Technology


9 download

TRANSCRIPT

Page 1: Deep dive into Coroutines on JVM @ KotlinConf 2017

elizarov at JetBrainsRoman Elizarov

Deep dive into Coroutines on JVM

Page 2: Deep dive into Coroutines on JVM @ KotlinConf 2017

There is no magic

Page 3: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation Passing Style (CPS)

Page 4: Deep dive into Coroutines on JVM @ KotlinConf 2017

A toy problem

fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}Direct style

Page 5: Deep dive into Coroutines on JVM @ KotlinConf 2017

Direct style

fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}

Page 6: Deep dive into Coroutines on JVM @ KotlinConf 2017

Direct style

fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}Continuation

Page 7: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation-Passing Style

fun postItem(item: Item) {requestToken { token ->

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

}}

Continuation

CPS == Callbacks

Page 8: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation-Passing Style

fun postItem(item: Item) {requestToken { token ->

createPost(token, item) { post ->processPost(post)

}}

}

Page 9: Deep dive into Coroutines on JVM @ KotlinConf 2017

Coroutines Direct Style

suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}

Page 10: Deep dive into Coroutines on JVM @ KotlinConf 2017

How does it work?Behind the scenes

Page 11: Deep dive into Coroutines on JVM @ KotlinConf 2017

Kotlin suspending functionsKotlin

suspend fun createPost(token: Token, item: Item): Post { … }

Page 12: Deep dive into Coroutines on JVM @ KotlinConf 2017

CPS Transformation

Java/JVM

suspend fun createPost(token: Token, item: Item): Post { … }

Object createPost(Token token, Item item, Continuation<Post> cont) { … }

Page 13: Deep dive into Coroutines on JVM @ KotlinConf 2017

CPS Transformation

callbackJava/JVM

suspend fun createPost(token: Token, item: Item): Post { … }

Object createPost(Token token, Item item, Continuation<Post> cont) { … }

Page 14: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation

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 15: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation

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 16: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation

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 17: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation

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 18: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation

Continuation is a generic callback interface

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 19: Deep dive into Coroutines on JVM @ KotlinConf 2017

Direct to CPS

Page 20: Deep dive into Coroutines on JVM @ KotlinConf 2017

Direct code

suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}

Page 21: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuations

suspend fun postItem(item: Item) {

val token = requestToken()

val post = createPost(token, item)

processPost(post)}

Initial continuation

Page 22: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuations

suspend fun postItem(item: Item) {

val token = requestToken()

val post = createPost(token, item)

processPost(post)}

Continuation

Page 23: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuations

suspend fun postItem(item: Item) {

val token = requestToken()

val post = createPost(token, item)

processPost(post)} Continuation

Convert to CPS?

Page 24: Deep dive into Coroutines on JVM @ KotlinConf 2017

Callbacks?

fun postItem(item: Item) {

requestToken { token ->

createPost(token, item) { post ->

processPost(post)

}}

}

Page 25: Deep dive into Coroutines on JVM @ KotlinConf 2017

Labels

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

val token = requestToken()// LABEL 1

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

processPost(post)}

Page 26: Deep dive into Coroutines on JVM @ KotlinConf 2017

Labels

suspend fun postItem(item: Item) {switch (label) {case 0:

val token = requestToken()case 1:

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

processPost(post)}

}

Page 27: Deep dive into Coroutines on JVM @ KotlinConf 2017

suspend fun postItem(item: Item) {val sm = object : CoroutineImpl { … }switch (sm.label) {case 0:

val token = requestToken()case 1:

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

processPost(post)}

}

State

Page 28: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = object : CoroutineImpl { … }switch (sm.label) {case 0:

requestToken(sm)case 1:

createPost(token, item, sm)case 2:

processPost(post)}

}

CPS Transform

Page 29: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = …switch (sm.label) {case 0:

sm.item = itemsm.label = 1requestToken(sm)

case 1:createPost(token, item, sm)

case 2:processPost(post)

}}

Save state

Page 30: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = object : CoroutineImpl { … }switch (sm.label) {case 0:

sm.item = itemsm.label = 1requestToken(sm)

case 1:createPost(token, item, sm)

case 2:processPost(post)

}}

Callback

State Machine as Continuation

Page 31: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = object : CoroutineImpl {

fun resume(…) {postItem(null, this)

}}switch (sm.label) {case 0:

sm.item = itemsm.label = 1requestToken(sm)

case 1:createPost(token, item, sm)

…}

Callback

Page 32: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = cont as? ThisSM ?: object : ThisSM {

fun resume(…) {postItem(null, this)

}}switch (sm.label) {case 0:

sm.item = itemsm.label = 1requestToken(sm)

case 1:createPost(token, item, sm)

…}

Callback

Page 33: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = …switch (sm.label) {case 0:

sm.item = itemsm.label = 1requestToken(sm)

case 1:val item = sm.itemval token = sm.result as Tokensm.label = 2createPost(token, item, sm)

…}

Restore state

Page 34: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun postItem(item: Item, cont: Continuation) {val sm = …switch (sm.label) {case 0:

sm.item = itemsm.label = 1requestToken(sm)

case 1:val item = sm.itemval token = sm.result as Tokensm.label = 2createPost(token, item, sm)

…}

Continue

Page 35: Deep dive into Coroutines on JVM @ KotlinConf 2017

State Machine vs Callbacks

fun postItem(item: Item) {requestToken { token ->

createPost(token, item) { post ->processPost(post)

}}

}

suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}

Page 36: Deep dive into Coroutines on JVM @ KotlinConf 2017

State Machine vs Callbacks

fun postItem(item: Item) {requestToken { token ->

createPost(token, item) { post ->processPost(post)

}}

}

suspend fun postItem(item: Item) {val token = requestToken()val post = createPost(token, item)processPost(post)

}

Reuse closure / state object

Create new closure

Page 37: Deep dive into Coroutines on JVM @ KotlinConf 2017

State Machine vs Callbackssuspend fun postItems(items: List<Item>) {

for (item in items) {val token = requestToken()val post = createPost(token, item)processPost(post)

}}

Easy loops and higher-order functions

Page 38: Deep dive into Coroutines on JVM @ KotlinConf 2017

State Machine vs Callbacks

fun postItems(items: List<Item>) {…

}

suspend fun postItems(items: List<Item>) {for (item in items) {

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

}}

A horrid callback mess

Easy loops and higher-order functions

Page 39: Deep dive into Coroutines on JVM @ KotlinConf 2017

Integration

Page 40: Deep dive into Coroutines on JVM @ KotlinConf 2017

Zoo of futures on JVM

Page 41: Deep dive into Coroutines on JVM @ KotlinConf 2017

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

}

Page 42: Deep dive into Coroutines on JVM @ KotlinConf 2017

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

}

suspend fun createPost(token: Token, item: Item): Post =serviceInstance.createPost(token, item).await()

Page 43: Deep dive into Coroutines on JVM @ KotlinConf 2017

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

}

Page 44: Deep dive into Coroutines on JVM @ KotlinConf 2017

Callbacks everywheresuspend 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 45: Deep dive into Coroutines on JVM @ KotlinConf 2017

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 46: Deep dive into Coroutines on JVM @ KotlinConf 2017

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

Page 47: Deep dive into Coroutines on JVM @ KotlinConf 2017

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

Regular function

Inspired by call/cc from Scheme

Page 48: Deep dive into Coroutines on JVM @ KotlinConf 2017

Install callbacksuspend 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()!!)

elsecont.resumeWithException(ErrorResponse(response))

}

override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)

}})

}

Page 49: Deep dive into Coroutines on JVM @ KotlinConf 2017

Install callbacksuspend 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()!!)

elsecont.resumeWithException(ErrorResponse(response))

}

override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)

}})

}

Page 50: Deep dive into Coroutines on JVM @ KotlinConf 2017

Analyze responsesuspend 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()!!)

elsecont.resumeWithException(ErrorResponse(response))

}

override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)

}})

}

Page 51: Deep dive into Coroutines on JVM @ KotlinConf 2017

Analyze responsesuspend 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()!!)

elsecont.resumeWithException(ErrorResponse(response))

}

override fun onFailure(call: Call<T>, t: Throwable) {cont.resumeWithException(t)

}})

}That’s all

Page 52: Deep dive into Coroutines on JVM @ KotlinConf 2017

Out-of-the box integrations

kotlinx-coroutines-core

jdk8

guava

nio

reactor

rx1

rx2

Contributions are welcome

Page 53: Deep dive into Coroutines on JVM @ KotlinConf 2017

Coroutine context

Page 54: Deep dive into Coroutines on JVM @ KotlinConf 2017

What thread it resumes on?

suspend fun postItem(item: Item) {

val token = requestToken()

val post = createPost(token, item)

processPost(post)}

Continuation

It depends!

Page 55: Deep dive into Coroutines on JVM @ KotlinConf 2017

What thread it resumes on?

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

val token = requestToken()

val post = createPost(token, item)

processPost(post)}

}

Continuation

Page 56: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation Interceptorinterface ContinuationInterceptor : CoroutineContext.Element {

companion object Key : CoroutineContext.Key<ContinuationInterceptor>

fun <T> interceptContinuation(continuation: Continuation<T>):Continuation<T>

}

Page 57: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation Interceptorinterface ContinuationInterceptor : CoroutineContext.Element {

companion object Key : CoroutineContext.Key<ContinuationInterceptor>

fun <T> interceptContinuation(continuation: Continuation<T>):Continuation<T>

}

Page 58: Deep dive into Coroutines on JVM @ KotlinConf 2017

Continuation Interceptorinterface ContinuationInterceptor : CoroutineContext.Element {

companion object Key : CoroutineContext.Key<ContinuationInterceptor>

fun <T> interceptContinuation(continuation: Continuation<T>):Continuation<T>

}

Page 59: Deep dive into Coroutines on JVM @ KotlinConf 2017

Dispatched continuation

class DispatchedContinuation<in T>(val dispatcher: CoroutineDispatcher,val continuation: Continuation<T>

): Continuation<T> by continuation {

override fun resume(value: T) {dispatcher.dispatch(context, DispatchTask(…))

}

…} Dispatches execution to another thread

Page 60: Deep dive into Coroutines on JVM @ KotlinConf 2017

Starting coroutines

Page 61: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T>

Coroutine builder

Page 62: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T>

A regular function

Page 63: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T>

Page 64: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T> suspending lambda

Page 65: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T> {val future = CompletableFuture<T>()block.startCoroutine(…)return future

}

Page 66: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T> {val future = CompletableFuture<T>()block.startCoroutine(…)return future

}

Page 67: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(context: CoroutineContext = DefaultDispatcher,block: suspend () -> T

): CompletableFuture<T> {val future = CompletableFuture<T>()block.startCoroutine(completion = object : Continuation<T> {

…})return future

}

Page 68: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(…): CompletableFuture<T> {val future = CompletableFuture<T>()block.startCoroutine(completion = object : Continuation<T> {

override val context: CoroutineContext get() = context

override fun resume(value: T) {future.complete(value)

}

override fun resumeWithException(exception: Throwable) {future.completeExceptionally(exception)

}})return future

}

Page 69: Deep dive into Coroutines on JVM @ KotlinConf 2017

fun <T> future(…): CompletableFuture<T> {val future = CompletableFuture<T>()block.startCoroutine(completion = object : Continuation<T> {

override val context: CoroutineContext get() = context

override fun resume(value: T) {future.complete(value)

}

override fun resumeWithException(exception: Throwable) {future.completeExceptionally(exception)

}})return future

}That’s all, folks!

Page 70: Deep dive into Coroutines on JVM @ KotlinConf 2017

Job cancellation

Page 71: Deep dive into Coroutines on JVM @ KotlinConf 2017

Launch coroutine builderfun launch(

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

): Job { … }

Page 72: Deep dive into Coroutines on JVM @ KotlinConf 2017

Launching coroutineval job = launch {

…}

Page 73: Deep dive into Coroutines on JVM @ KotlinConf 2017

val job = launch { …

}

job.join()

Page 74: Deep dive into Coroutines on JVM @ KotlinConf 2017

val job = launch { …

}

job.join()job.cancel()

Page 75: Deep dive into Coroutines on JVM @ KotlinConf 2017

Jobinterface Job : CoroutineContext.Element {

companion object Key : CoroutineContext.Key<Job>

…}

Page 76: Deep dive into Coroutines on JVM @ KotlinConf 2017

Using coroutine contextlaunch {

val job = coroutineContext[Job]!!…

}

Page 77: Deep dive into Coroutines on JVM @ KotlinConf 2017

Using coroutine contextlaunch {

val job = coroutineContext[Job]!!val interceptor = coroutineContext[CoroutineInterceptor]!!…

}

Page 78: Deep dive into Coroutines on JVM @ KotlinConf 2017

Timeoutslaunch {

withTimeout(10, TimeUnit.SECONDS) {…

}}

Page 79: Deep dive into Coroutines on JVM @ KotlinConf 2017

Cooperative cancellation

Page 80: Deep dive into Coroutines on JVM @ KotlinConf 2017

Cooperative cancellationlaunch {

while (true) {…

}}

Page 81: Deep dive into Coroutines on JVM @ KotlinConf 2017

Cooperative cancellationlaunch {

while (isActive) {…

}}

Page 82: Deep dive into Coroutines on JVM @ KotlinConf 2017

Cooperative cancellationlaunch {

while (true) {delay(…)…

}}

Page 83: Deep dive into Coroutines on JVM @ KotlinConf 2017

Cancellable suspensionsuspend fun <T> Call<T>.await(): T =

suspendCancellableCoroutine { cont ->enqueue(…)

}

Page 84: Deep dive into Coroutines on JVM @ KotlinConf 2017

Cancellable continuationsuspend fun <T> Call<T>.await(): T =

suspendCancellableCoroutine { cont: CancellableContinuation<T> ->enqueue(…)

}

Page 85: Deep dive into Coroutines on JVM @ KotlinConf 2017

Completion handlersuspend fun <T> Call<T>.await(): T =

suspendCancellableCoroutine { cont: CancellableContinuation<T> ->enqueue(…)cont.invokeOnCompletion {

[email protected]()}

}

Page 86: Deep dive into Coroutines on JVM @ KotlinConf 2017

Completion handlersuspend fun <T> Call<T>.await(): T =

suspendCancellableCoroutine { cont: CancellableContinuation<T> ->enqueue(…)cont.invokeOnCompletion {

[email protected]()}

}

Page 87: Deep dive into Coroutines on JVM @ KotlinConf 2017

Communicating Sequential Processes (CSP)

Page 88: Deep dive into Coroutines on JVM @ KotlinConf 2017

Shared Mutable State

@stefanobaghino

Page 89: Deep dive into Coroutines on JVM @ KotlinConf 2017

The choice

SharedMutable State

Share by Communicating

Page 90: Deep dive into Coroutines on JVM @ KotlinConf 2017

Examplefun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Page 91: Deep dive into Coroutines on JVM @ KotlinConf 2017

Main coroutinefun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Page 92: Deep dive into Coroutines on JVM @ KotlinConf 2017

Channelfun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Page 93: Deep dive into Coroutines on JVM @ KotlinConf 2017

Launchfun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Child coroutine

Page 94: Deep dive into Coroutines on JVM @ KotlinConf 2017

Coroutine bodyfun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Sequential code!

Page 95: Deep dive into Coroutines on JVM @ KotlinConf 2017

Sendfun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Page 96: Deep dive into Coroutines on JVM @ KotlinConf 2017

Closefun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Page 97: Deep dive into Coroutines on JVM @ KotlinConf 2017

Receive for loopfun main(args: Array<String>) = runBlocking<Unit> {

val chan = Channel<Int>()launch(coroutineContext) {

repeat(10) { i ->delay(100)chan.send(i)

}chan.close()

}launch(coroutineContext) {

for (i in chan) {println(i)

}}

}

Page 98: Deep dive into Coroutines on JVM @ KotlinConf 2017

Demo

Page 99: Deep dive into Coroutines on JVM @ KotlinConf 2017

ActorsThe other way to look at CSP

Page 100: Deep dive into Coroutines on JVM @ KotlinConf 2017

The choice

Named channels

Namedcoroutines

Actor == named coroutine & inbox channel

Page 101: Deep dive into Coroutines on JVM @ KotlinConf 2017

Examplefun main(args: Array<String>) = runBlocking<Unit> {

val printer = actor<Int>(coroutineContext) {for (i in channel) {

println(i)}

}launch(coroutineContext) {

repeat(10) { i ->delay(100)printer.send(i)

}printer.close()

}}

Page 102: Deep dive into Coroutines on JVM @ KotlinConf 2017

Actor coroutine builderfun main(args: Array<String>) = runBlocking<Unit> {

val printer = actor<Int>(coroutineContext) {for (i in channel) {

println(i)}

}launch(coroutineContext) {

repeat(10) { i ->delay(100)printer.send(i)

}printer.close()

}}

Page 103: Deep dive into Coroutines on JVM @ KotlinConf 2017

Actor bodyfun main(args: Array<String>) = runBlocking<Unit> {

val printer = actor<Int>(coroutineContext) {for (i in channel) {

println(i)}

}launch(coroutineContext) {

repeat(10) { i ->delay(100)printer.send(i)

}printer.close()

}}

Sequential!

Page 104: Deep dive into Coroutines on JVM @ KotlinConf 2017

Interacting with an actorfun main(args: Array<String>) = runBlocking<Unit> {

val printer = actor<Int>(coroutineContext) {for (i in channel) {

println(i)}

}launch(coroutineContext) {

repeat(10) { i ->delay(100)printer.send(i)

}printer.close()

}}

Page 105: Deep dive into Coroutines on JVM @ KotlinConf 2017

References

Page 106: Deep dive into Coroutines on JVM @ KotlinConf 2017

Guide to kotlinx.coroutinesby example

https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md

• Basics• Cancellation and Timeouts• Composition• Coroutine contexts• Channels• Shared Mutable State and Concurrency• Select expressions

Page 107: Deep dive into Coroutines on JVM @ KotlinConf 2017

#kotlinconf17

relizarovelizarov at JetBrains

Roman Elizarov

Thank you

Any questions?