Like almost 15 years ago, we created tools to convert the diagrams logic to c++ using this context/label approach to mimic the multi-threads to handle the concurrent calls in the telecommunication systems.
Nice talk. Unfortunately it leaves me with more questions than answers. Just to name a few: 1) Coroutines need to be "hooked up" somewhere. In JavaScript, it's the browser itself. In Kotlin, I would assume that there is some static "context holder"object to which every new coroutine is passed, such that it can be triggered from there once the continuation condition is met. Where is this central static place? 2) How exactly does the "delay(...)" function work? To my knowledge, you cannot delay anything in Java per se, except by either burning CPU cycles with busy waiting, using Thread.sleep() or Object.wait() / Object.notify(). How exactly does this work? 3) If you invoke an inherently blocking operation from a given API (e.g. load text from file), how do you do so without "sacrificing" a thread that is being blocked? The coroutines claim that they can do hundreds of thousands of such operations, without each of them requiring a thread. Which bears the question: how? Roman said that there is no magic involved. It still looks like plenty of magic to me.
1) As far as I know, it's in Kotlin coroutines library. 2) If there is something to do, executor can put your coroutine aside and do something for another coroutine. 3) There are non-blocking counterparts for IO operations en.wikipedia.org/wiki/Non-blocking_I/O_(Java)
Check the doc here: github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md To me, Kotlin's coroutine design models Go's very closely (I am a Go developer).
@Alan You are right on 3. The thread will be blocked. Coroutines will not help. And this is same in any other library. Coroutines just gives you an easy syntax to compose multiple asynchronous tasks together.
By "hooked up somewhere", did you mean executing somewhere, like JS message queue? In 12:35, he says that state/closure object is reused. The state instance is passed around. So it doesn't need a central queue to process. I agree that the stack will grow very very quickly, but the actual memory used is not that much, just references. Full disclosure: I'm like 20min into coroutine, and 1-2 month into JS.
2) I think that the implementations on how `delay` works is provided by the underlying Dispatcher. Dispatchers.IO might use a thread pool (of a specific size). Same for Dispatchers.Default, Dispatchers.Main (main thread in android) will probably just post something into the event queue/loop with a delay. A single threaded dispatchers might do something similar (event queue)
No, launch() returns immediately, and the next line will be executed after it returns, which would be cancel() if it was called first, which would cancel the asynchronous work that was started in the coroutine. By calling join() first, we wait until the coroutine is finished before we cancel it.
I don't like it, seems like overengineering to me. It looks the same as the other approaches - async/await, Futures, callbacks,...done over again in a more confusing way :S In his other presentation, he said asynchronous code needs to be explicit to be understood and handled well. All I get from coroutines is a headache. I would much rather create my own thread pool manually and submit Runnables to it, catching exceptions by myself. That or use the C# style with async and await, that looks much simpler :)
Another valuable resource for learning about how coroutines work in-depth, is the talk from its co-creator, Roman Elizarov from 2017. ua-cam.com/video/YrrUCSi72E8/v-deo.html
"suspend" and "await" are two different things. Suspend is modifying your function to be capable of suspending its execution via continuations. Await, on the other hand, describes that a detached asynchronous process is being awaited for by my code. For example, I launched multiple network requests in parallel but my function needs to (a)wait for their values before it can continue so, therefore, my function SUSPENDS and AWAITs for the asynchronous values to become available before resuming execution. They may be new to those that don't have much experience in asynchronous execution paradigms, but they describe exactly what's going on. These keywords weren't invented by the Kotlin language team, just used to accurately describe what the code is doing. Good reads on why "suspend" is accurate: > Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be SUSPENDED and resumed. en.wikipedia.org/wiki/Coroutine Good reads on why "await" is accurate: > While await and wait are similar in terms of meaning, they differ in usage. > • Wait can be used without an object, like in the sentence I am waiting. > • Await, meanwhile, requires an object. writingexplained.org/awaiting-vs-waiting-difference > In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function. en.wikipedia.org/wiki/Async/await
Continuation Passing Style (CPS) [2:06]
Direct Style [2:33]
Continuation-Passing Style [3:08]
CPS == Callbacks
Coroutines Direct Style [3:52]
How does it work? [4:15]
Kotlin suspending functions [4:27]
CPS Transformation [4:36]
Continuation [5:03]
Direct to CPS [6:16]
Direct code [6:28]
Continuations [6:34]
Callbacks? [7:01]
Labels [7:21]
State [8:11]
CPS Transform [8:38]
Save state [9:15]
Callback [9:44]
Restore state [10:53]
Continue [11:18]
State Machine vs Callbacks [11:39]
SM: Reuse closure/state object
CB: Create new closure
(C#, JavaScript do it in state machines)
SM: Easy loops and higher-order functions
Integration [13:37]
Zoo of futures on JVM [13:55]
Callbacks everywhere [15:44]
Install callback [18:05]
Analyze response [18:25]
Out-of-the box integrations [19:14]
Coroutine context [20:23]
What thread it resumes on? [21:14]
Continuation Interceptor [22:42]
Dispatched continuation [23:45]
Starting coroutines [24:36]
Coroutine builder [25:00]
Job cancellation [28:17]
Launch coroutine builder [29:24]
Launching coroutine [29:38]
Job [29:58]
Using coroutine context [30:07]
Timeouts [30:53]
Cooperative cancellation [31:21]
(Java Thread.stop() story ~[33:15])
(example) [33:29]
while (isActive)
delay()
Cancellable suspension [34:32]
Cancellable continuation [35:08]
Completion handler [35:15]
Communicating Sequential Processes (CSP) [36:32]
Shared Mutable State [37:29]
The choice [37:47]
Example [38:53]
(Channel)
Demo [41:06] (failed)
Actors [42:19]
The choice [42:34]
CSP -> named channels
Actor -> named coroutine & inbox channel
Example [43:26]
References [44:44]
Guide to kotlinx.coroutines by example
github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
This is a fantastic talk. Roman is super smart and is good at explaining things simply.
Very well done, seems that with Kotlin the official explanation is usually the simplest and best :)
I liked this talk. The lecturer explains not only how to program, but also how things work, and in a step by step manner.
My feeling while watching this video:
The world is full of genius people. It's an amazing feeling to live with them.
Roman Elizarov.....This was awesome discussion...i enjoyed every little explaination of CPS and coroutines internal working.
Excellent talk! Presents complex topics in an accessible manner, with well thought out transitions from concept to concept.
Like almost 15 years ago, we created tools to convert the diagrams logic to c++ using this context/label approach to mimic the multi-threads to handle the concurrent calls in the telecommunication systems.
Brilliant talk ! Loved it ! Makes it all very clear
Nice talk. Unfortunately it leaves me with more questions than answers. Just to name a few:
1) Coroutines need to be "hooked up" somewhere. In JavaScript, it's the browser itself. In Kotlin, I would assume that there is some static "context holder"object to which every new coroutine is passed, such that it can be triggered from there once the continuation condition is met. Where is this central static place?
2) How exactly does the "delay(...)" function work? To my knowledge, you cannot delay anything in Java per se, except by either burning CPU cycles with busy waiting, using Thread.sleep() or Object.wait() / Object.notify(). How exactly does this work?
3) If you invoke an inherently blocking operation from a given API (e.g. load text from file), how do you do so without "sacrificing" a thread that is being blocked? The coroutines claim that they can do hundreds of thousands of such operations, without each of them requiring a thread. Which bears the question: how?
Roman said that there is no magic involved. It still looks like plenty of magic to me.
1) As far as I know, it's in Kotlin coroutines library.
2) If there is something to do, executor can put your coroutine aside and do something for another coroutine.
3) There are non-blocking counterparts for IO operations en.wikipedia.org/wiki/Non-blocking_I/O_(Java)
Check the doc here: github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md To me, Kotlin's coroutine design models Go's very closely (I am a Go developer).
@Alan You are right on 3. The thread will be blocked. Coroutines will not help. And this is same in any other library. Coroutines just gives you an easy syntax to compose multiple asynchronous tasks together.
By "hooked up somewhere", did you mean executing somewhere, like JS message queue? In 12:35, he says that state/closure object is reused. The state instance is passed around. So it doesn't need a central queue to process. I agree that the stack will grow very very quickly, but the actual memory used is not that much, just references. Full disclosure: I'm like 20min into coroutine, and 1-2 month into JS.
2) I think that the implementations on how `delay` works is provided by the underlying Dispatcher. Dispatchers.IO might use a thread pool (of a specific size). Same for Dispatchers.Default, Dispatchers.Main (main thread in android) will probably just post something into the event queue/loop with a delay. A single threaded dispatchers might do something similar (event queue)
Amazing, it makes things clearer to me.
Sometimes we don't have idea how things works behind the hood.
I think `cancel` should be called before `join`? at 29:50
No, launch() returns immediately, and the next line will be executed after it returns, which would be cancel() if it was called first, which would cancel the asynchronous work that was started in the coroutine. By calling join() first, we wait until the coroutine is finished before we cancel it.
Legendary talk
insightful and very easy to comprehend talk. thanks
good explanation 👍
where to find the slides
Try this link: www.slideshare.net/elizarov/deep-dive-into-coroutines-on-jvm-kotlinconf-2017
They are all linked on kotlinconf.com/talks/
Great explanation. Thanks!
I don't like it, seems like overengineering to me. It looks the same as the other approaches - async/await, Futures, callbacks,...done over again in a more confusing way :S In his other presentation, he said asynchronous code needs to be explicit to be understood and handled well. All I get from coroutines is a headache. I would much rather create my own thread pool manually and submit Runnables to it, catching exceptions by myself. That or use the C# style with async and await, that looks much simpler :)
Another valuable resource for learning about how coroutines work in-depth, is the talk from its co-creator, Roman Elizarov from 2017. ua-cam.com/video/YrrUCSi72E8/v-deo.html
45:17
good stuff
kotlin coroutine has dumb naming. "suspend" and then "await()". Hella dumb.
"suspend" and "await" are two different things.
Suspend is modifying your function to be capable of suspending its execution via continuations. Await, on the other hand, describes that a detached asynchronous process is being awaited for by my code. For example, I launched multiple network requests in parallel but my function needs to (a)wait for their values before it can continue so, therefore, my function SUSPENDS and AWAITs for the asynchronous values to become available before resuming execution.
They may be new to those that don't have much experience in asynchronous execution paradigms, but they describe exactly what's going on. These keywords weren't invented by the Kotlin language team, just used to accurately describe what the code is doing.
Good reads on why "suspend" is accurate:
> Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be SUSPENDED and resumed.
en.wikipedia.org/wiki/Coroutine
Good reads on why "await" is accurate:
> While await and wait are similar in terms of meaning, they differ in usage.
> • Wait can be used without an object, like in the sentence I am waiting.
> • Await, meanwhile, requires an object.
writingexplained.org/awaiting-vs-waiting-difference
> In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function.
en.wikipedia.org/wiki/Async/await
37:27