deep dive into coroutines on jvm
play

Deep dive into Coroutines on JVM Roman Elizarov elizarov at - PowerPoint PPT Presentation

Deep dive into Coroutines on JVM Roman Elizarov elizarov at JetBrains There is no magic Continuation Passing Style (CPS) A toy problem fun postItem(item: Item) { val token = requestToken () val post = createPost (token, item) processPost


  1. Install callback 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) } }) }

  2. Analyze response 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) } }) }

  3. Analyze response 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’s all

  4. Out-of-the box integrations reactor guava jdk8 rx2 rx1 nio kotlinx-coroutines-core Contributions are welcome

  5. Coroutine context

  6. What thread it resumes on? suspend fun postItem(item: Item) { val token = requestToken () val post = createPost (token, item) processPost (post) Continuation } It depends!

  7. What thread it resumes on? fun postItem(item: Item) { launch (UI) { val token = requestToken () val post = createPost (token, item) processPost (post) Continuation } }

  8. Continuation Interceptor interface ContinuationInterceptor : CoroutineContext.Element { companion object Key : CoroutineContext.Key<ContinuationInterceptor> fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> }

  9. Continuation Interceptor interface ContinuationInterceptor : CoroutineContext.Element { companion object Key : CoroutineContext.Key<ContinuationInterceptor> fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> }

  10. Continuation Interceptor interface ContinuationInterceptor : CoroutineContext.Element { companion object Key : CoroutineContext.Key<ContinuationInterceptor> fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> }

  11. 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

  12. Starting coroutines

  13. Coroutine builder fun <T> future( context: CoroutineContext = DefaultDispatcher , block: suspend () -> T ): CompletableFuture<T>

  14. A regular function fun <T> future( context: CoroutineContext = DefaultDispatcher , block: suspend () -> T ): CompletableFuture<T>

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

  16. fun <T> future( context: CoroutineContext = DefaultDispatcher , block: suspend () -> T ): CompletableFuture<T> suspending lambda

  17. fun <T> future( context: CoroutineContext = DefaultDispatcher , block: suspend () -> T ): CompletableFuture<T> { val future = CompletableFuture<T>() block. startCoroutine (…) return future }

  18. fun <T> future( context: CoroutineContext = DefaultDispatcher , block: suspend () -> T ): CompletableFuture<T> { val future = CompletableFuture<T>() block. startCoroutine (…) return future }

  19. fun <T> future( context: CoroutineContext = DefaultDispatcher , block: suspend () -> T ): CompletableFuture<T> { val future = CompletableFuture<T>() block. startCoroutine (completion = object : Continuation<T> { … }) return future }

  20. 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 }

  21. 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) } }) That’s all, folks! return future }

  22. Job cancellation

  23. Launch coroutine builder fun launch( context: CoroutineContext = DefaultDispatcher, block: suspend () -> Unit ): Job { … }

  24. Launching coroutine val job = launch { … }

  25. val job = launch { … } job.join()

  26. val job = launch { … } job.join() job.cancel()

  27. Job interface Job : CoroutineContext.Element { companion object Key : CoroutineContext.Key<Job> … }

  28. Using coroutine context launch { val job = coroutineContext [Job]!! … }

  29. Using coroutine context launch { val job = coroutineContext [Job]!! val interceptor = coroutineContext [CoroutineInterceptor]!! … }

  30. Timeouts launch { withTimeout (10, TimeUnit. SECONDS ) { … } }

  31. Cooperative cancellation

  32. Cooperative cancellation launch { while ( true ) { … } }

  33. Cooperative cancellation launch { while ( isActive ) { … } }

  34. Cooperative cancellation launch { while ( true ) { delay (…) … } }

  35. Cancellable suspension suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont -> enqueue( … ) }

  36. Cancellable continuation suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> -> enqueue( … ) }

  37. Completion handler suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> -> enqueue( … ) cont.invokeOnCompletion { this @await.cancel() } }

  38. Completion handler suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> -> enqueue( … ) cont.invokeOnCompletion { this @await.cancel() } }

  39. Communicating Sequential Processes (CSP)

  40. Shared Mutable State @stefanobaghino

  41. The choice Shared Share by Mutable State Communicating

  42. Example fun 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) } } }

  43. Main coroutine fun 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) } } }

  44. Channel fun 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) } } }

  45. Launch fun main(args: Array<String>) = runBlocking <Unit> { val chan = Channel <Int>() launch ( coroutineContext ) { repeat (10) { i -> delay (100) chan.send(i) Child coroutine } chan.close() } launch ( coroutineContext ) { for (i in chan) { println (i) } } }

  46. Coroutine body fun main(args: Array<String>) = runBlocking <Unit> { val chan = Channel <Int>() launch ( coroutineContext ) { repeat (10) { i -> delay (100) chan.send(i) Sequential code! } chan.close() } launch ( coroutineContext ) { for (i in chan) { println (i) } } }

  47. Send fun 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) } } }

  48. Close fun 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) } } }

  49. Receive for loop fun 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) } } }

  50. Demo

  51. Actors The other way to look at CSP

  52. The choice Named Named channels coroutines Actor == named coroutine & inbox channel

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend