update: update docs for the new WebHelp engine (#2393)
* update: update cancellation-and-timeouts.md
* update: update channels.md
* update: update composing-suspending-functions.md
* update: update coroutine-context-and-dispatchers.md
* update: update coroutines-guide.md
* update: update exception-handling.md
* update: update select-expression.md
* update: update shared-mutable-state-and-concurrency.md
* update: update basics.md
* update: update flow.md
* update: update flow.md
* update: update _nav.yml
* update: add _nav.tree
* update: update links
* update: fixes after review
* update: get rid of divs
* update: add new lines for WebHelp parser
* update: add new lines for WebHelp parser
* fix: fix knit errors
* removed _nav.yml;
* renamed _nav.tree to kc.tree.
* removed coroutines overview from the list; a title for a hands-on tutorial
* update: Made kc.tree as valid XML
* update: added a configuration file project.ihp
* update: added a configuration file buildprofiles.xml
* update: moved coroutines overview from the main repository
* update: update cancellation-and-timeouts.md
* update: update channels.md
* update: update composing-suspending-functions.md
* update: update coroutine-context-and-dispatchers.md
* update: update coroutines-guide.md
* update: update exception-handling.md
* update: update select-expression.md
* update: update shared-mutable-state-and-concurrency.md
* update: update basics.md
* update: update flow.md
* update: update flow.md
* update: update _nav.yml
* update: add _nav.tree
* update: update links
* update: fixes after review
* update: get rid of divs
* removed _nav.yml;
* renamed _nav.tree to kc.tree.
* removed coroutines overview from the list; a title for a hands-on tutorial
* update: Made kc.tree as valid XML
* update: added a configuration file project.ihp
* update: added a configuration file buildprofiles.xml
* update: moved coroutines overview from the main repository
* update: move debug tutorials to coroutines repository
* update: update after knit
* update: move all docs files to topics/
* update: corrected the xml version of project.ihp
* update: move old jvm tutorial coroutines-basic-jvm.md
* update: moved knit.properties to resolve relative path correctly
* update: add stubs for moved pages
* update: update README.md
Co-authored-by: Ekaterina.Volodko <ekaterina.volodko@jetbrains.com>
diff --git a/docs/_nav.yml b/docs/_nav.yml
deleted file mode 100644
index 79a6969..0000000
--- a/docs/_nav.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-- md: coroutines-guide.md
- url: coroutines-guide.html
- title: Coroutines Guide
-- md: basics.md
- url: basics.html
- title: Basics
-- md: cancellation-and-timeouts.md
- url: cancellation-and-timeouts.html
- title: Cancellation and Timeouts
-- md: composing-suspending-functions.md
- url: composing-suspending-functions.html
- title: Composing Suspending Functions
-- md: coroutine-context-and-dispatchers.md
- url: coroutine-context-and-dispatchers.html
- title: Coroutine Context and Dispatchers
-- md: flow.md
- url: flow.html
- title: Asynchronous Flow
-- md: channels.md
- url: channels.html
- title: Channels
-- md: exception-handling.md
- url: exception-handling.html
- title: Exception Handling and Supervision
-- md: shared-mutable-state-and-concurrency.md
- url: shared-mutable-state-and-concurrency.html
- title: Shared Mutable State and Concurrency
-- md: select-expression.md
- url: select-expression.html
- title: Select Expression (experimental)
diff --git a/docs/basics.md b/docs/basics.md
index 8aca23a..5de1de2 100644
--- a/docs/basics.md
+++ b/docs/basics.md
@@ -1,410 +1,3 @@
-<!--- TEST_NAME BasicsGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/basics.html](https://kotlinlang.org/docs/basics.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Coroutine Basics](#coroutine-basics)
- * [Your first coroutine](#your-first-coroutine)
- * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
- * [Waiting for a job](#waiting-for-a-job)
- * [Structured concurrency](#structured-concurrency)
- * [Scope builder](#scope-builder)
- * [Extract function refactoring](#extract-function-refactoring)
- * [Coroutines ARE light-weight](#coroutines-are-light-weight)
- * [Global coroutines are like daemon threads](#global-coroutines-are-like-daemon-threads)
-
-<!--- END -->
-
-## Coroutine Basics
-
-This section covers basic coroutine concepts.
-
-### Your first coroutine
-
-Run the following code:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() {
- GlobalScope.launch { // launch a new coroutine in background and continue
- delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
- println("World!") // print after delay
- }
- println("Hello,") // main thread continues while coroutine is delayed
- Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt).
-
-You will see the following result:
-
-```text
-Hello,
-World!
-```
-
-<!--- TEST -->
-
-Essentially, coroutines are light-weight threads.
-They are launched with [launch] _coroutine builder_ in a context of some [CoroutineScope].
-Here we are launching a new coroutine in the [GlobalScope], meaning that the lifetime of the new
-coroutine is limited only by the lifetime of the whole application.
-
-You can achieve the same result by replacing
-`GlobalScope.launch { ... }` with `thread { ... }`, and `delay(...)` with `Thread.sleep(...)`.
-Try it (don't forget to import `kotlin.concurrent.thread`).
-
-If you start by replacing `GlobalScope.launch` with `thread`, the compiler produces the following error:
-
-```
-Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
-```
-
-That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_ the
-coroutine, and it can be only used from a coroutine.
-
-### Bridging blocking and non-blocking worlds
-
-The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
-It is easy to lose track of which one is blocking and which one is not.
-Let's be explicit about blocking using the [runBlocking] coroutine builder:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() {
- GlobalScope.launch { // launch a new coroutine in background and continue
- delay(1000L)
- println("World!")
- }
- println("Hello,") // main thread continues here immediately
- runBlocking { // but this expression blocks the main thread
- delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt).
-
-<!--- TEST
-Hello,
-World!
--->
-
-The result is the same, but this code uses only non-blocking [delay].
-The main thread invoking `runBlocking` _blocks_ until the coroutine inside `runBlocking` completes.
-
-This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
-the execution of the main function:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> { // start main coroutine
- GlobalScope.launch { // launch a new coroutine in background and continue
- delay(1000L)
- println("World!")
- }
- println("Hello,") // main coroutine continues here immediately
- delay(2000L) // delaying for 2 seconds to keep JVM alive
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt).
-
-<!--- TEST
-Hello,
-World!
--->
-
-Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
-We explicitly specify its `Unit` return type, because a well-formed `main` function in Kotlin has to return `Unit`.
-
-This is also a way to write unit tests for suspending functions:
-
-<!--- INCLUDE
-import kotlinx.coroutines.*
--->
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-class MyTest {
- @Test
- fun testMySuspendingFunction() = runBlocking<Unit> {
- // here we can use suspending functions using any assertion style that we like
- }
-}
-```
-
-</div>
-
-<!--- CLEAR -->
-
-### Waiting for a job
-
-Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
-wait (in a non-blocking way) until the background [Job] that we have launched is complete:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
- delay(1000L)
- println("World!")
- }
- println("Hello,")
- job.join() // wait until child coroutine completes
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt).
-
-<!--- TEST
-Hello,
-World!
--->
-
-Now the result is still the same, but the code of the main coroutine is not tied to the duration of
-the background job in any way. Much better.
-
-### Structured concurrency
-
-There is still something to be desired for practical usage of coroutines.
-When we use `GlobalScope.launch`, we create a top-level coroutine. Even though it is light-weight, it still
-consumes some memory resources while it runs. If we forget to keep a reference to the newly launched
-coroutine, it still runs. What if the code in the coroutine hangs (for example, we erroneously
-delay for too long), what if we launched too many coroutines and ran out of memory?
-Having to manually keep references to all the launched coroutines and [join][Job.join] them is error-prone.
-
-There is a better solution. We can use structured concurrency in our code.
-Instead of launching coroutines in the [GlobalScope], just like we usually do with threads (threads are always global),
-we can launch coroutines in the specific scope of the operation we are performing.
-
-In our example, we have a `main` function that is turned into a coroutine using the [runBlocking] coroutine builder.
-Every coroutine builder, including `runBlocking`, adds an instance of [CoroutineScope] to the scope of its code block.
-We can launch coroutines in this scope without having to `join` them explicitly, because
-an outer coroutine (`runBlocking` in our example) does not complete until all the coroutines launched
-in its scope complete. Thus, we can make our example simpler:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking { // this: CoroutineScope
- launch { // launch a new coroutine in the scope of runBlocking
- delay(1000L)
- println("World!")
- }
- println("Hello,")
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt).
-
-<!--- TEST
-Hello,
-World!
--->
-
-### Scope builder
-
-In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using the
-[coroutineScope][_coroutineScope] builder. It creates a coroutine scope and does not complete until all launched children complete.
-
-[runBlocking] and [coroutineScope][_coroutineScope] may look similar because they both wait for their body and all its children to complete.
-The main difference is that the [runBlocking] method _blocks_ the current thread for waiting,
-while [coroutineScope][_coroutineScope] just suspends, releasing the underlying thread for other usages.
-Because of that difference, [runBlocking] is a regular function and [coroutineScope][_coroutineScope] is a suspending function.
-
-It can be demonstrated by the following example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking { // this: CoroutineScope
- launch {
- delay(200L)
- println("Task from runBlocking")
- }
-
- coroutineScope { // Creates a coroutine scope
- launch {
- delay(500L)
- println("Task from nested launch")
- }
-
- delay(100L)
- println("Task from coroutine scope") // This line will be printed before the nested launch
- }
-
- println("Coroutine scope is over") // This line is not printed until the nested launch completes
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt).
-
-<!--- TEST
-Task from coroutine scope
-Task from runBlocking
-Task from nested launch
-Coroutine scope is over
--->
-
-Note that right after the "Task from coroutine scope" message (while waiting for nested launch)
- "Task from runBlocking" is executed and printed — even though the [coroutineScope][_coroutineScope] is not completed yet.
-
-### Extract function refactoring
-
-Let's extract the block of code inside `launch { ... }` into a separate function. When you
-perform "Extract function" refactoring on this code, you get a new function with the `suspend` modifier.
-This is your first _suspending function_. Suspending functions can be used inside coroutines
-just like regular functions, but their additional feature is that they can, in turn,
-use other suspending functions (like `delay` in this example) to _suspend_ execution of a coroutine.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
- launch { doWorld() }
- println("Hello,")
-}
-
-// this is your first suspending function
-suspend fun doWorld() {
- delay(1000L)
- println("World!")
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt).
-
-<!--- TEST
-Hello,
-World!
--->
-
-
-But what if the extracted function contains a coroutine builder which is invoked on the current scope?
-In this case, the `suspend` modifier on the extracted function is not enough. Making `doWorld` an extension
-method on `CoroutineScope` is one of the solutions, but it may not always be applicable as it does not make the API clearer.
-The idiomatic solution is to have either an explicit `CoroutineScope` as a field in a class containing the target function
-or an implicit one when the outer class implements `CoroutineScope`.
-As a last resort, [CoroutineScope(coroutineContext)][CoroutineScope()] can be used, but such an approach is structurally unsafe
-because you no longer have control on the scope of execution of this method. Only private APIs can use this builder.
-
-### Coroutines ARE light-weight
-
-Run the following code:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
- repeat(100_000) { // launch a lot of coroutines
- launch {
- delay(5000L)
- print(".")
- }
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt).
-
-<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
-
-It launches 100K coroutines and, after 5 seconds, each coroutine prints a dot.
-
-Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
-
-### Global coroutines are like daemon threads
-
-The following code launches a long-running coroutine in [GlobalScope] that prints "I'm sleeping" twice a second and then
-returns from the main function after some delay:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- GlobalScope.launch {
- repeat(1000) { i ->
- println("I'm sleeping $i ...")
- delay(500L)
- }
- }
- delay(1300L) // just quit after delay
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt).
-
-You can run and see that it prints three lines and terminates:
-
-```text
-I'm sleeping 0 ...
-I'm sleeping 1 ...
-I'm sleeping 2 ...
-```
-
-<!--- TEST -->
-
-Active coroutines that were launched in [GlobalScope] do not keep the process alive. They are like daemon threads.
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
-[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
-[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
-[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
-[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
-[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope.html
-<!--- END -->
-
-
+To edit the documentation, open the [topics/basics.md](topics/basics.md) page.
\ No newline at end of file
diff --git a/docs/cancellation-and-timeouts.md b/docs/cancellation-and-timeouts.md
index b296bde..ad6afca 100644
--- a/docs/cancellation-and-timeouts.md
+++ b/docs/cancellation-and-timeouts.md
@@ -1,482 +1,3 @@
-<!--- TEST_NAME CancellationGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/cancellation-and-timeouts.html](https://kotlinlang.org/docs/cancellation-and-timeouts.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Cancellation and Timeouts](#cancellation-and-timeouts)
- * [Cancelling coroutine execution](#cancelling-coroutine-execution)
- * [Cancellation is cooperative](#cancellation-is-cooperative)
- * [Making computation code cancellable](#making-computation-code-cancellable)
- * [Closing resources with `finally`](#closing-resources-with-finally)
- * [Run non-cancellable block](#run-non-cancellable-block)
- * [Timeout](#timeout)
- * [Asynchronous timeout and resources](#asynchronous-timeout-and-resources)
-
-<!--- END -->
-
-## Cancellation and Timeouts
-
-This section covers coroutine cancellation and timeouts.
-
-### Cancelling coroutine execution
-
-In a long-running application you might need fine-grained control on your background coroutines.
-For example, a user might have closed the page that launched a coroutine and now its result
-is no longer needed and its operation can be cancelled.
-The [launch] function returns a [Job] that can be used to cancel the running coroutine:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val job = launch {
- repeat(1000) { i ->
- println("job: I'm sleeping $i ...")
- delay(500L)
- }
- }
- delay(1300L) // delay a bit
- println("main: I'm tired of waiting!")
- job.cancel() // cancels the job
- job.join() // waits for job's completion
- println("main: Now I can quit.")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt).
-
-It produces the following output:
-
-```text
-job: I'm sleeping 0 ...
-job: I'm sleeping 1 ...
-job: I'm sleeping 2 ...
-main: I'm tired of waiting!
-main: Now I can quit.
-```
-
-<!--- TEST -->
-
-As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
-There is also a [Job] extension function [cancelAndJoin]
-that combines [cancel][Job.cancel] and [join][Job.join] invocations.
-
-### Cancellation is cooperative
-
-Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
-All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
-coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
-a computation and does not check for cancellation, then it cannot be cancelled, like the following
-example shows:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val startTime = System.currentTimeMillis()
- val job = launch(Dispatchers.Default) {
- var nextPrintTime = startTime
- var i = 0
- while (i < 5) { // computation loop, just wastes CPU
- // print a message twice a second
- if (System.currentTimeMillis() >= nextPrintTime) {
- println("job: I'm sleeping ${i++} ...")
- nextPrintTime += 500L
- }
- }
- }
- delay(1300L) // delay a bit
- println("main: I'm tired of waiting!")
- job.cancelAndJoin() // cancels the job and waits for its completion
- println("main: Now I can quit.")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt).
-
-Run it to see that it continues to print "I'm sleeping" even after cancellation
-until the job completes by itself after five iterations.
-
-<!--- TEST
-job: I'm sleeping 0 ...
-job: I'm sleeping 1 ...
-job: I'm sleeping 2 ...
-main: I'm tired of waiting!
-job: I'm sleeping 3 ...
-job: I'm sleeping 4 ...
-main: Now I can quit.
--->
-
-### Making computation code cancellable
-
-There are two approaches to making computation code cancellable. The first one is to periodically
-invoke a suspending function that checks for cancellation. There is a [yield] function that is a good choice for that purpose.
-The other one is to explicitly check the cancellation status. Let us try the latter approach.
-
-Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val startTime = System.currentTimeMillis()
- val job = launch(Dispatchers.Default) {
- var nextPrintTime = startTime
- var i = 0
- while (isActive) { // cancellable computation loop
- // print a message twice a second
- if (System.currentTimeMillis() >= nextPrintTime) {
- println("job: I'm sleeping ${i++} ...")
- nextPrintTime += 500L
- }
- }
- }
- delay(1300L) // delay a bit
- println("main: I'm tired of waiting!")
- job.cancelAndJoin() // cancels the job and waits for its completion
- println("main: Now I can quit.")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt).
-
-As you can see, now this loop is cancelled. [isActive] is an extension property
-available inside the coroutine via the [CoroutineScope] object.
-
-<!--- TEST
-job: I'm sleeping 0 ...
-job: I'm sleeping 1 ...
-job: I'm sleeping 2 ...
-main: I'm tired of waiting!
-main: Now I can quit.
--->
-
-### Closing resources with `finally`
-
-Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
-the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
-finalization actions normally when a coroutine is cancelled:
-
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val job = launch {
- try {
- repeat(1000) { i ->
- println("job: I'm sleeping $i ...")
- delay(500L)
- }
- } finally {
- println("job: I'm running finally")
- }
- }
- delay(1300L) // delay a bit
- println("main: I'm tired of waiting!")
- job.cancelAndJoin() // cancels the job and waits for its completion
- println("main: Now I can quit.")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt).
-
-Both [join][Job.join] and [cancelAndJoin] wait for all finalization actions to complete,
-so the example above produces the following output:
-
-```text
-job: I'm sleeping 0 ...
-job: I'm sleeping 1 ...
-job: I'm sleeping 2 ...
-main: I'm tired of waiting!
-job: I'm running finally
-main: Now I can quit.
-```
-
-<!--- TEST -->
-
-### Run non-cancellable block
-
-Any attempt to use a suspending function in the `finally` block of the previous example causes
-[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
-problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
-communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
-rare case when you need to suspend in a cancelled coroutine you can wrap the corresponding code in
-`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val job = launch {
- try {
- repeat(1000) { i ->
- println("job: I'm sleeping $i ...")
- delay(500L)
- }
- } finally {
- withContext(NonCancellable) {
- println("job: I'm running finally")
- delay(1000L)
- println("job: And I've just delayed for 1 sec because I'm non-cancellable")
- }
- }
- }
- delay(1300L) // delay a bit
- println("main: I'm tired of waiting!")
- job.cancelAndJoin() // cancels the job and waits for its completion
- println("main: Now I can quit.")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt).
-
-<!--- TEST
-job: I'm sleeping 0 ...
-job: I'm sleeping 1 ...
-job: I'm sleeping 2 ...
-main: I'm tired of waiting!
-job: I'm running finally
-job: And I've just delayed for 1 sec because I'm non-cancellable
-main: Now I can quit.
--->
-
-### Timeout
-
-The most obvious practical reason to cancel execution of a coroutine
-is because its execution time has exceeded some timeout.
-While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
-the tracked one after delay, there is a ready to use [withTimeout] function that does it.
-Look at the following example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- withTimeout(1300L) {
- repeat(1000) { i ->
- println("I'm sleeping $i ...")
- delay(500L)
- }
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt).
-
-It produces the following output:
-
-```text
-I'm sleeping 0 ...
-I'm sleeping 1 ...
-I'm sleeping 2 ...
-Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1300 ms
-```
-
-<!--- TEST STARTS_WITH -->
-
-The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
-We have not seen its stack trace printed on the console before. That is because
-inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
-However, in this example we have used `withTimeout` right inside the `main` function.
-
-Since cancellation is just an exception, all resources are closed in the usual way.
-You can wrap the code with timeout in a `try {...} catch (e: TimeoutCancellationException) {...}` block if
-you need to do some additional action specifically on any kind of timeout or use the [withTimeoutOrNull] function
-that is similar to [withTimeout] but returns `null` on timeout instead of throwing an exception:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val result = withTimeoutOrNull(1300L) {
- repeat(1000) { i ->
- println("I'm sleeping $i ...")
- delay(500L)
- }
- "Done" // will get cancelled before it produces this result
- }
- println("Result is $result")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt).
-
-There is no longer an exception when running this code:
-
-```text
-I'm sleeping 0 ...
-I'm sleeping 1 ...
-I'm sleeping 2 ...
-Result is null
-```
-
-<!--- TEST -->
-
-### Asynchronous timeout and resources
-
-<!--
- NOTE: Don't change this section name. It is being referenced to from within KDoc of withTimeout functions.
--->
-
-The timeout event in [withTimeout] is asynchronous with respect to the code running in its block and may happen at any time,
-even right before the return from inside of the timeout block. Keep this in mind if you open or acquire some
-resource inside the block that needs closing or release outside of the block.
-
-For example, here we imitate a closeable resource with the `Resource` class, that simply keeps track of how many times
-it was created by incrementing the `acquired` counter and decrementing this counter from its `close` function.
-Let us run a lot of coroutines with the small timeout try acquire this resource from inside
-of the `withTimeout` block after a bit of delay and release it from outside.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-//sampleStart
-var acquired = 0
-
-class Resource {
- init { acquired++ } // Acquire the resource
- fun close() { acquired-- } // Release the resource
-}
-
-fun main() {
- runBlocking {
- repeat(100_000) { // Launch 100K coroutines
- launch {
- val resource = withTimeout(60) { // Timeout of 60 ms
- delay(50) // Delay for 50 ms
- Resource() // Acquire a resource and return it from withTimeout block
- }
- resource.close() // Release the resource
- }
- }
- }
- // Outside of runBlocking all coroutines have completed
- println(acquired) // Print the number of resources still acquired
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt).
-
-<!--- CLEAR -->
-
-If you run the above code you'll see that it does not always print zero, though it may depend on the timings
-of your machine you may need to tweak timeouts in this example to actually see non-zero values.
-
-> Note, that incrementing and decrementing `acquired` counter here from 100K coroutines is completely safe,
-> since it always happens from the same main thread. More on that will be explained in the next chapter
-> on coroutine context.
-
-To workaround this problem you can store a reference to the resource in the variable as opposed to returning it
-from the `withTimeout` block.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-var acquired = 0
-
-class Resource {
- init { acquired++ } // Acquire the resource
- fun close() { acquired-- } // Release the resource
-}
-
-fun main() {
-//sampleStart
- runBlocking {
- repeat(100_000) { // Launch 100K coroutines
- launch {
- var resource: Resource? = null // Not acquired yet
- try {
- withTimeout(60) { // Timeout of 60 ms
- delay(50) // Delay for 50 ms
- resource = Resource() // Store a resource to the variable if acquired
- }
- // We can do something else with the resource here
- } finally {
- resource?.close() // Release the resource if it was acquired
- }
- }
- }
- }
- // Outside of runBlocking all coroutines have completed
- println(acquired) // Print the number of resources still acquired
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt).
-
-This example always prints zero. Resources do not leak.
-
-<!--- TEST
-0
--->
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
-[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/cancel-and-join.html
-[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
-[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
-[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
-[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/yield.html
-[isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html
-[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
-[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-non-cancellable.html
-[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout.html
-[withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html
-<!--- END -->
+To edit the documentation, open the [topics/cancellation-and-timeouts.md](topics/cancellation-and-timeouts.md) page.
\ No newline at end of file
diff --git a/docs/cfg/buildprofiles.xml b/docs/cfg/buildprofiles.xml
new file mode 100644
index 0000000..cd546de
--- /dev/null
+++ b/docs/cfg/buildprofiles.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<buildprofiles>
+ <variables>
+ <enable-browser-edits>true</enable-browser-edits>
+ <browser-edits-url>https://github.com/Kotlin/kotlinx.coroutines/edit/master/</browser-edits-url>
+ </variables>
+ <build-profile product="kc"/>
+</buildprofiles>
diff --git a/docs/channels.md b/docs/channels.md
index d1a4bac..73415ce 100644
--- a/docs/channels.md
+++ b/docs/channels.md
@@ -1,702 +1,3 @@
-<!--- TEST_NAME ChannelsGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/channels.html](https://kotlinlang.org/docs/channels.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Channels](#channels)
- * [Channel basics](#channel-basics)
- * [Closing and iteration over channels](#closing-and-iteration-over-channels)
- * [Building channel producers](#building-channel-producers)
- * [Pipelines](#pipelines)
- * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
- * [Fan-out](#fan-out)
- * [Fan-in](#fan-in)
- * [Buffered channels](#buffered-channels)
- * [Channels are fair](#channels-are-fair)
- * [Ticker channels](#ticker-channels)
-
-<!--- END -->
-
-## Channels
-
-Deferred values provide a convenient way to transfer a single value between coroutines.
-Channels provide a way to transfer a stream of values.
-
-### Channel basics
-
-A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
-instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
-a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
-
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking {
-//sampleStart
- val channel = Channel<Int>()
- launch {
- // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
- for (x in 1..5) channel.send(x * x)
- }
- // here we print five received integers:
- repeat(5) { println(channel.receive()) }
- println("Done!")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt).
-
-The output of this code is:
-
-```text
-1
-4
-9
-16
-25
-Done!
-```
-
-<!--- TEST -->
-
-### Closing and iteration over channels
-
-Unlike a queue, a channel can be closed to indicate that no more elements are coming.
-On the receiver side it is convenient to use a regular `for` loop to receive elements
-from the channel.
-
-Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
-The iteration stops as soon as this close token is received, so there is a guarantee
-that all previously sent elements before the close are received:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking {
-//sampleStart
- val channel = Channel<Int>()
- launch {
- for (x in 1..5) channel.send(x * x)
- channel.close() // we're done sending
- }
- // here we print received values using `for` loop (until the channel is closed)
- for (y in channel) println(y)
- println("Done!")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt).
-
-<!--- TEST
-1
-4
-9
-16
-25
-Done!
--->
-
-### Building channel producers
-
-The pattern where a coroutine is producing a sequence of elements is quite common.
-This is a part of _producer-consumer_ pattern that is often found in concurrent code.
-You could abstract such a producer into a function that takes channel as its parameter, but this goes contrary
-to common sense that results must be returned from functions.
-
-There is a convenient coroutine builder named [produce] that makes it easy to do it right on producer side,
-and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
- for (x in 1..5) send(x * x)
-}
-
-fun main() = runBlocking {
-//sampleStart
- val squares = produceSquares()
- squares.consumeEach { println(it) }
- println("Done!")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt).
-
-<!--- TEST
-1
-4
-9
-16
-25
-Done!
--->
-
-### Pipelines
-
-A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.produceNumbers() = produce<Int> {
- var x = 1
- while (true) send(x++) // infinite stream of integers starting from 1
-}
-```
-
-</div>
-
-And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
-In the example below, the numbers are just squared:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
- for (x in numbers) send(x * x)
-}
-```
-
-</div>
-
-The main code starts and connects the whole pipeline:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking {
-//sampleStart
- val numbers = produceNumbers() // produces integers from 1 and on
- val squares = square(numbers) // squares integers
- repeat(5) {
- println(squares.receive()) // print first five
- }
- println("Done!") // we are done
- coroutineContext.cancelChildren() // cancel children coroutines
-//sampleEnd
-}
-
-fun CoroutineScope.produceNumbers() = produce<Int> {
- var x = 1
- while (true) send(x++) // infinite stream of integers starting from 1
-}
-
-fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
- for (x in numbers) send(x * x)
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt).
-
-<!--- TEST
-1
-4
-9
-16
-25
-Done!
--->
-
-> All functions that create coroutines are defined as extensions on [CoroutineScope],
-so that we can rely on [structured concurrency](https://kotlinlang.org/docs/reference/coroutines/composing-suspending-functions.html#structured-concurrency-with-async) to make
-sure that we don't have lingering global coroutines in our application.
-
-### Prime numbers with pipeline
-
-Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
-of coroutines. We start with an infinite sequence of numbers.
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.numbersFrom(start: Int) = produce<Int> {
- var x = start
- while (true) send(x++) // infinite stream of integers from start
-}
-```
-
-</div>
-
-The following pipeline stage filters an incoming stream of numbers, removing all the numbers
-that are divisible by the given prime number:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> {
- for (x in numbers) if (x % prime != 0) send(x)
-}
-```
-
-</div>
-
-Now we build our pipeline by starting a stream of numbers from 2, taking a prime number from the current channel,
-and launching new pipeline stage for each prime number found:
-
-```
-numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
-```
-
-The following example prints the first ten prime numbers,
-running the whole pipeline in the context of the main thread. Since all the coroutines are launched in
-the scope of the main [runBlocking] coroutine
-we don't have to keep an explicit list of all the coroutines we have started.
-We use [cancelChildren][kotlin.coroutines.CoroutineContext.cancelChildren]
-extension function to cancel all the children coroutines after we have printed
-the first ten prime numbers.
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking {
-//sampleStart
- var cur = numbersFrom(2)
- repeat(10) {
- val prime = cur.receive()
- println(prime)
- cur = filter(cur, prime)
- }
- coroutineContext.cancelChildren() // cancel all children to let main finish
-//sampleEnd
-}
-
-fun CoroutineScope.numbersFrom(start: Int) = produce<Int> {
- var x = start
- while (true) send(x++) // infinite stream of integers from start
-}
-
-fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> {
- for (x in numbers) if (x % prime != 0) send(x)
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt).
-
-The output of this code is:
-
-```text
-2
-3
-5
-7
-11
-13
-17
-19
-23
-29
-```
-
-<!--- TEST -->
-
-Note that you can build the same pipeline using
-[`iterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/iterator.html)
-coroutine builder from the standard library.
-Replace `produce` with `iterator`, `send` with `yield`, `receive` with `next`,
-`ReceiveChannel` with `Iterator`, and get rid of the coroutine scope. You will not need `runBlocking` either.
-However, the benefit of a pipeline that uses channels as shown above is that it can actually use
-multiple CPU cores if you run it in [Dispatchers.Default] context.
-
-Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
-other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
-built using `sequence`/`iterator`, because they do not allow arbitrary suspension, unlike
-`produce`, which is fully asynchronous.
-
-### Fan-out
-
-Multiple coroutines may receive from the same channel, distributing work between themselves.
-Let us start with a producer coroutine that is periodically producing integers
-(ten numbers per second):
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.produceNumbers() = produce<Int> {
- var x = 1 // start from 1
- while (true) {
- send(x++) // produce next
- delay(100) // wait 0.1s
- }
-}
-```
-
-</div>
-
-Then we can have several processor coroutines. In this example, they just print their id and
-received number:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
- for (msg in channel) {
- println("Processor #$id received $msg")
- }
-}
-```
-
-</div>
-
-Now let us launch five processors and let them work for almost a second. See what happens:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val producer = produceNumbers()
- repeat(5) { launchProcessor(it, producer) }
- delay(950)
- producer.cancel() // cancel producer coroutine and thus kill them all
-//sampleEnd
-}
-
-fun CoroutineScope.produceNumbers() = produce<Int> {
- var x = 1 // start from 1
- while (true) {
- send(x++) // produce next
- delay(100) // wait 0.1s
- }
-}
-
-fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
- for (msg in channel) {
- println("Processor #$id received $msg")
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt).
-
-The output will be similar to the the following one, albeit the processor ids that receive
-each specific integer may be different:
-
-```
-Processor #2 received 1
-Processor #4 received 2
-Processor #0 received 3
-Processor #1 received 4
-Processor #3 received 5
-Processor #2 received 6
-Processor #4 received 7
-Processor #0 received 8
-Processor #1 received 9
-Processor #3 received 10
-```
-
-<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
-
-Note that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
-over the channel that processor coroutines are doing.
-
-Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
-Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
-coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
-always consumes (cancels) the underlying channel on its normal or abnormal completion.
-
-### Fan-in
-
-Multiple coroutines may send to the same channel.
-For example, let us have a channel of strings, and a suspending function that
-repeatedly sends a specified string to this channel with a specified delay:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
- while (true) {
- delay(time)
- channel.send(s)
- }
-}
-```
-
-</div>
-
-Now, let us see what happens if we launch a couple of coroutines sending strings
-(in this example we launch them in the context of the main thread as main coroutine's children):
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking {
-//sampleStart
- val channel = Channel<String>()
- launch { sendString(channel, "foo", 200L) }
- launch { sendString(channel, "BAR!", 500L) }
- repeat(6) { // receive first six
- println(channel.receive())
- }
- coroutineContext.cancelChildren() // cancel all children to let main finish
-//sampleEnd
-}
-
-suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
- while (true) {
- delay(time)
- channel.send(s)
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt).
-
-The output is:
-
-```text
-foo
-foo
-BAR!
-foo
-foo
-BAR!
-```
-
-<!--- TEST -->
-
-### Buffered channels
-
-The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
-meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
-if receive is invoked first, it is suspended until send is invoked.
-
-Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
-specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
-similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
-
-Take a look at the behavior of the following code:
-
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val channel = Channel<Int>(4) // create buffered channel
- val sender = launch { // launch sender coroutine
- repeat(10) {
- println("Sending $it") // print before sending each element
- channel.send(it) // will suspend when buffer is full
- }
- }
- // don't receive anything... just wait....
- delay(1000)
- sender.cancel() // cancel sender coroutine
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt).
-
-It prints "sending" _five_ times using a buffered channel with capacity of _four_:
-
-```text
-Sending 0
-Sending 1
-Sending 2
-Sending 3
-Sending 4
-```
-
-<!--- TEST -->
-
-The first four elements are added to the buffer and the sender suspends when trying to send the fifth one.
-
-### Channels are fair
-
-Send and receive operations to channels are _fair_ with respect to the order of their invocation from
-multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
-gets the element. In the following example two coroutines "ping" and "pong" are
-receiving the "ball" object from the shared "table" channel.
-
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-//sampleStart
-data class Ball(var hits: Int)
-
-fun main() = runBlocking {
- val table = Channel<Ball>() // a shared table
- launch { player("ping", table) }
- launch { player("pong", table) }
- table.send(Ball(0)) // serve the ball
- delay(1000) // delay 1 second
- coroutineContext.cancelChildren() // game over, cancel them
-}
-
-suspend fun player(name: String, table: Channel<Ball>) {
- for (ball in table) { // receive the ball in a loop
- ball.hits++
- println("$name $ball")
- delay(300) // wait a bit
- table.send(ball) // send the ball back
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt).
-
-The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
-coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
-received by the "pong" coroutine, because it was already waiting for it:
-
-```text
-ping Ball(hits=1)
-pong Ball(hits=2)
-ping Ball(hits=3)
-pong Ball(hits=4)
-```
-
-<!--- TEST -->
-
-Note that sometimes channels may produce executions that look unfair due to the nature of the executor
-that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
-
-### Ticker channels
-
-Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
-Though it may seem to be useless standalone, it is a useful building block to create complex time-based [produce]
-pipelines and operators that do windowing and other time-dependent processing.
-Ticker channel can be used in [select] to perform "on tick" action.
-
-To create such channel use a factory method [ticker].
-To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
-
-Now let's see how it works in practice:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-
-fun main() = runBlocking<Unit> {
- val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
- var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
- println("Initial element is available immediately: $nextElement") // no initial delay
-
- nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
- println("Next element is not ready in 50 ms: $nextElement")
-
- nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
- println("Next element is ready in 100 ms: $nextElement")
-
- // Emulate large consumption delays
- println("Consumer pauses for 150ms")
- delay(150)
- // Next element is available immediately
- nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
- println("Next element is available immediately after large consumer delay: $nextElement")
- // Note that the pause between `receive` calls is taken into account and next element arrives faster
- nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
- println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
-
- tickerChannel.cancel() // indicate that no more elements are needed
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt).
-
-It prints following lines:
-
-```text
-Initial element is available immediately: kotlin.Unit
-Next element is not ready in 50 ms: null
-Next element is ready in 100 ms: kotlin.Unit
-Consumer pauses for 150ms
-Next element is available immediately after large consumer delay: kotlin.Unit
-Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
-```
-
-<!--- TEST -->
-
-Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
-delay if a pause occurs, trying to maintain a fixed rate of produced elements.
-
-Optionally, a `mode` parameter equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
-delay between elements.
-
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[kotlin.coroutines.CoroutineContext.cancelChildren]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/kotlin.coroutines.-coroutine-context/cancel-children.html
-[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
-<!--- INDEX kotlinx.coroutines.channels -->
-[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/index.html
-[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/send.html
-[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
-[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/close.html
-[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
-[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/consume-each.html
-[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel.html
-[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/ticker.html
-[ReceiveChannel.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/cancel.html
-[TickerMode.FIXED_DELAY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-ticker-mode/-f-i-x-e-d_-d-e-l-a-y.html
-<!--- INDEX kotlinx.coroutines.selects -->
-[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html
-<!--- END -->
+To edit the documentation, open the [topics/channels.md](topics/channels.md) page.
\ No newline at end of file
diff --git a/docs/compatibility.md b/docs/compatibility.md
index 8dafae7..b61f629 100644
--- a/docs/compatibility.md
+++ b/docs/compatibility.md
@@ -1,125 +1 @@
-<!--- TOC -->
-
-* [Compatibility](#compatibility)
-* [Public API types](#public-api-types)
- * [Experimental API](#experimental-api)
- * [Flow preview API](#flow-preview-api)
- * [Obsolete API](#obsolete-api)
- * [Internal API](#internal-api)
- * [Stable API](#stable-api)
- * [Deprecation cycle](#deprecation-cycle)
-* [Using annotated API](#using-annotated-api)
- * [Programmatically](#programmatically)
- * [Gradle](#gradle)
- * [Maven](#maven)
-
-<!--- END -->
-
-## Compatibility
-This document describes the compatibility policy of `kotlinx.coroutines` library since version 1.0.0 and semantics of compatibility-specific annotations.
-
-
-## Public API types
-`kotlinx.coroutines` public API comes in five flavours: stable, experimental, obsolete, internal and deprecated.
-All public API except stable is marked with the corresponding annotation.
-
-### Experimental API
-Experimental API is marked with [@ExperimentalCoroutinesApi][ExperimentalCoroutinesApi] annotation.
-API is marked experimental when its design has potential open questions which may eventually lead to
-either semantics changes of the API or its deprecation.
-
-By default, most of the new API is marked as experimental and becomes stable in one of the next major releases if no new issues arise.
-Otherwise, either semantics is fixed without changes in ABI or API goes through deprecation cycle.
-
-When using experimental API may be dangerous:
-* You are writing a library which depends on `kotlinx.coroutines` and want to use experimental coroutines API in a stable library API.
-It may lead to undesired consequences when end users of your library update their `kotlinx.coroutines` version where experimental API
-has slightly different semantics.
-* You want to build core infrastructure of the application around experimental API.
-
-### Flow preview API
-All [Flow]-related API is marked with [@FlowPreview][FlowPreview] annotation.
-This annotation indicates that Flow API is in preview status.
-We provide no compatibility guarantees between releases for preview features, including binary, source and semantics compatibility.
-
-When using preview API may be dangerous:
-* You are writing a library/framework and want to use [Flow] API in a stable release or in a stable API.
-* You want to use [Flow] in the core infrastructure of your application.
-* You want to use [Flow] as "write-and-forget" solution and cannot afford additional maintenance cost when
- it comes to `kotlinx.coroutines` updates.
-
-
-### Obsolete API
-Obsolete API is marked with [@ObsoleteCoroutinesApi][ObsoleteCoroutinesApi] annotation.
-Obsolete API is similar to experimental, but already known to have serious design flaws and its potential replacement,
-but replacement is not yet implemented.
-
-The semantics of this API won't be changed, but it will go through a deprecation cycle as soon as the replacement is ready.
-
-### Internal API
-Internal API is marked with [@InternalCoroutinesApi][InternalCoroutinesApi] or is part of `kotlinx.coroutines.internal` package.
-This API has no guarantees on its stability, can and will be changed and/or removed in the future releases.
-If you can't avoid using internal API, please report it to [issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues/new).
-
-### Stable API
-Stable API is guaranteed to preserve its ABI and documented semantics. If at some point unfixable design flaws will be discovered,
-this API will go through a deprecation cycle and remain binary compatible as long as possible.
-
-### Deprecation cycle
-When some API is deprecated, it goes through multiple stages and there is at least one major release between stages.
-* Feature is deprecated with compilation warning. Most of the time, proper replacement
-(and corresponding `replaceWith` declaration) is provided to automatically migrate deprecated usages with a help of IntelliJ IDEA.
-* Deprecation level is increased to `error` or `hidden`. It is no longer possible to compile new code against deprecated API,
- though it is still present in the ABI.
-* API is completely removed. While we give our best efforts not to do so and have no plans of removing any API, we still are leaving
-this option in case of unforeseen problems such as security holes.
-
-## Using annotated API
-All API annotations are [kotlin.Experimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-experimental/index.html).
-It is done in order to produce compilation warning about using experimental or obsolete API.
-Warnings can be disabled either programmatically for a specific call site or globally for the whole module.
-
-### Programmatically
-For a specific call-site, warning can be disabled by using [UseExperimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-use-experimental/index.html) annotation:
-```kotlin
-@UseExperimental(ExperimentalCoroutinesApi::class) // Disables warning about experimental coroutines API
-fun experimentalApiUsage() {
- someKotlinxCoroutinesExperimentalMethod()
-}
-```
-
-### Gradle
-For the Gradle project, a warning can be disabled by passing a compiler flag in your `build.gradle` file:
-
-```groovy
-tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all {
- kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi"]
-}
-
-```
-
-### Maven
-For the Maven project, a warning can be disabled by passing a compiler flag in your `pom.xml` file:
-```xml
-<plugin>
- <artifactId>kotlin-maven-plugin</artifactId>
- <groupId>org.jetbrains.kotlin</groupId>
- ... your configuration ...
- <configuration>
- <args>
- <arg>-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi</arg>
- </args>
- </configuration>
-</plugin>
-```
-
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines.flow -->
-[Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html
-<!--- INDEX kotlinx.coroutines -->
-[ExperimentalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-experimental-coroutines-api/index.html
-[FlowPreview]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-flow-preview/index.html
-[ObsoleteCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-obsolete-coroutines-api/index.html
-[InternalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-internal-coroutines-api/index.html
-<!--- END -->
+The documentation has been moved to the [topics/compatibility.md](topics/compatibility.md).
\ No newline at end of file
diff --git a/docs/composing-suspending-functions.md b/docs/composing-suspending-functions.md
index 81b6f53..4318c4e 100644
--- a/docs/composing-suspending-functions.md
+++ b/docs/composing-suspending-functions.md
@@ -1,435 +1,3 @@
-<!--- TEST_NAME ComposingGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/composing-suspending-functions.html](https://kotlinlang.org/docs/composing-suspending-functions.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Composing Suspending Functions](#composing-suspending-functions)
- * [Sequential by default](#sequential-by-default)
- * [Concurrent using async](#concurrent-using-async)
- * [Lazily started async](#lazily-started-async)
- * [Async-style functions](#async-style-functions)
- * [Structured concurrency with async](#structured-concurrency-with-async)
-
-<!--- END -->
-
-## Composing Suspending Functions
-
-This section covers various approaches to composition of suspending functions.
-
-### Sequential by default
-
-Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
-remote service call or computation. We just pretend they are useful, but actually each one just
-delays for a second for the purpose of this example:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-suspend fun doSomethingUsefulOne(): Int {
- delay(1000L) // pretend we are doing something useful here
- return 13
-}
-
-suspend fun doSomethingUsefulTwo(): Int {
- delay(1000L) // pretend we are doing something useful here, too
- return 29
-}
-```
-
-</div>
-
-
-What do we do if we need them to be invoked _sequentially_ — first `doSomethingUsefulOne` _and then_
-`doSomethingUsefulTwo`, and compute the sum of their results?
-In practice we do this if we use the result of the first function to make a decision on whether we need
-to invoke the second one or to decide on how to invoke it.
-
-We use a normal sequential invocation, because the code in the coroutine, just like in the regular
-code, is _sequential_ by default. The following example demonstrates it by measuring the total
-time it takes to execute both suspending functions:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- val one = doSomethingUsefulOne()
- val two = doSomethingUsefulTwo()
- println("The answer is ${one + two}")
- }
- println("Completed in $time ms")
-//sampleEnd
-}
-
-suspend fun doSomethingUsefulOne(): Int {
- delay(1000L) // pretend we are doing something useful here
- return 13
-}
-
-suspend fun doSomethingUsefulTwo(): Int {
- delay(1000L) // pretend we are doing something useful here, too
- return 29
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt).
-
-It produces something like this:
-
-```text
-The answer is 42
-Completed in 2017 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-### Concurrent using async
-
-What if there are no dependencies between invocations of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
-we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
-
-Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
-that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
-does not carry any resulting value, while `async` returns a [Deferred] — a light-weight non-blocking future
-that represents a promise to provide a result later. You can use `.await()` on a deferred value to get its eventual result,
-but `Deferred` is also a `Job`, so you can cancel it if needed.
-
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- val one = async { doSomethingUsefulOne() }
- val two = async { doSomethingUsefulTwo() }
- println("The answer is ${one.await() + two.await()}")
- }
- println("Completed in $time ms")
-//sampleEnd
-}
-
-suspend fun doSomethingUsefulOne(): Int {
- delay(1000L) // pretend we are doing something useful here
- return 13
-}
-
-suspend fun doSomethingUsefulTwo(): Int {
- delay(1000L) // pretend we are doing something useful here, too
- return 29
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt).
-
-It produces something like this:
-
-```text
-The answer is 42
-Completed in 1017 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-This is twice as fast, because the two coroutines execute concurrently.
-Note that concurrency with coroutines is always explicit.
-
-### Lazily started async
-
-Optionally, [async] can be made lazy by setting its `start` parameter to [CoroutineStart.LAZY].
-In this mode it only starts the coroutine when its result is required by
-[await][Deferred.await], or if its `Job`'s [start][Job.start] function
-is invoked. Run the following example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
- val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
- // some computation
- one.start() // start the first one
- two.start() // start the second one
- println("The answer is ${one.await() + two.await()}")
- }
- println("Completed in $time ms")
-//sampleEnd
-}
-
-suspend fun doSomethingUsefulOne(): Int {
- delay(1000L) // pretend we are doing something useful here
- return 13
-}
-
-suspend fun doSomethingUsefulTwo(): Int {
- delay(1000L) // pretend we are doing something useful here, too
- return 29
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt).
-
-It produces something like this:
-
-```text
-The answer is 42
-Completed in 1017 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-So, here the two coroutines are defined but not executed as in the previous example, but the control is given to
-the programmer on when exactly to start the execution by calling [start][Job.start]. We first
-start `one`, then start `two`, and then await for the individual coroutines to finish.
-
-Note that if we just call [await][Deferred.await] in `println` without first calling [start][Job.start] on individual
-coroutines, this will lead to sequential behavior, since [await][Deferred.await] starts the coroutine
-execution and waits for its finish, which is not the intended use-case for laziness.
-The use-case for `async(start = CoroutineStart.LAZY)` is a replacement for the
-standard `lazy` function in cases when computation of the value involves suspending functions.
-
-### Async-style functions
-
-We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
-_asynchronously_ using the [async] coroutine builder with an explicit [GlobalScope] reference.
-We name such functions with the
-"...Async" suffix to highlight the fact that they only start asynchronous computation and one needs
-to use the resulting deferred value to get the result.
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-// The result type of somethingUsefulOneAsync is Deferred<Int>
-fun somethingUsefulOneAsync() = GlobalScope.async {
- doSomethingUsefulOne()
-}
-
-// The result type of somethingUsefulTwoAsync is Deferred<Int>
-fun somethingUsefulTwoAsync() = GlobalScope.async {
- doSomethingUsefulTwo()
-}
-```
-
-</div>
-
-Note that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
-However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
-with the invoking code.
-
-The following example shows their use outside of coroutine:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-//sampleStart
-// note that we don't have `runBlocking` to the right of `main` in this example
-fun main() {
- val time = measureTimeMillis {
- // we can initiate async actions outside of a coroutine
- val one = somethingUsefulOneAsync()
- val two = somethingUsefulTwoAsync()
- // but waiting for a result must involve either suspending or blocking.
- // here we use `runBlocking { ... }` to block the main thread while waiting for the result
- runBlocking {
- println("The answer is ${one.await() + two.await()}")
- }
- }
- println("Completed in $time ms")
-}
-//sampleEnd
-
-fun somethingUsefulOneAsync() = GlobalScope.async {
- doSomethingUsefulOne()
-}
-
-fun somethingUsefulTwoAsync() = GlobalScope.async {
- doSomethingUsefulTwo()
-}
-
-suspend fun doSomethingUsefulOne(): Int {
- delay(1000L) // pretend we are doing something useful here
- return 13
-}
-
-suspend fun doSomethingUsefulTwo(): Int {
- delay(1000L) // pretend we are doing something useful here, too
- return 29
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt).
-
-<!--- TEST ARBITRARY_TIME
-The answer is 42
-Completed in 1085 ms
--->
-
-> This programming style with async functions is provided here only for illustration, because it is a popular style
-in other programming languages. Using this style with Kotlin coroutines is **strongly discouraged** for the
-reasons explained below.
-
-Consider what happens if between the `val one = somethingUsefulOneAsync()` line and `one.await()` expression there is some logic
-error in the code and the program throws an exception and the operation that was being performed by the program aborts.
-Normally, a global error-handler could catch this exception, log and report the error for developers, but the program
-could otherwise continue doing other operations. But here we have `somethingUsefulOneAsync` still running in the background,
-even though the operation that initiated it was aborted. This problem does not happen with structured
-concurrency, as shown in the section below.
-
-### Structured concurrency with async
-
-Let us take the [Concurrent using async](#concurrent-using-async) example and extract a function that
-concurrently performs `doSomethingUsefulOne` and `doSomethingUsefulTwo` and returns the sum of their results.
-Because the [async] coroutine builder is defined as an extension on [CoroutineScope], we need to have it in the
-scope and that is what the [coroutineScope][_coroutineScope] function provides:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-suspend fun concurrentSum(): Int = coroutineScope {
- val one = async { doSomethingUsefulOne() }
- val two = async { doSomethingUsefulTwo() }
- one.await() + two.await()
-}
-```
-
-</div>
-
-This way, if something goes wrong inside the code of the `concurrentSum` function and it throws an exception,
-all the coroutines that were launched in its scope will be cancelled.
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- println("The answer is ${concurrentSum()}")
- }
- println("Completed in $time ms")
-//sampleEnd
-}
-
-suspend fun concurrentSum(): Int = coroutineScope {
- val one = async { doSomethingUsefulOne() }
- val two = async { doSomethingUsefulTwo() }
- one.await() + two.await()
-}
-
-suspend fun doSomethingUsefulOne(): Int {
- delay(1000L) // pretend we are doing something useful here
- return 13
-}
-
-suspend fun doSomethingUsefulTwo(): Int {
- delay(1000L) // pretend we are doing something useful here, too
- return 29
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt).
-
-We still have concurrent execution of both operations, as evident from the output of the above `main` function:
-
-```text
-The answer is 42
-Completed in 1017 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-Cancellation is always propagated through coroutines hierarchy:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
- try {
- failedConcurrentSum()
- } catch(e: ArithmeticException) {
- println("Computation failed with ArithmeticException")
- }
-}
-
-suspend fun failedConcurrentSum(): Int = coroutineScope {
- val one = async<Int> {
- try {
- delay(Long.MAX_VALUE) // Emulates very long computation
- 42
- } finally {
- println("First child was cancelled")
- }
- }
- val two = async<Int> {
- println("Second child throws an exception")
- throw ArithmeticException()
- }
- one.await() + two.await()
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt).
-
-Note how both the first `async` and the awaiting parent are cancelled on failure of one of the children
-(namely, `two`):
-```text
-Second child throws an exception
-First child was cancelled
-Computation failed with ArithmeticException
-```
-
-<!--- TEST -->
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
-[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
-[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html
-[CoroutineStart.LAZY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-start/-l-a-z-y.html
-[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html
-[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/start.html
-[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
-[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
-<!--- END -->
+To edit the documentation, open the [topics/composing-suspending-functions.md](topics/composing-suspending-functions.md) page.
\ No newline at end of file
diff --git a/docs/coroutine-context-and-dispatchers.md b/docs/coroutine-context-and-dispatchers.md
index 36e049d..f8ba128 100644
--- a/docs/coroutine-context-and-dispatchers.md
+++ b/docs/coroutine-context-and-dispatchers.md
@@ -1,712 +1,3 @@
-<!--- TEST_NAME DispatcherGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/coroutine-context-and-dispatchers.html](https://kotlinlang.org/docs/coroutine-context-and-dispatchers.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Coroutine Context and Dispatchers](#coroutine-context-and-dispatchers)
- * [Dispatchers and threads](#dispatchers-and-threads)
- * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
- * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
- * [Debugging with IDEA](#debugging-with-idea)
- * [Debugging using logging](#debugging-using-logging)
- * [Jumping between threads](#jumping-between-threads)
- * [Job in the context](#job-in-the-context)
- * [Children of a coroutine](#children-of-a-coroutine)
- * [Parental responsibilities](#parental-responsibilities)
- * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
- * [Combining context elements](#combining-context-elements)
- * [Coroutine scope](#coroutine-scope)
- * [Thread-local data](#thread-local-data)
-
-<!--- END -->
-
-## Coroutine Context and Dispatchers
-
-Coroutines always execute in some context represented by a value of the
-[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/)
-type, defined in the Kotlin standard library.
-
-The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
-which we've seen before, and its dispatcher, which is covered in this section.
-
-### Dispatchers and threads
-
-The coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
-the corresponding coroutine uses for its execution. The coroutine dispatcher can confine coroutine execution
-to a specific thread, dispatch it to a thread pool, or let it run unconfined.
-
-All coroutine builders like [launch] and [async] accept an optional
-[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/)
-parameter that can be used to explicitly specify the dispatcher for the new coroutine and other context elements.
-
-Try the following example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- launch { // context of the parent, main runBlocking coroutine
- println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
- }
- launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
- println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
- }
- launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher
- println("Default : I'm working in thread ${Thread.currentThread().name}")
- }
- launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
- println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt).
-
-It produces the following output (maybe in different order):
-
-```text
-Unconfined : I'm working in thread main
-Default : I'm working in thread DefaultDispatcher-worker-1
-newSingleThreadContext: I'm working in thread MyOwnThread
-main runBlocking : I'm working in thread main
-```
-
-<!--- TEST LINES_START_UNORDERED -->
-
-When `launch { ... }` is used without parameters, it inherits the context (and thus dispatcher)
-from the [CoroutineScope] it is being launched from. In this case, it inherits the
-context of the main `runBlocking` coroutine which runs in the `main` thread.
-
-[Dispatchers.Unconfined] is a special dispatcher that also appears to run in the `main` thread, but it is,
-in fact, a different mechanism that is explained later.
-
-The default dispatcher that is used when coroutines are launched in [GlobalScope]
-is represented by [Dispatchers.Default] and uses a shared background pool of threads,
-so `launch(Dispatchers.Default) { ... }` uses the same dispatcher as `GlobalScope.launch { ... }`.
-
-[newSingleThreadContext] creates a thread for the coroutine to run.
-A dedicated thread is a very expensive resource.
-In a real application it must be either released, when no longer needed, using the [close][ExecutorCoroutineDispatcher.close]
-function, or stored in a top-level variable and reused throughout the application.
-
-### Unconfined vs confined dispatcher
-
-The [Dispatchers.Unconfined] coroutine dispatcher starts a coroutine in the caller thread, but only until the
-first suspension point. After suspension it resumes the coroutine in the thread that is fully determined by the
-suspending function that was invoked. The unconfined dispatcher is appropriate for coroutines which neither
-consume CPU time nor update any shared data (like UI) confined to a specific thread.
-
-On the other side, the dispatcher is inherited from the outer [CoroutineScope] by default.
-The default dispatcher for the [runBlocking] coroutine, in particular,
-is confined to the invoker thread, so inheriting it has the effect of confining execution to
-this thread with predictable FIFO scheduling.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
- println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
- delay(500)
- println("Unconfined : After delay in thread ${Thread.currentThread().name}")
- }
- launch { // context of the parent, main runBlocking coroutine
- println("main runBlocking: I'm working in thread ${Thread.currentThread().name}")
- delay(1000)
- println("main runBlocking: After delay in thread ${Thread.currentThread().name}")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt).
-
-Produces the output:
-
-```text
-Unconfined : I'm working in thread main
-main runBlocking: I'm working in thread main
-Unconfined : After delay in thread kotlinx.coroutines.DefaultExecutor
-main runBlocking: After delay in thread main
-```
-
-<!--- TEST LINES_START -->
-
-So, the coroutine with the context inherited from `runBlocking {...}` continues to execute
-in the `main` thread, while the unconfined one resumes in the default executor thread that the [delay]
-function is using.
-
-> The unconfined dispatcher is an advanced mechanism that can be helpful in certain corner cases where
-dispatching of a coroutine for its execution later is not needed or produces undesirable side-effects,
-because some operation in a coroutine must be performed right away.
-The unconfined dispatcher should not be used in general code.
-
-### Debugging coroutines and threads
-
-Coroutines can suspend on one thread and resume on another thread.
-Even with a single-threaded dispatcher it might be hard to
-figure out what the coroutine was doing, where, and when if you don't have special tooling.
-
-#### Debugging with IDEA
-
-The Coroutine Debugger of the Kotlin plugin simplifies debugging coroutines in IntelliJ IDEA.
-
-> Debugging works for versions 1.3.8 or later of `kotlinx-coroutines-core`.
-
-The **Debug** tool window contains the **Coroutines** tab. In this tab, you can find information about both currently running and suspended coroutines.
-The coroutines are grouped by the dispatcher they are running on.
-
-
-
-With the coroutine debugger, you can:
-* Check the state of each coroutine.
-* See the values of local and captured variables for both running and suspended coroutines.
-* See a full coroutine creation stack, as well as a call stack inside the coroutine. The stack includes all frames with
-variable values, even those that would be lost during standard debugging.
-* Get a full report that contains the state of each coroutine and its stack. To obtain it, right-click inside the **Coroutines** tab, and then click **Get Coroutines Dump**.
-
-To start coroutine debugging, you just need to set breakpoints and run the application in debug mode.
-
-Learn more about coroutines debugging in the [tutorial](https://kotlinlang.org/docs/tutorials/coroutines/debug-coroutines-with-idea.html).
-
-#### Debugging using logging
-
-Another approach to debugging applications with
-threads without Coroutine Debugger is to print the thread name in the log file on each log statement. This feature is universally supported
-by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
-`kotlinx.coroutines` includes debugging facilities to make it easier.
-
-Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val a = async {
- log("I'm computing a piece of the answer")
- 6
- }
- val b = async {
- log("I'm computing another piece of the answer")
- 7
- }
- log("The answer is ${a.await() * b.await()}")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt).
-
-There are three coroutines. The main coroutine (#1) inside `runBlocking`
-and two coroutines computing the deferred values `a` (#2) and `b` (#3).
-They are all executing in the context of `runBlocking` and are confined to the main thread.
-The output of this code is:
-
-```text
-[main @coroutine#2] I'm computing a piece of the answer
-[main @coroutine#3] I'm computing another piece of the answer
-[main @coroutine#1] The answer is 42
-```
-
-<!--- TEST FLEXIBLE_THREAD -->
-
-The `log` function prints the name of the thread in square brackets, and you can see that it is the `main`
-thread with the identifier of the currently executing coroutine appended to it. This identifier
-is consecutively assigned to all created coroutines when the debugging mode is on.
-
-> Debugging mode is also turned on when JVM is run with `-ea` option.
-You can read more about debugging facilities in the documentation of the [DEBUG_PROPERTY_NAME] property.
-
-### Jumping between threads
-
-Run the following code with the `-Dkotlinx.coroutines.debug` JVM option (see [debug](#debugging-coroutines-and-threads)):
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
-
-fun main() {
-//sampleStart
- newSingleThreadContext("Ctx1").use { ctx1 ->
- newSingleThreadContext("Ctx2").use { ctx2 ->
- runBlocking(ctx1) {
- log("Started in ctx1")
- withContext(ctx2) {
- log("Working in ctx2")
- }
- log("Back to ctx1")
- }
- }
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt).
-
-It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
-the other one is using the [withContext] function to change the context of a coroutine while still staying in the
-same coroutine, as you can see in the output below:
-
-```text
-[Ctx1 @coroutine#1] Started in ctx1
-[Ctx2 @coroutine#1] Working in ctx2
-[Ctx1 @coroutine#1] Back to ctx1
-```
-
-<!--- TEST -->
-
-Note that this example also uses the `use` function from the Kotlin standard library to release threads
-created with [newSingleThreadContext] when they are no longer needed.
-
-### Job in the context
-
-The coroutine's [Job] is part of its context, and can be retrieved from it
-using the `coroutineContext[Job]` expression:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- println("My job is ${coroutineContext[Job]}")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt).
-
-In the [debug mode](#debugging-coroutines-and-threads), it outputs something like this:
-
-```
-My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
-```
-
-<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
-
-Note that [isActive] in [CoroutineScope] is just a convenient shortcut for
-`coroutineContext[Job]?.isActive == true`.
-
-### Children of a coroutine
-
-When a coroutine is launched in the [CoroutineScope] of another coroutine,
-it inherits its context via [CoroutineScope.coroutineContext] and
-the [Job] of the new coroutine becomes
-a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
-are recursively cancelled, too.
-
-However, when [GlobalScope] is used to launch a coroutine, there is no parent for the job of the new coroutine.
-It is therefore not tied to the scope it was launched from and operates independently.
-
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- // launch a coroutine to process some kind of incoming request
- val request = launch {
- // it spawns two other jobs, one with GlobalScope
- GlobalScope.launch {
- println("job1: I run in GlobalScope and execute independently!")
- delay(1000)
- println("job1: I am not affected by cancellation of the request")
- }
- // and the other inherits the parent context
- launch {
- delay(100)
- println("job2: I am a child of the request coroutine")
- delay(1000)
- println("job2: I will not execute this line if my parent request is cancelled")
- }
- }
- delay(500)
- request.cancel() // cancel processing of the request
- delay(1000) // delay a second to see what happens
- println("main: Who has survived request cancellation?")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt).
-
-The output of this code is:
-
-```text
-job1: I run in GlobalScope and execute independently!
-job2: I am a child of the request coroutine
-job1: I am not affected by cancellation of the request
-main: Who has survived request cancellation?
-```
-
-<!--- TEST -->
-
-### Parental responsibilities
-
-A parent coroutine always waits for completion of all its children. A parent does not have to explicitly track
-all the children it launches, and it does not have to use [Job.join] to wait for them at the end:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- // launch a coroutine to process some kind of incoming request
- val request = launch {
- repeat(3) { i -> // launch a few children jobs
- launch {
- delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
- println("Coroutine $i is done")
- }
- }
- println("request: I'm done and I don't explicitly join my children that are still active")
- }
- request.join() // wait for completion of the request, including all its children
- println("Now processing of the request is complete")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt).
-
-The result is going to be:
-
-```text
-request: I'm done and I don't explicitly join my children that are still active
-Coroutine 0 is done
-Coroutine 1 is done
-Coroutine 2 is done
-Now processing of the request is complete
-```
-
-<!--- TEST -->
-
-### Naming coroutines for debugging
-
-Automatically assigned ids are good when coroutines log often and you just need to correlate log records
-coming from the same coroutine. However, when a coroutine is tied to the processing of a specific request
-or doing some specific background task, it is better to name it explicitly for debugging purposes.
-The [CoroutineName] context element serves the same purpose as the thread name. It is included in the thread name that
-is executing this coroutine when the [debugging mode](#debugging-coroutines-and-threads) is turned on.
-
-The following example demonstrates this concept:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
-
-fun main() = runBlocking(CoroutineName("main")) {
-//sampleStart
- log("Started main coroutine")
- // run two background value computations
- val v1 = async(CoroutineName("v1coroutine")) {
- delay(500)
- log("Computing v1")
- 252
- }
- val v2 = async(CoroutineName("v2coroutine")) {
- delay(1000)
- log("Computing v2")
- 6
- }
- log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt).
-
-The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
-
-```text
-[main @main#1] Started main coroutine
-[main @v1coroutine#2] Computing v1
-[main @v2coroutine#3] Computing v2
-[main @main#1] The answer for v1 / v2 = 42
-```
-
-<!--- TEST FLEXIBLE_THREAD -->
-
-### Combining context elements
-
-Sometimes we need to define multiple elements for a coroutine context. We can use the `+` operator for that.
-For example, we can launch a coroutine with an explicitly specified dispatcher and an explicitly specified
-name at the same time:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- launch(Dispatchers.Default + CoroutineName("test")) {
- println("I'm working in thread ${Thread.currentThread().name}")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt).
-
-The output of this code with the `-Dkotlinx.coroutines.debug` JVM option is:
-
-```text
-I'm working in thread DefaultDispatcher-worker-1 @test#2
-```
-
-<!--- TEST FLEXIBLE_THREAD -->
-
-### Coroutine scope
-
-Let us put our knowledge about contexts, children and jobs together. Assume that our application has
-an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
-and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
-and update data, do animations, etc. All of these coroutines must be cancelled when the activity is destroyed
-to avoid memory leaks. We, of course, can manipulate contexts and jobs manually to tie the lifecycles of the activity
-and its coroutines, but `kotlinx.coroutines` provides an abstraction encapsulating that: [CoroutineScope].
-You should be already familiar with the coroutine scope as all coroutine builders are declared as extensions on it.
-
-We manage the lifecycles of our coroutines by creating an instance of [CoroutineScope] tied to
-the lifecycle of our activity. A `CoroutineScope` instance can be created by the [CoroutineScope()] or [MainScope()]
-factory functions. The former creates a general-purpose scope, while the latter creates a scope for UI applications and uses
-[Dispatchers.Main] as the default dispatcher:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-class Activity {
- private val mainScope = MainScope()
-
- fun destroy() {
- mainScope.cancel()
- }
- // to be continued ...
-```
-
-</div>
-
-Now, we can launch coroutines in the scope of this `Activity` using the defined `scope`.
-For the demo, we launch ten coroutines that delay for a different time:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
- // class Activity continues
- fun doSomething() {
- // launch ten coroutines for a demo, each working for a different time
- repeat(10) { i ->
- mainScope.launch {
- delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
- println("Coroutine $i is done")
- }
- }
- }
-} // class Activity ends
-```
-
-</div>
-
-In our main function we create the activity, call our test `doSomething` function, and destroy the activity after 500ms.
-This cancels all the coroutines that were launched from `doSomething`. We can see that because after the destruction
-of the activity no more messages are printed, even if we wait a little longer.
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-class Activity {
- private val mainScope = CoroutineScope(Dispatchers.Default) // use Default for test purposes
-
- fun destroy() {
- mainScope.cancel()
- }
-
- fun doSomething() {
- // launch ten coroutines for a demo, each working for a different time
- repeat(10) { i ->
- mainScope.launch {
- delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
- println("Coroutine $i is done")
- }
- }
- }
-} // class Activity ends
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val activity = Activity()
- activity.doSomething() // run test function
- println("Launched coroutines")
- delay(500L) // delay for half a second
- println("Destroying activity!")
- activity.destroy() // cancels all coroutines
- delay(1000) // visually confirm that they don't work
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt).
-
-The output of this example is:
-
-```text
-Launched coroutines
-Coroutine 0 is done
-Coroutine 1 is done
-Destroying activity!
-```
-
-<!--- TEST -->
-
-As you can see, only the first two coroutines print a message and the others are cancelled
-by a single invocation of `job.cancel()` in `Activity.destroy()`.
-
-> Note, that Android has first-party support for coroutine scope in all entities with the lifecycle.
-See [the corresponding documentation](https://developer.android.com/topic/libraries/architecture/coroutines#lifecyclescope).
-
-### Thread-local data
-
-Sometimes it is convenient to have an ability to pass some thread-local data to or between coroutines.
-However, since they are not bound to any particular thread, this will likely lead to boilerplate if done manually.
-
-For [`ThreadLocal`](https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html),
-the [asContextElement] extension function is here for the rescue. It creates an additional context element
-which keeps the value of the given `ThreadLocal` and restores it every time the coroutine switches its context.
-
-It is easy to demonstrate it in action:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-val threadLocal = ThreadLocal<String?>() // declare thread-local variable
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- threadLocal.set("main")
- println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
- val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) {
- println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
- yield()
- println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
- }
- job.join()
- println("Post-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt).
-
-In this example we launch a new coroutine in a background thread pool using [Dispatchers.Default], so
-it works on a different thread from the thread pool, but it still has the value of the thread local variable
-that we specified using `threadLocal.asContextElement(value = "launch")`,
-no matter which thread the coroutine is executed on.
-Thus, the output (with [debug](#debugging-coroutines-and-threads)) is:
-
-```text
-Pre-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
-Launch start, current thread: Thread[DefaultDispatcher-worker-1 @coroutine#2,5,main], thread local value: 'launch'
-After yield, current thread: Thread[DefaultDispatcher-worker-2 @coroutine#2,5,main], thread local value: 'launch'
-Post-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
-```
-
-<!--- TEST FLEXIBLE_THREAD -->
-
-It's easy to forget to set the corresponding context element. The thread-local variable accessed from the coroutine may
-then have an unexpected value, if the thread running the coroutine is different.
-To avoid such situations, it is recommended to use the [ensurePresent] method
-and fail-fast on improper usages.
-
-`ThreadLocal` has first-class support and can be used with any primitive `kotlinx.coroutines` provides.
-It has one key limitation, though: when a thread-local is mutated, a new value is not propagated to the coroutine caller
-(because a context element cannot track all `ThreadLocal` object accesses), and the updated value is lost on the next suspension.
-Use [withContext] to update the value of the thread-local in a coroutine, see [asContextElement] for more details.
-
-Alternatively, a value can be stored in a mutable box like `class Counter(var i: Int)`, which is, in turn,
-stored in a thread-local variable. However, in this case you are fully responsible to synchronize
-potentially concurrent modifications to the variable in this mutable box.
-
-For advanced usage, for example for integration with logging MDC, transactional contexts or any other libraries
-which internally use thread-locals for passing data, see the documentation of the [ThreadContextElement] interface
-that should be implemented.
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
-[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html
-[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
-[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[Dispatchers.Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-unconfined.html
-[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
-[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
-[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/new-single-thread-context.html
-[ExecutorCoroutineDispatcher.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-executor-coroutine-dispatcher/close.html
-[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
-[DEBUG_PROPERTY_NAME]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-d-e-b-u-g_-p-r-o-p-e-r-t-y_-n-a-m-e.html
-[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
-[isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html
-[CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/coroutine-context.html
-[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
-[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html
-[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope.html
-[MainScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html
-[Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html
-[asContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/as-context-element.html
-[ensurePresent]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/ensure-present.html
-[ThreadContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/index.html
-<!--- END -->
+To edit the documentation, open the [topics/coroutine-context-and-dispatchers.md](topics/coroutine-context-and-dispatchers.md) page.
\ No newline at end of file
diff --git a/docs/coroutines-guide.md b/docs/coroutines-guide.md
index 2d15a7b..e2caa75 100644
--- a/docs/coroutines-guide.md
+++ b/docs/coroutines-guide.md
@@ -1,32 +1,3 @@
+The documentation has been moved to the [https://kotlinlang.org/docs/coroutines-guide.html](https://kotlinlang.org/docs/coroutines-guide.html) page.
-Kotlin, as a language, provides only minimal low-level APIs in its standard library to enable various other
-libraries to utilize coroutines. Unlike many other languages with similar capabilities, `async` and `await`
-are not keywords in Kotlin and are not even part of its standard library. Moreover, Kotlin's concept
-of _suspending function_ provides a safer and less error-prone abstraction for asynchronous
-operations than futures and promises.
-
-`kotlinx.coroutines` is a rich library for coroutines developed by JetBrains. It contains a number of high-level
-coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
-
-This is a guide on core features of `kotlinx.coroutines` with a series of examples, divided up into different topics.
-
-In order to use coroutines as well as follow the examples in this guide, you need to add a dependency on the `kotlinx-coroutines-core` module as explained
-[in the project README](../README.md#using-in-your-projects).
-
-## Table of contents
-
-* [Basics](basics.md)
-* [Cancellation and Timeouts](cancellation-and-timeouts.md)
-* [Composing Suspending Functions](composing-suspending-functions.md)
-* [Coroutine Context and Dispatchers](coroutine-context-and-dispatchers.md)
-* [Asynchronous Flow](flow.md)
-* [Channels](channels.md)
-* [Exception Handling and Supervision](exception-handling.md)
-* [Shared Mutable State and Concurrency](shared-mutable-state-and-concurrency.md)
-* [Select Expression (experimental)](select-expression.md)
-
-## Additional references
-
-* [Guide to UI programming with coroutines](../ui/coroutines-guide-ui.md)
-* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
-* [Full kotlinx.coroutines API reference](https://kotlin.github.io/kotlinx.coroutines)
+To edit the documentation, open the [topics/coroutines-guide.md](topics/coroutines-guide.md) page.
\ No newline at end of file
diff --git a/docs/debugging.md b/docs/debugging.md
index 6c846f2..a5dab63 100644
--- a/docs/debugging.md
+++ b/docs/debugging.md
@@ -1,106 +1 @@
-**Table of contents**
-
-<!--- TOC -->
-
-* [Debugging coroutines](#debugging-coroutines)
-* [Debug mode](#debug-mode)
-* [Stacktrace recovery](#stacktrace-recovery)
- * [Stacktrace recovery machinery](#stacktrace-recovery-machinery)
-* [Debug agent](#debug-agent)
- * [Debug agent and Android](#debug-agent-and-android)
-* [Android optimization](#android-optimization)
-
-<!--- END -->
-
-## Debugging coroutines
-
-Debugging asynchronous programs is challenging, because multiple concurrent coroutines are typically working at the same time.
-To help with that, `kotlinx.coroutines` comes with additional features for debugging: debug mode, stacktrace recovery
-and debug agent.
-
-## Debug mode
-
-The first debugging feature of `kotlinx.coroutines` is debug mode.
-It can be enabled either by setting system property [DEBUG_PROPERTY_NAME] or by running Java with enabled assertions (`-ea` flag).
-The latter is helpful to have debug mode enabled by default in unit tests.
-
-Debug mode attaches a unique [name][CoroutineName] to every launched coroutine.
-Coroutine name can be seen in a regular Java debugger,
-in a string representation of the coroutine or in the thread name executing named coroutine.
-Overhead of this feature is negligible and it can be safely turned on by default to simplify logging and diagnostic.
-
-## Stacktrace recovery
-
-Stacktrace recovery is another useful feature of debug mode. It is enabled by default in the debug mode,
-but can be separately disabled by setting `kotlinx.coroutines.stacktrace.recovery` system property to `false`.
-
-Stacktrace recovery tries to stitch asynchronous exception stacktrace with a stacktrace of the receiver by copying it, providing
-not only information where an exception was thrown, but also where it was asynchronously rethrown or caught.
-
-It is easy to demonstrate with actual stacktraces of the same program that awaits asynchronous operation in `main` function
-(runnable code is [here](../kotlinx-coroutines-debug/test/RecoveryExample.kt)):
-
-| Without recovery | With recovery |
-| - | - |
-|  |  |
-
-The only downside of this approach is losing referential transparency of the exception.
-
-### Stacktrace recovery machinery
-
-This section explains the inner mechanism of stacktrace recovery and can be skipped.
-
-When an exception is rethrown between coroutines (e.g. through `withContext` or `Deferred.await` boundary), stacktrace recovery
-machinery tries to create a copy of the original exception (with the original exception as the cause), then rewrite stacktrace
-of the copy with coroutine-related stack frames (using [Throwable.setStackTrace](https://docs.oracle.com/javase/9/docs/api/java/lang/Throwable.html#setStackTrace-java.lang.StackTraceElement:A-))
-and then throws the resulting exception instead of the original one.
-
-Exception copy logic is straightforward:
- 1) If the exception class implements [CopyableThrowable], [CopyableThrowable.createCopy] is used.
- `null` can be returned from `createCopy` to opt-out specific exception from being recovered.
- 2) If the exception class has class-specific fields not inherited from Throwable, the exception is not copied.
- 3) Otherwise, one of the public exception's constructor is invoked reflectively with an optional `initCause` call.
-
-## Debug agent
-
-[kotlinx-coroutines-debug](../kotlinx-coroutines-debug) module provides one of the most powerful debug capabilities in `kotlinx.coroutines`.
-
-This is a separate module with a JVM agent that keeps track of all alive coroutines, introspects and dumps them similar to thread dump command,
-additionally enhancing stacktraces with information where coroutine was created.
-
-The full tutorial of how to use debug agent can be found in the corresponding [readme](../kotlinx-coroutines-debug/README.md).
-
-### Debug agent and Android
-
-Unfortunately, Android runtime does not support Instrument API necessary for `kotlinx-coroutines-debug` to function, triggering `java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;`.
-
-Nevertheless, it will be possible to support debug agent on Android as soon as [GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj) will support android-gradle 3.3
-
-<!---
-Make an exception googlable
-java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;
- at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm$ForLegacyVm.resolve(ByteBuddyAgent.java:1055)
- at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm.resolve(ByteBuddyAgent.java:1038)
- at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:374)
- at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:342)
- at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:328)
- at kotlinx.coroutines.debug.internal.DebugProbesImpl.install(DebugProbesImpl.kt:39)
- at kotlinx.coroutines.debug.DebugProbes.install(DebugProbes.kt:49)
--->
-
-## Android optimization
-
-In optimized (release) builds with R8 version 1.6.0 or later both
-[Debugging mode](../../docs/debugging.md#debug-mode) and
-[Stacktrace recovery](../../docs/debugging.md#stacktrace-recovery)
-are permanently turned off.
-For more details see ["Optimization" section for Android](../ui/kotlinx-coroutines-android/README.md#optimization).
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[DEBUG_PROPERTY_NAME]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-d-e-b-u-g_-p-r-o-p-e-r-t-y_-n-a-m-e.html
-[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html
-[CopyableThrowable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-copyable-throwable/index.html
-[CopyableThrowable.createCopy]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-copyable-throwable/create-copy.html
-<!--- MODULE kotlinx-coroutines-debug -->
-<!--- END -->
+The documentation has been moved to the [topics/debugging.md](topics/debugging.md).
\ No newline at end of file
diff --git a/docs/exception-handling.md b/docs/exception-handling.md
index a307021..77dbac9 100644
--- a/docs/exception-handling.md
+++ b/docs/exception-handling.md
@@ -1,526 +1,3 @@
-<!--- TEST_NAME ExceptionsGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/exception-handling.html](https://kotlinlang.org/docs/exception-handling.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Exception Handling](#exception-handling)
- * [Exception propagation](#exception-propagation)
- * [CoroutineExceptionHandler](#coroutineexceptionhandler)
- * [Cancellation and exceptions](#cancellation-and-exceptions)
- * [Exceptions aggregation](#exceptions-aggregation)
- * [Supervision](#supervision)
- * [Supervision job](#supervision-job)
- * [Supervision scope](#supervision-scope)
- * [Exceptions in supervised coroutines](#exceptions-in-supervised-coroutines)
-
-<!--- END -->
-
-## Exception Handling
-
-This section covers exception handling and cancellation on exceptions.
-We already know that a cancelled coroutine throws [CancellationException] in suspension points and that it
-is ignored by the coroutines' machinery. Here we look at what happens if an exception is thrown during cancellation or multiple children of the same
-coroutine throw an exception.
-
-### Exception propagation
-
-Coroutine builders come in two flavors: propagating exceptions automatically ([launch] and [actor]) or
-exposing them to users ([async] and [produce]).
-When these builders are used to create a _root_ coroutine, that is not a _child_ of another coroutine,
-the former builders treat exceptions as **uncaught** exceptions, similar to Java's `Thread.uncaughtExceptionHandler`,
-while the latter are relying on the user to consume the final
-exception, for example via [await][Deferred.await] or [receive][ReceiveChannel.receive]
-([produce] and [receive][ReceiveChannel.receive] are covered later in [Channels](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/channels.md) section).
-
-It can be demonstrated by a simple example that creates root coroutines using the [GlobalScope]:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
- val job = GlobalScope.launch { // root coroutine with launch
- println("Throwing exception from launch")
- throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
- }
- job.join()
- println("Joined failed job")
- val deferred = GlobalScope.async { // root coroutine with async
- println("Throwing exception from async")
- throw ArithmeticException() // Nothing is printed, relying on user to call await
- }
- try {
- deferred.await()
- println("Unreached")
- } catch (e: ArithmeticException) {
- println("Caught ArithmeticException")
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt).
-
-The output of this code is (with [debug](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/coroutine-context-and-dispatchers.md#debugging-coroutines-and-threads)):
-
-```text
-Throwing exception from launch
-Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
-Joined failed job
-Throwing exception from async
-Caught ArithmeticException
-```
-
-<!--- TEST EXCEPTION-->
-
-### CoroutineExceptionHandler
-
-It is possible to customize the default behavior of printing **uncaught** exceptions to the console.
-[CoroutineExceptionHandler] context element on a _root_ coroutine can be used as generic `catch` block for
-this root coroutine and all its children where custom exception handling may take place.
-It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
-You cannot recover from the exception in the `CoroutineExceptionHandler`. The coroutine had already completed
-with the corresponding exception when the handler is called. Normally, the handler is used to
-log the exception, show some kind of error message, terminate, and/or restart the application.
-
-On JVM it is possible to redefine global exception handler for all coroutines by registering [CoroutineExceptionHandler] via
-[`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
-Global exception handler is similar to
-[`Thread.defaultUncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler))
-which is used when no more specific handlers are registered.
-On Android, `uncaughtExceptionPreHandler` is installed as a global coroutine exception handler.
-
-`CoroutineExceptionHandler` is invoked only on **uncaught** exceptions — exceptions that were not handled in any other way.
-In particular, all _children_ coroutines (coroutines created in the context of another [Job]) delegate handling of
-their exceptions to their parent coroutine, which also delegates to the parent, and so on until the root,
-so the `CoroutineExceptionHandler` installed in their context is never used.
-In addition to that, [async] builder always catches all exceptions and represents them in the resulting [Deferred] object,
-so its `CoroutineExceptionHandler` has no effect either.
-
-> Coroutines running in supervision scope do not propagate exceptions to their parent and are
-excluded from this rule. A further [Supervision](#supervision) section of this document gives more details.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val handler = CoroutineExceptionHandler { _, exception ->
- println("CoroutineExceptionHandler got $exception")
- }
- val job = GlobalScope.launch(handler) { // root coroutine, running in GlobalScope
- throw AssertionError()
- }
- val deferred = GlobalScope.async(handler) { // also root, but async instead of launch
- throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
- }
- joinAll(job, deferred)
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt).
-
-The output of this code is:
-
-```text
-CoroutineExceptionHandler got java.lang.AssertionError
-```
-
-<!--- TEST-->
-
-### Cancellation and exceptions
-
-Cancellation is closely related to exceptions. Coroutines internally use `CancellationException` for cancellation, these
-exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can
-be obtained by `catch` block.
-When a coroutine is cancelled using [Job.cancel], it terminates, but it does not cancel its parent.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val job = launch {
- val child = launch {
- try {
- delay(Long.MAX_VALUE)
- } finally {
- println("Child is cancelled")
- }
- }
- yield()
- println("Cancelling child")
- child.cancel()
- child.join()
- yield()
- println("Parent is not cancelled")
- }
- job.join()
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt).
-
-The output of this code is:
-
-```text
-Cancelling child
-Child is cancelled
-Parent is not cancelled
-```
-
-<!--- TEST-->
-
-If a coroutine encounters an exception other than `CancellationException`, it cancels its parent with that exception.
-This behaviour cannot be overridden and is used to provide stable coroutines hierarchies for
-[structured concurrency](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/composing-suspending-functions.md#structured-concurrency-with-async).
-[CoroutineExceptionHandler] implementation is not used for child coroutines.
-
-> In these examples [CoroutineExceptionHandler] is always installed to a coroutine
-that is created in [GlobalScope]. It does not make sense to install an exception handler to a coroutine that
-is launched in the scope of the main [runBlocking], since the main coroutine is going to be always cancelled
-when its child completes with exception despite the installed handler.
-
-The original exception is handled by the parent only when all its children terminate,
-which is demonstrated by the following example.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
-//sampleStart
- val handler = CoroutineExceptionHandler { _, exception ->
- println("CoroutineExceptionHandler got $exception")
- }
- val job = GlobalScope.launch(handler) {
- launch { // the first child
- try {
- delay(Long.MAX_VALUE)
- } finally {
- withContext(NonCancellable) {
- println("Children are cancelled, but exception is not handled until all children terminate")
- delay(100)
- println("The first child finished its non cancellable block")
- }
- }
- }
- launch { // the second child
- delay(10)
- println("Second child throws an exception")
- throw ArithmeticException()
- }
- }
- job.join()
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt).
-
-The output of this code is:
-
-```text
-Second child throws an exception
-Children are cancelled, but exception is not handled until all children terminate
-The first child finished its non cancellable block
-CoroutineExceptionHandler got java.lang.ArithmeticException
-```
-<!--- TEST-->
-
-### Exceptions aggregation
-
-When multiple children of a coroutine fail with an exception, the
-general rule is "the first exception wins", so the first exception gets handled.
-All additional exceptions that happen after the first one are attached to the first exception as suppressed ones.
-
-<!--- INCLUDE
-import kotlinx.coroutines.exceptions.*
--->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import java.io.*
-
-fun main() = runBlocking {
- val handler = CoroutineExceptionHandler { _, exception ->
- println("CoroutineExceptionHandler got $exception with suppressed ${exception.suppressed.contentToString()}")
- }
- val job = GlobalScope.launch(handler) {
- launch {
- try {
- delay(Long.MAX_VALUE) // it gets cancelled when another sibling fails with IOException
- } finally {
- throw ArithmeticException() // the second exception
- }
- }
- launch {
- delay(100)
- throw IOException() // the first exception
- }
- delay(Long.MAX_VALUE)
- }
- job.join()
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt).
-
-> Note: This above code will work properly only on JDK7+ that supports `suppressed` exceptions
-
-The output of this code is:
-
-```text
-CoroutineExceptionHandler got java.io.IOException with suppressed [java.lang.ArithmeticException]
-```
-
-<!--- TEST-->
-
-> Note that this mechanism currently only works on Java version 1.7+.
-The JS and Native restrictions are temporary and will be lifted in the future.
-
-Cancellation exceptions are transparent and are unwrapped by default:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import java.io.*
-
-fun main() = runBlocking {
-//sampleStart
- val handler = CoroutineExceptionHandler { _, exception ->
- println("CoroutineExceptionHandler got $exception")
- }
- val job = GlobalScope.launch(handler) {
- val inner = launch { // all this stack of coroutines will get cancelled
- launch {
- launch {
- throw IOException() // the original exception
- }
- }
- }
- try {
- inner.join()
- } catch (e: CancellationException) {
- println("Rethrowing CancellationException with original cause")
- throw e // cancellation exception is rethrown, yet the original IOException gets to the handler
- }
- }
- job.join()
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt).
-
-The output of this code is:
-
-```text
-Rethrowing CancellationException with original cause
-CoroutineExceptionHandler got java.io.IOException
-```
-<!--- TEST-->
-
-### Supervision
-
-As we have studied before, cancellation is a bidirectional relationship propagating through the whole
-hierarchy of coroutines. Let us take a look at the case when unidirectional cancellation is required.
-
-A good example of such a requirement is a UI component with the job defined in its scope. If any of the UI's child tasks
-have failed, it is not always necessary to cancel (effectively kill) the whole UI component,
-but if UI component is destroyed (and its job is cancelled), then it is necessary to fail all child jobs as their results are no longer needed.
-
-Another example is a server process that spawns multiple child jobs and needs to _supervise_
-their execution, tracking their failures and only restarting the failed ones.
-
-#### Supervision job
-
-The [SupervisorJob][SupervisorJob()] can be used for these purposes.
-It is similar to a regular [Job][Job()] with the only exception that cancellation is propagated
-only downwards. This can easily be demonstrated using the following example:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
- val supervisor = SupervisorJob()
- with(CoroutineScope(coroutineContext + supervisor)) {
- // launch the first child -- its exception is ignored for this example (don't do this in practice!)
- val firstChild = launch(CoroutineExceptionHandler { _, _ -> }) {
- println("The first child is failing")
- throw AssertionError("The first child is cancelled")
- }
- // launch the second child
- val secondChild = launch {
- firstChild.join()
- // Cancellation of the first child is not propagated to the second child
- println("The first child is cancelled: ${firstChild.isCancelled}, but the second one is still active")
- try {
- delay(Long.MAX_VALUE)
- } finally {
- // But cancellation of the supervisor is propagated
- println("The second child is cancelled because the supervisor was cancelled")
- }
- }
- // wait until the first child fails & completes
- firstChild.join()
- println("Cancelling the supervisor")
- supervisor.cancel()
- secondChild.join()
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt).
-
-The output of this code is:
-
-```text
-The first child is failing
-The first child is cancelled: true, but the second one is still active
-Cancelling the supervisor
-The second child is cancelled because the supervisor was cancelled
-```
-<!--- TEST-->
-
-
-#### Supervision scope
-
-Instead of [coroutineScope][_coroutineScope], we can use [supervisorScope][_supervisorScope] for _scoped_ concurrency. It propagates the cancellation
-in one direction only and cancels all its children only if it failed itself. It also waits for all children before completion
-just like [coroutineScope][_coroutineScope] does.
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-import kotlin.coroutines.*
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
- try {
- supervisorScope {
- val child = launch {
- try {
- println("The child is sleeping")
- delay(Long.MAX_VALUE)
- } finally {
- println("The child is cancelled")
- }
- }
- // Give our child a chance to execute and print using yield
- yield()
- println("Throwing an exception from the scope")
- throw AssertionError()
- }
- } catch(e: AssertionError) {
- println("Caught an assertion error")
- }
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt).
-
-The output of this code is:
-
-```text
-The child is sleeping
-Throwing an exception from the scope
-The child is cancelled
-Caught an assertion error
-```
-<!--- TEST-->
-
-#### Exceptions in supervised coroutines
-
-Another crucial difference between regular and supervisor jobs is exception handling.
-Every child should handle its exceptions by itself via the exception handling mechanism.
-This difference comes from the fact that child's failure does not propagate to the parent.
-It means that coroutines launched directly inside the [supervisorScope][_supervisorScope] _do_ use the [CoroutineExceptionHandler]
-that is installed in their scope in the same way as root coroutines do
-(see the [CoroutineExceptionHandler](#coroutineexceptionhandler) section for details).
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-import kotlin.coroutines.*
-import kotlinx.coroutines.*
-
-fun main() = runBlocking {
- val handler = CoroutineExceptionHandler { _, exception ->
- println("CoroutineExceptionHandler got $exception")
- }
- supervisorScope {
- val child = launch(handler) {
- println("The child throws an exception")
- throw AssertionError()
- }
- println("The scope is completing")
- }
- println("The scope is completed")
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt).
-
-The output of this code is:
-
-```text
-The scope is completing
-The child throws an exception
-CoroutineExceptionHandler got java.lang.AssertionError
-The scope is completed
-```
-<!--- TEST-->
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
-[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
-[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html
-[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
-[CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/index.html
-[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
-[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html
-[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
-[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[SupervisorJob()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-supervisor-job.html
-[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job.html
-[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
-[_supervisorScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/supervisor-scope.html
-<!--- INDEX kotlinx.coroutines.channels -->
-[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
-[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
-[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
-<!--- END -->
+To edit the documentation, open the [topics/exception-handling.md](topics/exception-handling.md) page.
\ No newline at end of file
diff --git a/docs/flow.md b/docs/flow.md
index 4374e7a..400a15f 100644
--- a/docs/flow.md
+++ b/docs/flow.md
@@ -1,1979 +1,3 @@
-<!--- TEST_NAME FlowGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/flow.html](https://kotlinlang.org/docs/flow.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Asynchronous Flow](#asynchronous-flow)
- * [Representing multiple values](#representing-multiple-values)
- * [Sequences](#sequences)
- * [Suspending functions](#suspending-functions)
- * [Flows](#flows)
- * [Flows are cold](#flows-are-cold)
- * [Flow cancellation basics](#flow-cancellation-basics)
- * [Flow builders](#flow-builders)
- * [Intermediate flow operators](#intermediate-flow-operators)
- * [Transform operator](#transform-operator)
- * [Size-limiting operators](#size-limiting-operators)
- * [Terminal flow operators](#terminal-flow-operators)
- * [Flows are sequential](#flows-are-sequential)
- * [Flow context](#flow-context)
- * [Wrong emission withContext](#wrong-emission-withcontext)
- * [flowOn operator](#flowon-operator)
- * [Buffering](#buffering)
- * [Conflation](#conflation)
- * [Processing the latest value](#processing-the-latest-value)
- * [Composing multiple flows](#composing-multiple-flows)
- * [Zip](#zip)
- * [Combine](#combine)
- * [Flattening flows](#flattening-flows)
- * [flatMapConcat](#flatmapconcat)
- * [flatMapMerge](#flatmapmerge)
- * [flatMapLatest](#flatmaplatest)
- * [Flow exceptions](#flow-exceptions)
- * [Collector try and catch](#collector-try-and-catch)
- * [Everything is caught](#everything-is-caught)
- * [Exception transparency](#exception-transparency)
- * [Transparent catch](#transparent-catch)
- * [Catching declaratively](#catching-declaratively)
- * [Flow completion](#flow-completion)
- * [Imperative finally block](#imperative-finally-block)
- * [Declarative handling](#declarative-handling)
- * [Successful completion](#successful-completion)
- * [Imperative versus declarative](#imperative-versus-declarative)
- * [Launching flow](#launching-flow)
- * [Flow cancellation checks](#flow-cancellation-checks)
- * [Making busy flow cancellable](#making-busy-flow-cancellable)
- * [Flow and Reactive Streams](#flow-and-reactive-streams)
-
-<!--- END -->
-
-## Asynchronous Flow
-
-A suspending function asynchronously returns a single value, but how can we return
-multiple asynchronously computed values? This is where Kotlin Flows come in.
-
-### Representing multiple values
-
-Multiple values can be represented in Kotlin using [collections].
-For example, we can have a `simple` function that returns a [List]
-of three numbers and then print them all using [forEach]:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-fun simple(): List<Int> = listOf(1, 2, 3)
-
-fun main() {
- simple().forEach { value -> println(value) }
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt).
-
-This code outputs:
-
-```text
-1
-2
-3
-```
-
-<!--- TEST -->
-
-#### Sequences
-
-If we are computing the numbers with some CPU-consuming blocking code
-(each computation taking 100ms), then we can represent the numbers using a [Sequence]:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-fun simple(): Sequence<Int> = sequence { // sequence builder
- for (i in 1..3) {
- Thread.sleep(100) // pretend we are computing it
- yield(i) // yield next value
- }
-}
-
-fun main() {
- simple().forEach { value -> println(value) }
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt).
-
-This code outputs the same numbers, but it waits 100ms before printing each one.
-
-<!--- TEST
-1
-2
-3
--->
-
-#### Suspending functions
-
-However, this computation blocks the main thread that is running the code.
-When these values are computed by asynchronous code we can mark the `simple` function with a `suspend` modifier,
-so that it can perform its work without blocking and return the result as a list:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-
-//sampleStart
-suspend fun simple(): List<Int> {
- delay(1000) // pretend we are doing something asynchronous here
- return listOf(1, 2, 3)
-}
-
-fun main() = runBlocking<Unit> {
- simple().forEach { value -> println(value) }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt).
-
-This code prints the numbers after waiting for a second.
-
-<!--- TEST
-1
-2
-3
--->
-
-#### Flows
-
-Using the `List<Int>` result type, means we can only return all the values at once. To represent
-the stream of values that are being asynchronously computed, we can use a [`Flow<Int>`][Flow] type just like we would use the `Sequence<Int>` type for synchronously computed values:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow { // flow builder
- for (i in 1..3) {
- delay(100) // pretend we are doing something useful here
- emit(i) // emit next value
- }
-}
-
-fun main() = runBlocking<Unit> {
- // Launch a concurrent coroutine to check if the main thread is blocked
- launch {
- for (k in 1..3) {
- println("I'm not blocked $k")
- delay(100)
- }
- }
- // Collect the flow
- simple().collect { value -> println(value) }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt).
-
-This code waits 100ms before printing each number without blocking the main thread. This is verified
-by printing "I'm not blocked" every 100ms from a separate coroutine that is running in the main thread:
-
-```text
-I'm not blocked 1
-1
-I'm not blocked 2
-2
-I'm not blocked 3
-3
-```
-
-<!--- TEST -->
-
-Notice the following differences in the code with the [Flow] from the earlier examples:
-
-* A builder function for [Flow] type is called [flow][_flow].
-* Code inside the `flow { ... }` builder block can suspend.
-* The `simple` function is no longer marked with `suspend` modifier.
-* Values are _emitted_ from the flow using [emit][FlowCollector.emit] function.
-* Values are _collected_ from the flow using [collect][collect] function.
-
-> We can replace [delay] with `Thread.sleep` in the body of `simple`'s `flow { ... }` and see that the main
-thread is blocked in this case.
-
-### Flows are cold
-
-Flows are _cold_ streams similar to sequences — the code inside a [flow][_flow] builder does not
-run until the flow is collected. This becomes clear in the following example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- println("Flow started")
- for (i in 1..3) {
- delay(100)
- emit(i)
- }
-}
-
-fun main() = runBlocking<Unit> {
- println("Calling simple function...")
- val flow = simple()
- println("Calling collect...")
- flow.collect { value -> println(value) }
- println("Calling collect again...")
- flow.collect { value -> println(value) }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt).
-
-Which prints:
-
-```text
-Calling simple function...
-Calling collect...
-Flow started
-1
-2
-3
-Calling collect again...
-Flow started
-1
-2
-3
-```
-
-<!--- TEST -->
-
-This is a key reason the `simple` function (which returns a flow) is not marked with `suspend` modifier.
-By itself, `simple()` call returns quickly and does not wait for anything. The flow starts every time it is collected,
-that is why we see "Flow started" when we call `collect` again.
-
-### Flow cancellation basics
-
-Flow adheres to the general cooperative cancellation of coroutines. As usual, flow collection can be
-cancelled when the flow is suspended in a cancellable suspending function (like [delay]).
-The following example shows how the flow gets cancelled on a timeout when running in a [withTimeoutOrNull] block
-and stops executing its code:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- delay(100)
- println("Emitting $i")
- emit(i)
- }
-}
-
-fun main() = runBlocking<Unit> {
- withTimeoutOrNull(250) { // Timeout after 250ms
- simple().collect { value -> println(value) }
- }
- println("Done")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt).
-
-Notice how only two numbers get emitted by the flow in the `simple` function, producing the following output:
-
-```text
-Emitting 1
-1
-Emitting 2
-2
-Done
-```
-
-<!--- TEST -->
-
-See [Flow cancellation checks](#flow-cancellation-checks) section for more details.
-
-### Flow builders
-
-The `flow { ... }` builder from the previous examples is the most basic one. There are other builders for
-easier declaration of flows:
-
-* [flowOf] builder that defines a flow emitting a fixed set of values.
-* Various collections and sequences can be converted to flows using `.asFlow()` extension functions.
-
-So, the example that prints the numbers from 1 to 3 from a flow can be written as:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- // Convert an integer range to a flow
- (1..3).asFlow().collect { value -> println(value) }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt).
-
-<!--- TEST
-1
-2
-3
--->
-
-### Intermediate flow operators
-
-Flows can be transformed with operators, just as you would with collections and sequences.
-Intermediate operators are applied to an upstream flow and return a downstream flow.
-These operators are cold, just like flows are. A call to such an operator is not
-a suspending function itself. It works quickly, returning the definition of a new transformed flow.
-
-The basic operators have familiar names like [map] and [filter].
-The important difference to sequences is that blocks of
-code inside these operators can call suspending functions.
-
-For example, a flow of incoming requests can be
-mapped to the results with the [map] operator, even when performing a request is a long-running
-operation that is implemented by a suspending function:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-suspend fun performRequest(request: Int): String {
- delay(1000) // imitate long-running asynchronous work
- return "response $request"
-}
-
-fun main() = runBlocking<Unit> {
- (1..3).asFlow() // a flow of requests
- .map { request -> performRequest(request) }
- .collect { response -> println(response) }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt).
-
-It produces the following three lines, each line appearing after each second:
-
-```text
-response 1
-response 2
-response 3
-```
-
-<!--- TEST -->
-
-#### Transform operator
-
-Among the flow transformation operators, the most general one is called [transform]. It can be used to imitate
-simple transformations like [map] and [filter], as well as implement more complex transformations.
-Using the `transform` operator, we can [emit][FlowCollector.emit] arbitrary values an arbitrary number of times.
-
-For example, using `transform` we can emit a string before performing a long-running asynchronous request
-and follow it with a response:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-suspend fun performRequest(request: Int): String {
- delay(1000) // imitate long-running asynchronous work
- return "response $request"
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- (1..3).asFlow() // a flow of requests
- .transform { request ->
- emit("Making request $request")
- emit(performRequest(request))
- }
- .collect { response -> println(response) }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt).
-
-The output of this code is:
-
-```text
-Making request 1
-response 1
-Making request 2
-response 2
-Making request 3
-response 3
-```
-
-<!--- TEST -->
-
-#### Size-limiting operators
-
-Size-limiting intermediate operators like [take] cancel the execution of the flow when the corresponding limit
-is reached. Cancellation in coroutines is always performed by throwing an exception, so that all the resource-management
-functions (like `try { ... } finally { ... }` blocks) operate normally in case of cancellation:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun numbers(): Flow<Int> = flow {
- try {
- emit(1)
- emit(2)
- println("This line will not execute")
- emit(3)
- } finally {
- println("Finally in numbers")
- }
-}
-
-fun main() = runBlocking<Unit> {
- numbers()
- .take(2) // take only the first two
- .collect { value -> println(value) }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt).
-
-The output of this code clearly shows that the execution of the `flow { ... }` body in the `numbers()` function
-stopped after emitting the second number:
-
-```text
-1
-2
-Finally in numbers
-```
-
-<!--- TEST -->
-
-### Terminal flow operators
-
-Terminal operators on flows are _suspending functions_ that start a collection of the flow.
-The [collect] operator is the most basic one, but there are other terminal operators, which can make it easier:
-
-* Conversion to various collections like [toList] and [toSet].
-* Operators to get the [first] value and to ensure that a flow emits a [single] value.
-* Reducing a flow to a value with [reduce] and [fold].
-
-For example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val sum = (1..5).asFlow()
- .map { it * it } // squares of numbers from 1 to 5
- .reduce { a, b -> a + b } // sum them (terminal operator)
- println(sum)
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt).
-
-Prints a single number:
-
-```text
-55
-```
-
-<!--- TEST -->
-
-### Flows are sequential
-
-Each individual collection of a flow is performed sequentially unless special operators that operate
-on multiple flows are used. The collection works directly in the coroutine that calls a terminal operator.
-No new coroutines are launched by default.
-Each emitted value is processed by all the intermediate operators from
-upstream to downstream and is then delivered to the terminal operator after.
-
-See the following example that filters the even integers and maps them to strings:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- (1..5).asFlow()
- .filter {
- println("Filter $it")
- it % 2 == 0
- }
- .map {
- println("Map $it")
- "string $it"
- }.collect {
- println("Collect $it")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt).
-
-Producing:
-
-```text
-Filter 1
-Filter 2
-Map 2
-Collect string 2
-Filter 3
-Filter 4
-Map 4
-Collect string 4
-Filter 5
-```
-
-<!--- TEST -->
-
-### Flow context
-
-Collection of a flow always happens in the context of the calling coroutine. For example, if there is
-a `simple` flow, then the following code runs in the context specified
-by the author of this code, regardless of the implementation details of the `simple` flow:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-withContext(context) {
- simple().collect { value ->
- println(value) // run in the specified context
- }
-}
-```
-
-</div>
-
-<!--- CLEAR -->
-
-This property of a flow is called _context preservation_.
-
-So, by default, code in the `flow { ... }` builder runs in the context that is provided by a collector
-of the corresponding flow. For example, consider the implementation of a `simple` function that prints the thread
-it is called on and emits three numbers:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- log("Started simple flow")
- for (i in 1..3) {
- emit(i)
- }
-}
-
-fun main() = runBlocking<Unit> {
- simple().collect { value -> log("Collected $value") }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt).
-
-Running this code produces:
-
-```text
-[main @coroutine#1] Started simple flow
-[main @coroutine#1] Collected 1
-[main @coroutine#1] Collected 2
-[main @coroutine#1] Collected 3
-```
-
-<!--- TEST FLEXIBLE_THREAD -->
-
-Since `simple().collect` is called from the main thread, the body of `simple`'s flow is also called in the main thread.
-This is the perfect default for fast-running or asynchronous code that does not care about the execution context and
-does not block the caller.
-
-#### Wrong emission withContext
-
-However, the long-running CPU-consuming code might need to be executed in the context of [Dispatchers.Default] and UI-updating
-code might need to be executed in the context of [Dispatchers.Main]. Usually, [withContext] is used
-to change the context in the code using Kotlin coroutines, but code in the `flow { ... }` builder has to honor the context
-preservation property and is not allowed to [emit][FlowCollector.emit] from a different context.
-
-Try running the following code:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- // The WRONG way to change context for CPU-consuming code in flow builder
- kotlinx.coroutines.withContext(Dispatchers.Default) {
- for (i in 1..3) {
- Thread.sleep(100) // pretend we are computing it in CPU-consuming way
- emit(i) // emit next value
- }
- }
-}
-
-fun main() = runBlocking<Unit> {
- simple().collect { value -> println(value) }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt).
-
-This code produces the following exception:
-
-```text
-Exception in thread "main" java.lang.IllegalStateException: Flow invariant is violated:
- Flow was collected in [CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@5511c7f8, BlockingEventLoop@2eac3323],
- but emission happened in [CoroutineId(1), "coroutine#1":DispatchedCoroutine{Active}@2dae0000, Dispatchers.Default].
- Please refer to 'flow' documentation or use 'flowOn' instead
- at ...
-```
-
-<!--- TEST EXCEPTION -->
-
-#### flowOn operator
-
-The exception refers to the [flowOn] function that shall be used to change the context of the flow emission.
-The correct way to change the context of a flow is shown in the example below, which also prints the
-names of the corresponding threads to show how it all works:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- Thread.sleep(100) // pretend we are computing it in CPU-consuming way
- log("Emitting $i")
- emit(i) // emit next value
- }
-}.flowOn(Dispatchers.Default) // RIGHT way to change context for CPU-consuming code in flow builder
-
-fun main() = runBlocking<Unit> {
- simple().collect { value ->
- log("Collected $value")
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt).
-
-Notice how `flow { ... }` works in the background thread, while collection happens in the main thread:
-
-<!--- TEST FLEXIBLE_THREAD
-[DefaultDispatcher-worker-1 @coroutine#2] Emitting 1
-[main @coroutine#1] Collected 1
-[DefaultDispatcher-worker-1 @coroutine#2] Emitting 2
-[main @coroutine#1] Collected 2
-[DefaultDispatcher-worker-1 @coroutine#2] Emitting 3
-[main @coroutine#1] Collected 3
--->
-
-Another thing to observe here is that the [flowOn] operator has changed the default sequential nature of the flow.
-Now collection happens in one coroutine ("coroutine#1") and emission happens in another coroutine
-("coroutine#2") that is running in another thread concurrently with the collecting coroutine. The [flowOn] operator
-creates another coroutine for an upstream flow when it has to change the [CoroutineDispatcher] in its context.
-
-### Buffering
-
-Running different parts of a flow in different coroutines can be helpful from the standpoint of the overall time it takes
-to collect the flow, especially when long-running asynchronous operations are involved. For example, consider a case when
-the emission by a `simple` flow is slow, taking 100 ms to produce an element; and collector is also slow,
-taking 300 ms to process an element. Let's see how long it takes to collect such a flow with three numbers:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import kotlin.system.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- delay(100) // pretend we are asynchronously waiting 100 ms
- emit(i) // emit next value
- }
-}
-
-fun main() = runBlocking<Unit> {
- val time = measureTimeMillis {
- simple().collect { value ->
- delay(300) // pretend we are processing it for 300 ms
- println(value)
- }
- }
- println("Collected in $time ms")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt).
-
-It produces something like this, with the whole collection taking around 1200 ms (three numbers, 400 ms for each):
-
-```text
-1
-2
-3
-Collected in 1220 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-We can use a [buffer] operator on a flow to run emitting code of the `simple` flow concurrently with collecting code,
-as opposed to running them sequentially:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import kotlin.system.*
-
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- delay(100) // pretend we are asynchronously waiting 100 ms
- emit(i) // emit next value
- }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- simple()
- .buffer() // buffer emissions, don't wait
- .collect { value ->
- delay(300) // pretend we are processing it for 300 ms
- println(value)
- }
- }
- println("Collected in $time ms")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt).
-
-It produces the same numbers just faster, as we have effectively created a processing pipeline,
-having to only wait 100 ms for the first number and then spending only 300 ms to process
-each number. This way it takes around 1000 ms to run:
-
-```text
-1
-2
-3
-Collected in 1071 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-> Note that the [flowOn] operator uses the same buffering mechanism when it has to change a [CoroutineDispatcher],
-but here we explicitly request buffering without changing the execution context.
-
-#### Conflation
-
-When a flow represents partial results of the operation or operation status updates, it may not be necessary
-to process each value, but instead, only most recent ones. In this case, the [conflate] operator can be used to skip
-intermediate values when a collector is too slow to process them. Building on the previous example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import kotlin.system.*
-
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- delay(100) // pretend we are asynchronously waiting 100 ms
- emit(i) // emit next value
- }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- simple()
- .conflate() // conflate emissions, don't process each one
- .collect { value ->
- delay(300) // pretend we are processing it for 300 ms
- println(value)
- }
- }
- println("Collected in $time ms")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt).
-
-We see that while the first number was still being processed the second, and third were already produced, so
-the second one was _conflated_ and only the most recent (the third one) was delivered to the collector:
-
-```text
-1
-3
-Collected in 758 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-#### Processing the latest value
-
-Conflation is one way to speed up processing when both the emitter and collector are slow. It does it by dropping emitted values.
-The other way is to cancel a slow collector and restart it every time a new value is emitted. There is
-a family of `xxxLatest` operators that perform the same essential logic of a `xxx` operator, but cancel the
-code in their block on a new value. Let's try changing [conflate] to [collectLatest] in the previous example:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import kotlin.system.*
-
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- delay(100) // pretend we are asynchronously waiting 100 ms
- emit(i) // emit next value
- }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val time = measureTimeMillis {
- simple()
- .collectLatest { value -> // cancel & restart on the latest value
- println("Collecting $value")
- delay(300) // pretend we are processing it for 300 ms
- println("Done $value")
- }
- }
- println("Collected in $time ms")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt).
-
-Since the body of [collectLatest] takes 300 ms, but new values are emitted every 100 ms, we see that the block
-is run on every value, but completes only for the last value:
-
-```text
-Collecting 1
-Collecting 2
-Collecting 3
-Done 3
-Collected in 741 ms
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-### Composing multiple flows
-
-There are lots of ways to compose multiple flows.
-
-#### Zip
-
-Just like the [Sequence.zip] extension function in the Kotlin standard library,
-flows have a [zip] operator that combines the corresponding values of two flows:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val nums = (1..3).asFlow() // numbers 1..3
- val strs = flowOf("one", "two", "three") // strings
- nums.zip(strs) { a, b -> "$a -> $b" } // compose a single string
- .collect { println(it) } // collect and print
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt).
-
-This example prints:
-
-```text
-1 -> one
-2 -> two
-3 -> three
-```
-
-<!--- TEST -->
-
-#### Combine
-
-When flow represents the most recent value of a variable or operation (see also the related
-section on [conflation](#conflation)), it might be needed to perform a computation that depends on
-the most recent values of the corresponding flows and to recompute it whenever any of the upstream
-flows emit a value. The corresponding family of operators is called [combine].
-
-For example, if the numbers in the previous example update every 300ms, but strings update every 400 ms,
-then zipping them using the [zip] operator will still produce the same result,
-albeit results that are printed every 400 ms:
-
-> We use a [onEach] intermediate operator in this example to delay each element and make the code
-that emits sample flows more declarative and shorter.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val nums = (1..3).asFlow().onEach { delay(300) } // numbers 1..3 every 300 ms
- val strs = flowOf("one", "two", "three").onEach { delay(400) } // strings every 400 ms
- val startTime = System.currentTimeMillis() // remember the start time
- nums.zip(strs) { a, b -> "$a -> $b" } // compose a single string with "zip"
- .collect { value -> // collect and print
- println("$value at ${System.currentTimeMillis() - startTime} ms from start")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt).
-
-<!--- TEST ARBITRARY_TIME
-1 -> one at 437 ms from start
-2 -> two at 837 ms from start
-3 -> three at 1243 ms from start
--->
-
-However, when using a [combine] operator here instead of a [zip]:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val nums = (1..3).asFlow().onEach { delay(300) } // numbers 1..3 every 300 ms
- val strs = flowOf("one", "two", "three").onEach { delay(400) } // strings every 400 ms
- val startTime = System.currentTimeMillis() // remember the start time
- nums.combine(strs) { a, b -> "$a -> $b" } // compose a single string with "combine"
- .collect { value -> // collect and print
- println("$value at ${System.currentTimeMillis() - startTime} ms from start")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt).
-
-We get quite a different output, where a line is printed at each emission from either `nums` or `strs` flows:
-
-```text
-1 -> one at 452 ms from start
-2 -> one at 651 ms from start
-2 -> two at 854 ms from start
-3 -> two at 952 ms from start
-3 -> three at 1256 ms from start
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-### Flattening flows
-
-Flows represent asynchronously received sequences of values, so it is quite easy to get in a situation where
-each value triggers a request for another sequence of values. For example, we can have the following
-function that returns a flow of two strings 500 ms apart:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun requestFlow(i: Int): Flow<String> = flow {
- emit("$i: First")
- delay(500) // wait 500 ms
- emit("$i: Second")
-}
-```
-
-</div>
-
-<!--- CLEAR -->
-
-Now if we have a flow of three integers and call `requestFlow` for each of them like this:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-(1..3).asFlow().map { requestFlow(it) }
-```
-
-</div>
-
-<!--- CLEAR -->
-
-Then we end up with a flow of flows (`Flow<Flow<String>>`) that needs to be _flattened_ into a single flow for
-further processing. Collections and sequences have [flatten][Sequence.flatten] and [flatMap][Sequence.flatMap]
-operators for this. However, due to the asynchronous nature of flows they call for different _modes_ of flattening,
-as such, there is a family of flattening operators on flows.
-
-#### flatMapConcat
-
-Concatenating mode is implemented by [flatMapConcat] and [flattenConcat] operators. They are the most direct
-analogues of the corresponding sequence operators. They wait for the inner flow to complete before
-starting to collect the next one as the following example shows:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun requestFlow(i: Int): Flow<String> = flow {
- emit("$i: First")
- delay(500) // wait 500 ms
- emit("$i: Second")
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val startTime = System.currentTimeMillis() // remember the start time
- (1..3).asFlow().onEach { delay(100) } // a number every 100 ms
- .flatMapConcat { requestFlow(it) }
- .collect { value -> // collect and print
- println("$value at ${System.currentTimeMillis() - startTime} ms from start")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt).
-
-The sequential nature of [flatMapConcat] is clearly seen in the output:
-
-```text
-1: First at 121 ms from start
-1: Second at 622 ms from start
-2: First at 727 ms from start
-2: Second at 1227 ms from start
-3: First at 1328 ms from start
-3: Second at 1829 ms from start
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-#### flatMapMerge
-
-Another flattening mode is to concurrently collect all the incoming flows and merge their values into
-a single flow so that values are emitted as soon as possible.
-It is implemented by [flatMapMerge] and [flattenMerge] operators. They both accept an optional
-`concurrency` parameter that limits the number of concurrent flows that are collected at the same time
-(it is equal to [DEFAULT_CONCURRENCY] by default).
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun requestFlow(i: Int): Flow<String> = flow {
- emit("$i: First")
- delay(500) // wait 500 ms
- emit("$i: Second")
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val startTime = System.currentTimeMillis() // remember the start time
- (1..3).asFlow().onEach { delay(100) } // a number every 100 ms
- .flatMapMerge { requestFlow(it) }
- .collect { value -> // collect and print
- println("$value at ${System.currentTimeMillis() - startTime} ms from start")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt).
-
-The concurrent nature of [flatMapMerge] is obvious:
-
-```text
-1: First at 136 ms from start
-2: First at 231 ms from start
-3: First at 333 ms from start
-1: Second at 639 ms from start
-2: Second at 732 ms from start
-3: Second at 833 ms from start
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-> Note that the [flatMapMerge] calls its block of code (`{ requestFlow(it) }` in this example) sequentially, but
-collects the resulting flows concurrently, it is the equivalent of performing a sequential
-`map { requestFlow(it) }` first and then calling [flattenMerge] on the result.
-
-#### flatMapLatest
-
-In a similar way to the [collectLatest] operator, that was shown in
-["Processing the latest value"](#processing-the-latest-value) section, there is the corresponding "Latest"
-flattening mode where a collection of the previous flow is cancelled as soon as new flow is emitted.
-It is implemented by the [flatMapLatest] operator.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun requestFlow(i: Int): Flow<String> = flow {
- emit("$i: First")
- delay(500) // wait 500 ms
- emit("$i: Second")
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val startTime = System.currentTimeMillis() // remember the start time
- (1..3).asFlow().onEach { delay(100) } // a number every 100 ms
- .flatMapLatest { requestFlow(it) }
- .collect { value -> // collect and print
- println("$value at ${System.currentTimeMillis() - startTime} ms from start")
- }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt).
-
-The output here in this example is a good demonstration of how [flatMapLatest] works:
-
-```text
-1: First at 142 ms from start
-2: First at 322 ms from start
-3: First at 425 ms from start
-3: Second at 931 ms from start
-```
-
-<!--- TEST ARBITRARY_TIME -->
-
-> Note that [flatMapLatest] cancels all the code in its block (`{ requestFlow(it) }` in this example) on a new value.
-It makes no difference in this particular example, because the call to `requestFlow` itself is fast, not-suspending,
-and cannot be cancelled. However, it would show up if we were to use suspending functions like `delay` in there.
-
-### Flow exceptions
-
-Flow collection can complete with an exception when an emitter or code inside the operators throw an exception.
-There are several ways to handle these exceptions.
-
-#### Collector try and catch
-
-A collector can use Kotlin's [`try/catch`][exceptions] block to handle exceptions:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- println("Emitting $i")
- emit(i) // emit next value
- }
-}
-
-fun main() = runBlocking<Unit> {
- try {
- simple().collect { value ->
- println(value)
- check(value <= 1) { "Collected $value" }
- }
- } catch (e: Throwable) {
- println("Caught $e")
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt).
-
-This code successfully catches an exception in [collect] terminal operator and,
-as we see, no more values are emitted after that:
-
-```text
-Emitting 1
-1
-Emitting 2
-2
-Caught java.lang.IllegalStateException: Collected 2
-```
-
-<!--- TEST -->
-
-#### Everything is caught
-
-The previous example actually catches any exception happening in the emitter or in any intermediate or terminal operators.
-For example, let's change the code so that emitted values are [mapped][map] to strings,
-but the corresponding code produces an exception:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<String> =
- flow {
- for (i in 1..3) {
- println("Emitting $i")
- emit(i) // emit next value
- }
- }
- .map { value ->
- check(value <= 1) { "Crashed on $value" }
- "string $value"
- }
-
-fun main() = runBlocking<Unit> {
- try {
- simple().collect { value -> println(value) }
- } catch (e: Throwable) {
- println("Caught $e")
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt).
-
-This exception is still caught and collection is stopped:
-
-```text
-Emitting 1
-string 1
-Emitting 2
-Caught java.lang.IllegalStateException: Crashed on 2
-```
-
-<!--- TEST -->
-
-### Exception transparency
-
-But how can code of the emitter encapsulate its exception handling behavior?
-
-Flows must be _transparent to exceptions_ and it is a violation of the exception transparency to [emit][FlowCollector.emit] values in the
-`flow { ... }` builder from inside of a `try/catch` block. This guarantees that a collector throwing an exception
-can always catch it using `try/catch` as in the previous example.
-
-The emitter can use a [catch] operator that preserves this exception transparency and allows encapsulation
-of its exception handling. The body of the `catch` operator can analyze an exception
-and react to it in different ways depending on which exception was caught:
-
-* Exceptions can be rethrown using `throw`.
-* Exceptions can be turned into emission of values using [emit][FlowCollector.emit] from the body of [catch].
-* Exceptions can be ignored, logged, or processed by some other code.
-
-For example, let us emit the text on catching an exception:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun simple(): Flow<String> =
- flow {
- for (i in 1..3) {
- println("Emitting $i")
- emit(i) // emit next value
- }
- }
- .map { value ->
- check(value <= 1) { "Crashed on $value" }
- "string $value"
- }
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- simple()
- .catch { e -> emit("Caught $e") } // emit on exception
- .collect { value -> println(value) }
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt).
-
-The output of the example is the same, even though we do not have `try/catch` around the code anymore.
-
-<!--- TEST
-Emitting 1
-string 1
-Emitting 2
-Caught java.lang.IllegalStateException: Crashed on 2
--->
-
-#### Transparent catch
-
-The [catch] intermediate operator, honoring exception transparency, catches only upstream exceptions
-(that is an exception from all the operators above `catch`, but not below it).
-If the block in `collect { ... }` (placed below `catch`) throws an exception then it escapes:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- println("Emitting $i")
- emit(i)
- }
-}
-
-fun main() = runBlocking<Unit> {
- simple()
- .catch { e -> println("Caught $e") } // does not catch downstream exceptions
- .collect { value ->
- check(value <= 1) { "Collected $value" }
- println(value)
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt).
-
-A "Caught ..." message is not printed despite there being a `catch` operator:
-
-```text
-Emitting 1
-1
-Emitting 2
-Exception in thread "main" java.lang.IllegalStateException: Collected 2
- at ...
-```
-
-<!--- TEST EXCEPTION -->
-
-#### Catching declaratively
-
-We can combine the declarative nature of the [catch] operator with a desire to handle all the exceptions, by moving the body
-of the [collect] operator into [onEach] and putting it before the `catch` operator. Collection of this flow must
-be triggered by a call to `collect()` without parameters:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun simple(): Flow<Int> = flow {
- for (i in 1..3) {
- println("Emitting $i")
- emit(i)
- }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- simple()
- .onEach { value ->
- check(value <= 1) { "Collected $value" }
- println(value)
- }
- .catch { e -> println("Caught $e") }
- .collect()
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt).
-
-Now we can see that a "Caught ..." message is printed and so we can catch all the exceptions without explicitly
-using a `try/catch` block:
-
-```text
-Emitting 1
-1
-Emitting 2
-Caught java.lang.IllegalStateException: Collected 2
-```
-
-<!--- TEST EXCEPTION -->
-
-### Flow completion
-
-When flow collection completes (normally or exceptionally) it may need to execute an action.
-As you may have already noticed, it can be done in two ways: imperative or declarative.
-
-#### Imperative finally block
-
-In addition to `try`/`catch`, a collector can also use a `finally` block to execute an action
-upon `collect` completion.
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = (1..3).asFlow()
-
-fun main() = runBlocking<Unit> {
- try {
- simple().collect { value -> println(value) }
- } finally {
- println("Done")
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt).
-
-This code prints three numbers produced by the `simple` flow followed by a "Done" string:
-
-```text
-1
-2
-3
-Done
-```
-
-<!--- TEST -->
-
-#### Declarative handling
-
-For the declarative approach, flow has [onCompletion] intermediate operator that is invoked
-when the flow has completely collected.
-
-The previous example can be rewritten using an [onCompletion] operator and produces the same output:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-fun simple(): Flow<Int> = (1..3).asFlow()
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- simple()
- .onCompletion { println("Done") }
- .collect { value -> println(value) }
-//sampleEnd
-}
-```
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt).
-
-<!--- TEST
-1
-2
-3
-Done
--->
-
-The key advantage of [onCompletion] is a nullable `Throwable` parameter of the lambda that can be used
-to determine whether the flow collection was completed normally or exceptionally. In the following
-example the `simple` flow throws an exception after emitting the number 1:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = flow {
- emit(1)
- throw RuntimeException()
-}
-
-fun main() = runBlocking<Unit> {
- simple()
- .onCompletion { cause -> if (cause != null) println("Flow completed exceptionally") }
- .catch { cause -> println("Caught exception") }
- .collect { value -> println(value) }
-}
-//sampleEnd
-```
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt).
-
-As you may expect, it prints:
-
-```text
-1
-Flow completed exceptionally
-Caught exception
-```
-
-<!--- TEST -->
-
-The [onCompletion] operator, unlike [catch], does not handle the exception. As we can see from the above
-example code, the exception still flows downstream. It will be delivered to further `onCompletion` operators
-and can be handled with a `catch` operator.
-
-#### Successful completion
-
-Another difference with [catch] operator is that [onCompletion] sees all exceptions and receives
-a `null` exception only on successful completion of the upstream flow (without cancellation or failure).
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun simple(): Flow<Int> = (1..3).asFlow()
-
-fun main() = runBlocking<Unit> {
- simple()
- .onCompletion { cause -> println("Flow completed with $cause") }
- .collect { value ->
- check(value <= 1) { "Collected $value" }
- println(value)
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt).
-
-We can see the completion cause is not null, because the flow was aborted due to downstream exception:
-
-```text
-1
-Flow completed with java.lang.IllegalStateException: Collected 2
-Exception in thread "main" java.lang.IllegalStateException: Collected 2
-```
-
-<!--- TEST EXCEPTION -->
-
-### Imperative versus declarative
-
-Now we know how to collect flow, and handle its completion and exceptions in both imperative and declarative ways.
-The natural question here is, which approach is preferred and why?
-As a library, we do not advocate for any particular approach and believe that both options
-are valid and should be selected according to your own preferences and code style.
-
-### Launching flow
-
-It is easy to use flows to represent asynchronous events that are coming from some source.
-In this case, we need an analogue of the `addEventListener` function that registers a piece of code with a reaction
-for incoming events and continues further work. The [onEach] operator can serve this role.
-However, `onEach` is an intermediate operator. We also need a terminal operator to collect the flow.
-Otherwise, just calling `onEach` has no effect.
-
-If we use the [collect] terminal operator after `onEach`, then the code after it will wait until the flow is collected:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-// Imitate a flow of events
-fun events(): Flow<Int> = (1..3).asFlow().onEach { delay(100) }
-
-fun main() = runBlocking<Unit> {
- events()
- .onEach { event -> println("Event: $event") }
- .collect() // <--- Collecting the flow waits
- println("Done")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt).
-
-As you can see, it prints:
-
-```text
-Event: 1
-Event: 2
-Event: 3
-Done
-```
-
-<!--- TEST -->
-
-The [launchIn] terminal operator comes in handy here. By replacing `collect` with `launchIn` we can
-launch a collection of the flow in a separate coroutine, so that execution of further code
-immediately continues:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-// Imitate a flow of events
-fun events(): Flow<Int> = (1..3).asFlow().onEach { delay(100) }
-
-//sampleStart
-fun main() = runBlocking<Unit> {
- events()
- .onEach { event -> println("Event: $event") }
- .launchIn(this) // <--- Launching the flow in a separate coroutine
- println("Done")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt).
-
-It prints:
-
-```text
-Done
-Event: 1
-Event: 2
-Event: 3
-```
-
-<!--- TEST -->
-
-The required parameter to `launchIn` must specify a [CoroutineScope] in which the coroutine to collect the flow is
-launched. In the above example this scope comes from the [runBlocking]
-coroutine builder, so while the flow is running, this [runBlocking] scope waits for completion of its child coroutine
-and keeps the main function from returning and terminating this example.
-
-In actual applications a scope will come from an entity with a limited
-lifetime. As soon as the lifetime of this entity is terminated the corresponding scope is cancelled, cancelling
-the collection of the corresponding flow. This way the pair of `onEach { ... }.launchIn(scope)` works
-like the `addEventListener`. However, there is no need for the corresponding `removeEventListener` function,
-as cancellation and structured concurrency serve this purpose.
-
-Note that [launchIn] also returns a [Job], which can be used to [cancel][Job.cancel] the corresponding flow collection
-coroutine only without cancelling the whole scope or to [join][Job.join] it.
-
-### Flow cancellation checks
-
-For convenience, the [flow][_flow] builder performs additional [ensureActive] checks for cancellation on each emitted value.
-It means that a busy loop emitting from a `flow { ... }` is cancellable:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun foo(): Flow<Int> = flow {
- for (i in 1..5) {
- println("Emitting $i")
- emit(i)
- }
-}
-
-fun main() = runBlocking<Unit> {
- foo().collect { value ->
- if (value == 3) cancel()
- println(value)
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-37.kt).
-
-We get only numbers up to 3 and a [CancellationException] after trying to emit number 4:
-
-```text
-Emitting 1
-1
-Emitting 2
-2
-Emitting 3
-3
-Emitting 4
-Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@6d7b4f4c
-```
-
-<!--- TEST EXCEPTION -->
-
-However, most other flow operators do not do additional cancellation checks on their own for performance reasons.
-For example, if you use [IntRange.asFlow] extension to write the same busy loop and don't suspend anywhere,
-then there are no checks for cancellation:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun main() = runBlocking<Unit> {
- (1..5).asFlow().collect { value ->
- if (value == 3) cancel()
- println(value)
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-38.kt).
-
-All numbers from 1 to 5 are collected and cancellation gets detected only before return from `runBlocking`:
-
-```text
-1
-2
-3
-4
-5
-Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@3327bd23
-```
-
-<!--- TEST EXCEPTION -->
-
-#### Making busy flow cancellable
-
-In the case where you have a busy loop with coroutines you must explicitly check for cancellation.
-You can add `.onEach { currentCoroutineContext().ensureActive() }`, but there is a ready-to-use
-[cancellable] operator provided to do that:
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-
-//sampleStart
-fun main() = runBlocking<Unit> {
- (1..5).asFlow().cancellable().collect { value ->
- if (value == 3) cancel()
- println(value)
- }
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code from [here](../kotlinx-coroutines-core/jvm/test/guide/example-flow-39.kt).
-
-With the `cancellable` operator only the numbers from 1 to 3 are collected:
-
-```text
-1
-2
-3
-Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@5ec0a365
-```
-
-<!--- TEST EXCEPTION -->
-
-### Flow and Reactive Streams
-
-For those who are familiar with [Reactive Streams](https://www.reactive-streams.org/) or reactive frameworks such as RxJava and project Reactor,
-design of the Flow may look very familiar.
-
-Indeed, its design was inspired by Reactive Streams and its various implementations. But Flow main goal is to have as simple design as possible,
-be Kotlin and suspension friendly and respect structured concurrency. Achieving this goal would be impossible without reactive pioneers and their tremendous work. You can read the complete story in [Reactive Streams and Kotlin Flows](https://medium.com/@elizarov/reactive-streams-and-kotlin-flows-bfd12772cda4) article.
-
-While being different, conceptually, Flow *is* a reactive stream and it is possible to convert it to the reactive (spec and TCK compliant) Publisher and vice versa.
-Such converters are provided by `kotlinx.coroutines` out-of-the-box and can be found in corresponding reactive modules (`kotlinx-coroutines-reactive` for Reactive Streams, `kotlinx-coroutines-reactor` for Project Reactor and `kotlinx-coroutines-rx2`/`kotlinx-coroutines-rx3` for RxJava2/RxJava3).
-Integration modules include conversions from and to `Flow`, integration with Reactor's `Context` and suspension-friendly ways to work with various reactive entities.
-
-<!-- stdlib references -->
-
-[collections]: https://kotlinlang.org/docs/reference/collections-overview.html
-[List]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html
-[forEach]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/for-each.html
-[Sequence]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/index.html
-[Sequence.zip]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/zip.html
-[Sequence.flatten]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/flatten.html
-[Sequence.flatMap]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/flat-map.html
-[exceptions]: https://kotlinlang.org/docs/reference/exceptions.html
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
-[withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html
-[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
-[Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html
-[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
-[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html
-[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
-[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
-[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
-[ensureActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/ensure-active.html
-[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
-<!--- INDEX kotlinx.coroutines.flow -->
-[Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html
-[_flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow.html
-[FlowCollector.emit]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow-collector/emit.html
-[collect]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect.html
-[flowOf]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow-of.html
-[map]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/map.html
-[filter]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/filter.html
-[transform]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/transform.html
-[take]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/take.html
-[toList]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-list.html
-[toSet]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-set.html
-[first]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/first.html
-[single]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/single.html
-[reduce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/reduce.html
-[fold]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/fold.html
-[flowOn]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow-on.html
-[buffer]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/buffer.html
-[conflate]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/conflate.html
-[collectLatest]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect-latest.html
-[zip]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/zip.html
-[combine]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/combine.html
-[onEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/on-each.html
-[flatMapConcat]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flat-map-concat.html
-[flattenConcat]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flatten-concat.html
-[flatMapMerge]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flat-map-merge.html
-[flattenMerge]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flatten-merge.html
-[DEFAULT_CONCURRENCY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-d-e-f-a-u-l-t_-c-o-n-c-u-r-r-e-n-c-y.html
-[flatMapLatest]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flat-map-latest.html
-[catch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/catch.html
-[onCompletion]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/on-completion.html
-[launchIn]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/launch-in.html
-[IntRange.asFlow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/kotlin.ranges.-int-range/as-flow.html
-[cancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/cancellable.html
-<!--- END -->
+To edit the documentation, open the [topics/flow.md](topics/flow.md) page.
\ No newline at end of file
diff --git a/docs/images/coroutine-breakpoint.png b/docs/images/coroutine-breakpoint.png
new file mode 100644
index 0000000..b547e77
--- /dev/null
+++ b/docs/images/coroutine-breakpoint.png
Binary files differ
diff --git a/docs/images/coroutine-debug-1.png b/docs/images/coroutine-debug-1.png
new file mode 100644
index 0000000..d92d0ff
--- /dev/null
+++ b/docs/images/coroutine-debug-1.png
Binary files differ
diff --git a/docs/images/coroutine-debug-2.png b/docs/images/coroutine-debug-2.png
new file mode 100644
index 0000000..56f19c3
--- /dev/null
+++ b/docs/images/coroutine-debug-2.png
Binary files differ
diff --git a/docs/images/coroutine-debug-3.png b/docs/images/coroutine-debug-3.png
new file mode 100644
index 0000000..43a1460
--- /dev/null
+++ b/docs/images/coroutine-debug-3.png
Binary files differ
diff --git a/docs/images/flow-breakpoint.png b/docs/images/flow-breakpoint.png
new file mode 100644
index 0000000..aa98e18
--- /dev/null
+++ b/docs/images/flow-breakpoint.png
Binary files differ
diff --git a/docs/images/flow-build-project.png b/docs/images/flow-build-project.png
new file mode 100644
index 0000000..2218621
--- /dev/null
+++ b/docs/images/flow-build-project.png
Binary files differ
diff --git a/docs/images/flow-debug-1.png b/docs/images/flow-debug-1.png
new file mode 100644
index 0000000..8a16984
--- /dev/null
+++ b/docs/images/flow-debug-1.png
Binary files differ
diff --git a/docs/images/flow-debug-2.png b/docs/images/flow-debug-2.png
new file mode 100644
index 0000000..d06c86b
--- /dev/null
+++ b/docs/images/flow-debug-2.png
Binary files differ
diff --git a/docs/images/flow-debug-3.png b/docs/images/flow-debug-3.png
new file mode 100644
index 0000000..af082c0
--- /dev/null
+++ b/docs/images/flow-debug-3.png
Binary files differ
diff --git a/docs/images/flow-debug-4.png b/docs/images/flow-debug-4.png
new file mode 100644
index 0000000..8d1c42d
--- /dev/null
+++ b/docs/images/flow-debug-4.png
Binary files differ
diff --git a/docs/images/flow-debug-project.png b/docs/images/flow-debug-project.png
new file mode 100644
index 0000000..98d392e
--- /dev/null
+++ b/docs/images/flow-debug-project.png
Binary files differ
diff --git a/docs/images/flow-resume-debug.png b/docs/images/flow-resume-debug.png
new file mode 100644
index 0000000..adb1249
--- /dev/null
+++ b/docs/images/flow-resume-debug.png
Binary files differ
diff --git a/docs/images/new-gradle-project-jvm.png b/docs/images/new-gradle-project-jvm.png
new file mode 100644
index 0000000..108ce75
--- /dev/null
+++ b/docs/images/new-gradle-project-jvm.png
Binary files differ
diff --git a/docs/images/new-mvn-project-jvm.png b/docs/images/new-mvn-project-jvm.png
new file mode 100644
index 0000000..2154a3d
--- /dev/null
+++ b/docs/images/new-mvn-project-jvm.png
Binary files differ
diff --git a/docs/kc.tree b/docs/kc.tree
new file mode 100644
index 0000000..a72aa0c
--- /dev/null
+++ b/docs/kc.tree
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE product-profile
+ SYSTEM "http://helpserver.labs.intellij.net/help/product-profile.dtd">
+
+<product-profile id="kc"
+ name="Kotlin coroutines"
+ start-page="coroutines-guide.md">
+
+ <toc-element id="coroutines-guide.md"/>
+ <toc-element id="async-programming.md"/>
+ <toc-element id="basics.md"/>
+ <toc-element id="coroutines-basic-jvm.md"/>
+ <toc-element toc-title="Intro to coroutines and channels – hands-on tutorial" href="https://play.kotlinlang.org/hands-on/Introduction%20to%20Coroutines%20and%20Channels/"/>
+ <toc-element id="cancellation-and-timeouts.md"/>
+ <toc-element id="composing-suspending-functions.md"/>
+ <toc-element id="coroutine-context-and-dispatchers.md"/>
+ <toc-element id="flow.md"/>
+ <toc-element id="channels.md"/>
+ <toc-element id="exception-handling.md"/>
+ <toc-element id="shared-mutable-state-and-concurrency.md"/>
+ <toc-element id="select-expression.md"/>
+ <toc-element id="debug-coroutines-with-idea.md"/>
+ <toc-element id="debug-flow-with-idea.md"/>
+
+</product-profile>
\ No newline at end of file
diff --git a/docs/project.ihp b/docs/project.ihp
new file mode 100644
index 0000000..80859c4
--- /dev/null
+++ b/docs/project.ihp
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE ihp SYSTEM "http://helpserver.labs.intellij.net/help/ihp.dtd">
+
+<ihp version="2.0">
+ <categories src="c.list"/>
+ <topics dir="topics"/>
+ <images dir="images" web-path="/img/kotlin-coroutines/"/>
+ <vars src="v.list"/>
+ <product version="%coroutinesVersion%" id="help/kotlin-coroutines" src="kc.tree" web-path="/kotlin-coroutines/"/>
+ <settings>
+ <default-property element-name="toc-element" property-name="show-structure-depth" value="2"/>
+ </settings>
+</ihp>
\ No newline at end of file
diff --git a/docs/select-expression.md b/docs/select-expression.md
index 43fcfd2..d045168 100644
--- a/docs/select-expression.md
+++ b/docs/select-expression.md
@@ -1,549 +1,3 @@
-<!--- TEST_NAME SelectGuideTest -->
+The documentation has been moved to the [https://kotlinlang.org/docs/select-expression.html](https://kotlinlang.org/docs/select-expression.html) page.
-**Table of contents**
-
-<!--- TOC -->
-
-* [Select Expression (experimental)](#select-expression-experimental)
- * [Selecting from channels](#selecting-from-channels)
- * [Selecting on close](#selecting-on-close)
- * [Selecting to send](#selecting-to-send)
- * [Selecting deferred values](#selecting-deferred-values)
- * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
-
-<!--- END -->
-
-## Select Expression (experimental)
-
-Select expression makes it possible to await multiple suspending functions simultaneously and _select_
-the first one that becomes available.
-
-> Select expressions are an experimental feature of `kotlinx.coroutines`. Their API is expected to
-evolve in the upcoming updates of the `kotlinx.coroutines` library with potentially
-breaking changes.
-
-### Selecting from channels
-
-Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.fizz() = produce<String> {
- while (true) { // sends "Fizz" every 300 ms
- delay(300)
- send("Fizz")
- }
-}
-```
-
-</div>
-
-And the `buzz` produces "Buzz!" string every 500 ms:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.buzz() = produce<String> {
- while (true) { // sends "Buzz!" every 500 ms
- delay(500)
- send("Buzz!")
- }
-}
-```
-
-</div>
-
-Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
-other. But [select] expression allows us to receive from _both_ simultaneously using its
-[onReceive][ReceiveChannel.onReceive] clauses:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
- select<Unit> { // <Unit> means that this select expression does not produce any result
- fizz.onReceive { value -> // this is the first select clause
- println("fizz -> '$value'")
- }
- buzz.onReceive { value -> // this is the second select clause
- println("buzz -> '$value'")
- }
- }
-}
-```
-
-</div>
-
-Let us run it all seven times:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-import kotlinx.coroutines.selects.*
-
-fun CoroutineScope.fizz() = produce<String> {
- while (true) { // sends "Fizz" every 300 ms
- delay(300)
- send("Fizz")
- }
-}
-
-fun CoroutineScope.buzz() = produce<String> {
- while (true) { // sends "Buzz!" every 500 ms
- delay(500)
- send("Buzz!")
- }
-}
-
-suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
- select<Unit> { // <Unit> means that this select expression does not produce any result
- fizz.onReceive { value -> // this is the first select clause
- println("fizz -> '$value'")
- }
- buzz.onReceive { value -> // this is the second select clause
- println("buzz -> '$value'")
- }
- }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val fizz = fizz()
- val buzz = buzz()
- repeat(7) {
- selectFizzBuzz(fizz, buzz)
- }
- coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt).
-
-The result of this code is:
-
-```text
-fizz -> 'Fizz'
-buzz -> 'Buzz!'
-fizz -> 'Fizz'
-fizz -> 'Fizz'
-buzz -> 'Buzz!'
-fizz -> 'Fizz'
-buzz -> 'Buzz!'
-```
-
-<!--- TEST -->
-
-### Selecting on close
-
-The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
-`select` to throw an exception. We can use [onReceiveOrNull][onReceiveOrNull] clause to perform a
-specific action when the channel is closed. The following example also shows that `select` is an expression that returns
-the result of its selected clause:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
- select<String> {
- a.onReceiveOrNull { value ->
- if (value == null)
- "Channel 'a' is closed"
- else
- "a -> '$value'"
- }
- b.onReceiveOrNull { value ->
- if (value == null)
- "Channel 'b' is closed"
- else
- "b -> '$value'"
- }
- }
-```
-
-</div>
-
-Note that [onReceiveOrNull][onReceiveOrNull] is an extension function defined only
-for channels with non-nullable elements so that there is no accidental confusion between a closed channel
-and a null value.
-
-Let's use it with channel `a` that produces "Hello" string four times and
-channel `b` that produces "World" four times:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-import kotlinx.coroutines.selects.*
-
-suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
- select<String> {
- a.onReceiveOrNull { value ->
- if (value == null)
- "Channel 'a' is closed"
- else
- "a -> '$value'"
- }
- b.onReceiveOrNull { value ->
- if (value == null)
- "Channel 'b' is closed"
- else
- "b -> '$value'"
- }
- }
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val a = produce<String> {
- repeat(4) { send("Hello $it") }
- }
- val b = produce<String> {
- repeat(4) { send("World $it") }
- }
- repeat(8) { // print first eight results
- println(selectAorB(a, b))
- }
- coroutineContext.cancelChildren()
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt).
-
-The result of this code is quite interesting, so we'll analyze it in more detail:
-
-```text
-a -> 'Hello 0'
-a -> 'Hello 1'
-b -> 'World 0'
-a -> 'Hello 2'
-a -> 'Hello 3'
-b -> 'World 1'
-Channel 'a' is closed
-Channel 'a' is closed
-```
-
-<!--- TEST -->
-
-There are couple of observations to make out of it.
-
-First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
-the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
-being the first clause in select, wins. However, because we are using unbuffered channel, the `a` gets suspended from
-time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
-
-The second observation, is that [onReceiveOrNull][onReceiveOrNull] gets immediately selected when the
-channel is already closed.
-
-### Selecting to send
-
-Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
-with a biased nature of selection.
-
-Let us write an example of producer of integers that sends its values to a `side` channel when
-the consumers on its primary channel cannot keep up with it:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
- for (num in 1..10) { // produce 10 numbers from 1 to 10
- delay(100) // every 100 ms
- select<Unit> {
- onSend(num) {} // Send to the primary channel
- side.onSend(num) {} // or to the side channel
- }
- }
-}
-```
-
-</div>
-
-Consumer is going to be quite slow, taking 250 ms to process each number:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-import kotlinx.coroutines.selects.*
-
-fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
- for (num in 1..10) { // produce 10 numbers from 1 to 10
- delay(100) // every 100 ms
- select<Unit> {
- onSend(num) {} // Send to the primary channel
- side.onSend(num) {} // or to the side channel
- }
- }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val side = Channel<Int>() // allocate side channel
- launch { // this is a very fast consumer for the side channel
- side.consumeEach { println("Side channel has $it") }
- }
- produceNumbers(side).consumeEach {
- println("Consuming $it")
- delay(250) // let us digest the consumed number properly, do not hurry
- }
- println("Done consuming")
- coroutineContext.cancelChildren()
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt).
-
-So let us see what happens:
-
-```text
-Consuming 1
-Side channel has 2
-Side channel has 3
-Consuming 4
-Side channel has 5
-Side channel has 6
-Consuming 7
-Side channel has 8
-Side channel has 9
-Consuming 10
-Done consuming
-```
-
-<!--- TEST -->
-
-### Selecting deferred values
-
-Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
-Let us start with an async function that returns a deferred string value after
-a random delay:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.asyncString(time: Int) = async {
- delay(time.toLong())
- "Waited for $time ms"
-}
-```
-
-</div>
-
-Let us start a dozen of them with a random delay.
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
- val random = Random(3)
- return List(12) { asyncString(random.nextInt(1000)) }
-}
-```
-
-</div>
-
-Now the main function awaits for the first of them to complete and counts the number of deferred values
-that are still active. Note that we've used here the fact that `select` expression is a Kotlin DSL,
-so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
-of deferred values to provide `onAwait` clause for each deferred value.
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.selects.*
-import java.util.*
-
-fun CoroutineScope.asyncString(time: Int) = async {
- delay(time.toLong())
- "Waited for $time ms"
-}
-
-fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
- val random = Random(3)
- return List(12) { asyncString(random.nextInt(1000)) }
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val list = asyncStringsList()
- val result = select<String> {
- list.withIndex().forEach { (index, deferred) ->
- deferred.onAwait { answer ->
- "Deferred $index produced answer '$answer'"
- }
- }
- }
- println(result)
- val countActive = list.count { it.isActive }
- println("$countActive coroutines are still active")
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt).
-
-The output is:
-
-```text
-Deferred 4 produced answer 'Waited for 128 ms'
-11 coroutines are still active
-```
-
-<!--- TEST -->
-
-### Switch over a channel of deferred values
-
-Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
-deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
-[onReceiveOrNull][onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
- var current = input.receive() // start with first received deferred value
- while (isActive) { // loop while not cancelled/closed
- val next = select<Deferred<String>?> { // return next deferred value from this select or null
- input.onReceiveOrNull { update ->
- update // replaces next value to wait
- }
- current.onAwait { value ->
- send(value) // send value that current deferred has produced
- input.receiveOrNull() // and use the next deferred from the input channel
- }
- }
- if (next == null) {
- println("Channel was closed")
- break // out of loop
- } else {
- current = next
- }
- }
-}
-```
-
-</div>
-
-To test it, we'll use a simple async function that resolves to a specified string after a specified time:
-
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-fun CoroutineScope.asyncString(str: String, time: Long) = async {
- delay(time)
- str
-}
-```
-
-</div>
-
-The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
-data to it:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-import kotlinx.coroutines.selects.*
-
-fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
- var current = input.receive() // start with first received deferred value
- while (isActive) { // loop while not cancelled/closed
- val next = select<Deferred<String>?> { // return next deferred value from this select or null
- input.onReceiveOrNull { update ->
- update // replaces next value to wait
- }
- current.onAwait { value ->
- send(value) // send value that current deferred has produced
- input.receiveOrNull() // and use the next deferred from the input channel
- }
- }
- if (next == null) {
- println("Channel was closed")
- break // out of loop
- } else {
- current = next
- }
- }
-}
-
-fun CoroutineScope.asyncString(str: String, time: Long) = async {
- delay(time)
- str
-}
-
-fun main() = runBlocking<Unit> {
-//sampleStart
- val chan = Channel<Deferred<String>>() // the channel for test
- launch { // launch printing coroutine
- for (s in switchMapDeferreds(chan))
- println(s) // print each received string
- }
- chan.send(asyncString("BEGIN", 100))
- delay(200) // enough time for "BEGIN" to be produced
- chan.send(asyncString("Slow", 500))
- delay(100) // not enough time to produce slow
- chan.send(asyncString("Replace", 100))
- delay(500) // give it time before the last one
- chan.send(asyncString("END", 500))
- delay(1000) // give it time to process
- chan.close() // close the channel ...
- delay(500) // and wait some time to let it finish
-//sampleEnd
-}
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt).
-
-The result of this code:
-
-```text
-BEGIN
-Replace
-END
-Channel was closed
-```
-
-<!--- TEST -->
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[Deferred.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/on-await.html
-<!--- INDEX kotlinx.coroutines.channels -->
-[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
-[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/on-receive.html
-[onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/on-receive-or-null.html
-[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/send.html
-[SendChannel.onSend]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/on-send.html
-<!--- INDEX kotlinx.coroutines.selects -->
-[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html
-<!--- END -->
+To edit the documentation, open the [topics/select-expression.md](topics/select-expression.md) page.
\ No newline at end of file
diff --git a/docs/shared-mutable-state-and-concurrency.md b/docs/shared-mutable-state-and-concurrency.md
index 8b83ad0..ca05436 100644
--- a/docs/shared-mutable-state-and-concurrency.md
+++ b/docs/shared-mutable-state-and-concurrency.md
@@ -1,539 +1,3 @@
-<!--- TEST_NAME SharedStateGuideTest -->
-
-**Table of contents**
+The documentation has been moved to the [https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html](https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html) page.
-<!--- TOC -->
-
-* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
- * [The problem](#the-problem)
- * [Volatiles are of no help](#volatiles-are-of-no-help)
- * [Thread-safe data structures](#thread-safe-data-structures)
- * [Thread confinement fine-grained](#thread-confinement-fine-grained)
- * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
- * [Mutual exclusion](#mutual-exclusion)
- * [Actors](#actors)
-
-<!--- END -->
-
-## Shared mutable state and concurrency
-
-Coroutines can be executed concurrently using a multi-threaded dispatcher like the [Dispatchers.Default]. It presents
-all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
-Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
-but others are unique.
-
-### The problem
-
-Let us launch a hundred coroutines all doing the same action a thousand times.
-We'll also measure their completion time for further comparisons:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-```
-
-</div>
-
-We start with a very simple action that increments a shared mutable variable using
-multi-threaded [Dispatchers.Default].
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-//sampleStart
-var counter = 0
-
-fun main() = runBlocking {
- withContext(Dispatchers.Default) {
- massiveRun {
- counter++
- }
- }
- println("Counter = $counter")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt).
-
-<!--- TEST LINES_START
-Completed 100000 actions in
-Counter =
--->
-
-What does it print at the end? It is highly unlikely to ever print "Counter = 100000", because a hundred coroutines
-increment the `counter` concurrently from multiple threads without any synchronization.
-
-### Volatiles are of no help
-
-There is a common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-//sampleStart
-@Volatile // in Kotlin `volatile` is an annotation
-var counter = 0
-
-fun main() = runBlocking {
- withContext(Dispatchers.Default) {
- massiveRun {
- counter++
- }
- }
- println("Counter = $counter")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt).
-
-<!--- TEST LINES_START
-Completed 100000 actions in
-Counter =
--->
-
-This code works slower, but we still don't get "Counter = 100000" at the end, because volatile variables guarantee
-linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
-do not provide atomicity of larger actions (increment in our case).
-
-### Thread-safe data structures
-
-The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
-linearizable, or atomic) data structure that provides all the necessary synchronization for the corresponding
-operations that needs to be performed on a shared state.
-In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import java.util.concurrent.atomic.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-//sampleStart
-val counter = AtomicInteger()
-
-fun main() = runBlocking {
- withContext(Dispatchers.Default) {
- massiveRun {
- counter.incrementAndGet()
- }
- }
- println("Counter = $counter")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt).
-
-<!--- TEST ARBITRARY_TIME
-Completed 100000 actions in xxx ms
-Counter = 100000
--->
-
-This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
-standard data structures and basic operations on them. However, it does not easily scale to complex
-state or to complex operations that do not have ready-to-use thread-safe implementations.
-
-### Thread confinement fine-grained
-
-_Thread confinement_ is an approach to the problem of shared mutable state where all access to the particular shared
-state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
-the single event-dispatch/application thread. It is easy to apply with coroutines by using a
-single-threaded context.
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-//sampleStart
-val counterContext = newSingleThreadContext("CounterContext")
-var counter = 0
-
-fun main() = runBlocking {
- withContext(Dispatchers.Default) {
- massiveRun {
- // confine each increment to a single-threaded context
- withContext(counterContext) {
- counter++
- }
- }
- }
- println("Counter = $counter")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt).
-
-<!--- TEST ARBITRARY_TIME
-Completed 100000 actions in xxx ms
-Counter = 100000
--->
-
-This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
-from multi-threaded [Dispatchers.Default] context to the single-threaded context using
-[withContext(counterContext)][withContext] block.
-
-### Thread confinement coarse-grained
-
-In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
-are confined to the single thread. The following example does it like that, running each coroutine in
-the single-threaded context to start with.
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-//sampleStart
-val counterContext = newSingleThreadContext("CounterContext")
-var counter = 0
-
-fun main() = runBlocking {
- // confine everything to a single-threaded context
- withContext(counterContext) {
- massiveRun {
- counter++
- }
- }
- println("Counter = $counter")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt).
-
-<!--- TEST ARBITRARY_TIME
-Completed 100000 actions in xxx ms
-Counter = 100000
--->
-
-This now works much faster and produces correct result.
-
-### Mutual exclusion
-
-Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
-that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
-Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
-delimit a critical section. The key difference is that `Mutex.lock()` is a suspending function. It does not block a thread.
-
-There is also [withLock] extension function that conveniently represents
-`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.sync.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-//sampleStart
-val mutex = Mutex()
-var counter = 0
-
-fun main() = runBlocking {
- withContext(Dispatchers.Default) {
- massiveRun {
- // protect each increment with lock
- mutex.withLock {
- counter++
- }
- }
- }
- println("Counter = $counter")
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt).
-
-<!--- TEST ARBITRARY_TIME
-Completed 100000 actions in xxx ms
-Counter = 100000
--->
-
-The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
-where you absolutely must modify some shared state periodically, but there is no natural thread that this state
-is confined to.
-
-### Actors
-
-An [actor](https://en.wikipedia.org/wiki/Actor_model) is an entity made up of a combination of a coroutine,
-the state that is confined and encapsulated into this coroutine,
-and a channel to communicate with other coroutines. A simple actor can be written as a function,
-but an actor with a complex state is better suited for a class.
-
-There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
-scope to receive messages from and combines the send channel into the resulting job object, so that a
-single reference to the actor can be carried around as its handle.
-
-The first step of using an actor is to define a class of messages that an actor is going to process.
-Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
-We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
-to get its value. The later needs to send a response. A [CompletableDeferred] communication
-primitive, that represents a single value that will be known (communicated) in the future,
-is used here for that purpose.
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-// Message types for counterActor
-sealed class CounterMsg
-object IncCounter : CounterMsg() // one-way message to increment counter
-class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
-```
-
-</div>
-
-Then we define a function that launches an actor using an [actor] coroutine builder:
-
-<div class="sample" markdown="1" theme="idea" data-highlight-only>
-
-```kotlin
-// This function launches a new counter actor
-fun CoroutineScope.counterActor() = actor<CounterMsg> {
- var counter = 0 // actor state
- for (msg in channel) { // iterate over incoming messages
- when (msg) {
- is IncCounter -> counter++
- is GetCounter -> msg.response.complete(counter)
- }
- }
-}
-```
-
-</div>
-
-The main code is straightforward:
-
-<!--- CLEAR -->
-
-<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
-
-```kotlin
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-import kotlin.system.*
-
-suspend fun massiveRun(action: suspend () -> Unit) {
- val n = 100 // number of coroutines to launch
- val k = 1000 // times an action is repeated by each coroutine
- val time = measureTimeMillis {
- coroutineScope { // scope for coroutines
- repeat(n) {
- launch {
- repeat(k) { action() }
- }
- }
- }
- }
- println("Completed ${n * k} actions in $time ms")
-}
-
-// Message types for counterActor
-sealed class CounterMsg
-object IncCounter : CounterMsg() // one-way message to increment counter
-class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
-
-// This function launches a new counter actor
-fun CoroutineScope.counterActor() = actor<CounterMsg> {
- var counter = 0 // actor state
- for (msg in channel) { // iterate over incoming messages
- when (msg) {
- is IncCounter -> counter++
- is GetCounter -> msg.response.complete(counter)
- }
- }
-}
-
-//sampleStart
-fun main() = runBlocking<Unit> {
- val counter = counterActor() // create the actor
- withContext(Dispatchers.Default) {
- massiveRun {
- counter.send(IncCounter)
- }
- }
- // send a message to get a counter value from an actor
- val response = CompletableDeferred<Int>()
- counter.send(GetCounter(response))
- println("Counter = ${response.await()}")
- counter.close() // shutdown the actor
-}
-//sampleEnd
-```
-
-</div>
-
-> You can get the full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt).
-
-<!--- TEST ARBITRARY_TIME
-Completed 100000 actions in xxx ms
-Counter = 100000
--->
-
-It does not matter (for correctness) what context the actor itself is executed in. An actor is
-a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
-works as a solution to the problem of shared mutable state. Indeed, actors may modify their own private state,
-but can only affect each other through messages (avoiding the need for any locks).
-
-Actor is more efficient than locking under load, because in this case it always has work to do and it does not
-have to switch to a different context at all.
-
-> Note that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
- with the channel that it receives messages from, while a producer is associated with the channel that it
- sends elements to.
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines -->
-[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
-[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
-[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-completable-deferred/index.html
-<!--- INDEX kotlinx.coroutines.sync -->
-[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html
-[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/lock.html
-[Mutex.unlock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/unlock.html
-[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/with-lock.html
-<!--- INDEX kotlinx.coroutines.channels -->
-[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
-[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
-<!--- END -->
+To edit the documentation, open the [topics/shared-mutable-state-and-concurrency.md](topics/shared-mutable-state-and-concurrency.md) page.
\ No newline at end of file
diff --git a/docs/topics/basics.md b/docs/topics/basics.md
new file mode 100644
index 0000000..d4c9a89
--- /dev/null
+++ b/docs/topics/basics.md
@@ -0,0 +1,379 @@
+<!--- TEST_NAME BasicsGuideTest -->
+
+[//]: # (title: Coroutines basics)
+
+This section covers basic coroutine concepts.
+
+## Your first coroutine
+
+Run the following code:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() {
+ GlobalScope.launch { // launch a new coroutine in background and continue
+ delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
+ println("World!") // print after delay
+ }
+ println("Hello,") // main thread continues while coroutine is delayed
+ Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt).
+>
+{type="note"}
+
+You will see the following result:
+
+```text
+Hello,
+World!
+```
+
+<!--- TEST -->
+
+Essentially, coroutines are light-weight threads.
+They are launched with [launch] _coroutine builder_ in a context of some [CoroutineScope].
+Here we are launching a new coroutine in the [GlobalScope], meaning that the lifetime of the new
+coroutine is limited only by the lifetime of the whole application.
+
+You can achieve the same result by replacing
+`GlobalScope.launch { ... }` with `thread { ... }`, and `delay(...)` with `Thread.sleep(...)`.
+Try it (don't forget to import `kotlin.concurrent.thread`).
+
+If you start by replacing `GlobalScope.launch` with `thread`, the compiler produces the following error:
+
+```Plain Text
+Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
+```
+
+That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_ the
+coroutine, and it can be only used from a coroutine.
+
+## Bridging blocking and non-blocking worlds
+
+The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
+It is easy to lose track of which one is blocking and which one is not.
+Let's be explicit about blocking using the [runBlocking] coroutine builder:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() {
+ GlobalScope.launch { // launch a new coroutine in background and continue
+ delay(1000L)
+ println("World!")
+ }
+ println("Hello,") // main thread continues here immediately
+ runBlocking { // but this expression blocks the main thread
+ delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
+ }
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt).
+>
+{type="note"}
+
+<!--- TEST
+Hello,
+World!
+-->
+
+The result is the same, but this code uses only non-blocking [delay].
+The main thread invoking `runBlocking` _blocks_ until the coroutine inside `runBlocking` completes.
+
+This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
+the execution of the main function:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> { // start main coroutine
+ GlobalScope.launch { // launch a new coroutine in background and continue
+ delay(1000L)
+ println("World!")
+ }
+ println("Hello,") // main coroutine continues here immediately
+ delay(2000L) // delaying for 2 seconds to keep JVM alive
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt).
+>
+{type="note"}
+
+<!--- TEST
+Hello,
+World!
+-->
+
+Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
+We explicitly specify its `Unit` return type, because a well-formed `main` function in Kotlin has to return `Unit`.
+
+This is also a way to write unit tests for suspending functions:
+
+<!--- INCLUDE
+import kotlinx.coroutines.*
+-->
+
+```kotlin
+class MyTest {
+ @Test
+ fun testMySuspendingFunction() = runBlocking<Unit> {
+ // here we can use suspending functions using any assertion style that we like
+ }
+}
+```
+
+<!--- CLEAR -->
+
+## Waiting for a job
+
+Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
+wait (in a non-blocking way) until the background [Job] that we have launched is complete:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
+ delay(1000L)
+ println("World!")
+ }
+ println("Hello,")
+ job.join() // wait until child coroutine completes
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt).
+>
+{type="note"}
+
+<!--- TEST
+Hello,
+World!
+-->
+
+Now the result is still the same, but the code of the main coroutine is not tied to the duration of
+the background job in any way. Much better.
+
+## Structured concurrency
+
+There is still something to be desired for practical usage of coroutines.
+When we use `GlobalScope.launch`, we create a top-level coroutine. Even though it is light-weight, it still
+consumes some memory resources while it runs. If we forget to keep a reference to the newly launched
+coroutine, it still runs. What if the code in the coroutine hangs (for example, we erroneously
+delay for too long), what if we launched too many coroutines and ran out of memory?
+Having to manually keep references to all the launched coroutines and [join][Job.join] them is error-prone.
+
+There is a better solution. We can use structured concurrency in our code.
+Instead of launching coroutines in the [GlobalScope], just like we usually do with threads (threads are always global),
+we can launch coroutines in the specific scope of the operation we are performing.
+
+In our example, we have a `main` function that is turned into a coroutine using the [runBlocking] coroutine builder.
+Every coroutine builder, including `runBlocking`, adds an instance of [CoroutineScope] to the scope of its code block.
+We can launch coroutines in this scope without having to `join` them explicitly, because
+an outer coroutine (`runBlocking` in our example) does not complete until all the coroutines launched
+in its scope complete. Thus, we can make our example simpler:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking { // this: CoroutineScope
+ launch { // launch a new coroutine in the scope of runBlocking
+ delay(1000L)
+ println("World!")
+ }
+ println("Hello,")
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt).
+>
+{type="note"}
+
+<!--- TEST
+Hello,
+World!
+-->
+
+## Scope builder
+
+In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using the
+[coroutineScope][_coroutineScope] builder. It creates a coroutine scope and does not complete until all launched children complete.
+
+[runBlocking] and [coroutineScope][_coroutineScope] may look similar because they both wait for their body and all its children to complete.
+The main difference is that the [runBlocking] method _blocks_ the current thread for waiting,
+while [coroutineScope][_coroutineScope] just suspends, releasing the underlying thread for other usages.
+Because of that difference, [runBlocking] is a regular function and [coroutineScope][_coroutineScope] is a suspending function.
+
+It can be demonstrated by the following example:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking { // this: CoroutineScope
+ launch {
+ delay(200L)
+ println("Task from runBlocking")
+ }
+
+ coroutineScope { // Creates a coroutine scope
+ launch {
+ delay(500L)
+ println("Task from nested launch")
+ }
+
+ delay(100L)
+ println("Task from coroutine scope") // This line will be printed before the nested launch
+ }
+
+ println("Coroutine scope is over") // This line is not printed until the nested launch completes
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt).
+>
+{type="note"}
+
+<!--- TEST
+Task from coroutine scope
+Task from runBlocking
+Task from nested launch
+Coroutine scope is over
+-->
+
+Note that right after the "Task from coroutine scope" message (while waiting for nested launch)
+ "Task from runBlocking" is executed and printed — even though the [coroutineScope][_coroutineScope] is not completed yet.
+
+## Extract function refactoring
+
+Let's extract the block of code inside `launch { ... }` into a separate function. When you
+perform "Extract function" refactoring on this code, you get a new function with the `suspend` modifier.
+This is your first _suspending function_. Suspending functions can be used inside coroutines
+just like regular functions, but their additional feature is that they can, in turn,
+use other suspending functions (like `delay` in this example) to _suspend_ execution of a coroutine.
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ launch { doWorld() }
+ println("Hello,")
+}
+
+// this is your first suspending function
+suspend fun doWorld() {
+ delay(1000L)
+ println("World!")
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt).
+>
+{type="note"}
+
+<!--- TEST
+Hello,
+World!
+-->
+
+But what if the extracted function contains a coroutine builder which is invoked on the current scope?
+In this case, the `suspend` modifier on the extracted function is not enough. Making `doWorld` an extension
+method on `CoroutineScope` is one of the solutions, but it may not always be applicable as it does not make the API clearer.
+The idiomatic solution is to have either an explicit `CoroutineScope` as a field in a class containing the target function
+or an implicit one when the outer class implements `CoroutineScope`.
+As a last resort, [CoroutineScope(coroutineContext)][CoroutineScope()] can be used, but such an approach is structurally unsafe
+because you no longer have control on the scope of execution of this method. Only private APIs can use this builder.
+
+## Coroutines ARE light-weight
+
+Run the following code:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ repeat(100_000) { // launch a lot of coroutines
+ launch {
+ delay(5000L)
+ print(".")
+ }
+ }
+}
+```
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt).
+>
+{type="note"}
+
+<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
+
+It launches 100K coroutines and, after 5 seconds, each coroutine prints a dot.
+
+Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
+
+## Global coroutines are like daemon threads
+
+The following code launches a long-running coroutine in [GlobalScope] that prints "I'm sleeping" twice a second and then
+returns from the main function after some delay:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ GlobalScope.launch {
+ repeat(1000) { i ->
+ println("I'm sleeping $i ...")
+ delay(500L)
+ }
+ }
+ delay(1300L) // just quit after delay
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt).
+>
+{type="note"}
+
+You can run and see that it prints three lines and terminates:
+
+```text
+I'm sleeping 0 ...
+I'm sleeping 1 ...
+I'm sleeping 2 ...
+```
+
+<!--- TEST -->
+
+Active coroutines that were launched in [GlobalScope] do not keep the process alive. They are like daemon threads.
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
+[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
+[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
+[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
+[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
+[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
+[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
+[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope.html
+
+<!--- END -->
\ No newline at end of file
diff --git a/docs/topics/cancellation-and-timeouts.md b/docs/topics/cancellation-and-timeouts.md
new file mode 100644
index 0000000..7aa51e2
--- /dev/null
+++ b/docs/topics/cancellation-and-timeouts.md
@@ -0,0 +1,461 @@
+<!--- TEST_NAME CancellationGuideTest -->
+
+[//]: # (title: Cancellation and timeouts)
+
+This section covers coroutine cancellation and timeouts.
+
+## Cancelling coroutine execution
+
+In a long-running application you might need fine-grained control on your background coroutines.
+For example, a user might have closed the page that launched a coroutine and now its result
+is no longer needed and its operation can be cancelled.
+The [launch] function returns a [Job] that can be used to cancel the running coroutine:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val job = launch {
+ repeat(1000) { i ->
+ println("job: I'm sleeping $i ...")
+ delay(500L)
+ }
+ }
+ delay(1300L) // delay a bit
+ println("main: I'm tired of waiting!")
+ job.cancel() // cancels the job
+ job.join() // waits for job's completion
+ println("main: Now I can quit.")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt).
+>
+{type="note"}
+
+It produces the following output:
+
+```text
+job: I'm sleeping 0 ...
+job: I'm sleeping 1 ...
+job: I'm sleeping 2 ...
+main: I'm tired of waiting!
+main: Now I can quit.
+```
+
+<!--- TEST -->
+
+As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
+There is also a [Job] extension function [cancelAndJoin]
+that combines [cancel][Job.cancel] and [join][Job.join] invocations.
+
+## Cancellation is cooperative
+
+Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
+All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
+coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
+a computation and does not check for cancellation, then it cannot be cancelled, like the following
+example shows:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val startTime = System.currentTimeMillis()
+ val job = launch(Dispatchers.Default) {
+ var nextPrintTime = startTime
+ var i = 0
+ while (i < 5) { // computation loop, just wastes CPU
+ // print a message twice a second
+ if (System.currentTimeMillis() >= nextPrintTime) {
+ println("job: I'm sleeping ${i++} ...")
+ nextPrintTime += 500L
+ }
+ }
+ }
+ delay(1300L) // delay a bit
+ println("main: I'm tired of waiting!")
+ job.cancelAndJoin() // cancels the job and waits for its completion
+ println("main: Now I can quit.")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt).
+>
+{type="note"}
+
+Run it to see that it continues to print "I'm sleeping" even after cancellation
+until the job completes by itself after five iterations.
+
+<!--- TEST
+job: I'm sleeping 0 ...
+job: I'm sleeping 1 ...
+job: I'm sleeping 2 ...
+main: I'm tired of waiting!
+job: I'm sleeping 3 ...
+job: I'm sleeping 4 ...
+main: Now I can quit.
+-->
+
+## Making computation code cancellable
+
+There are two approaches to making computation code cancellable. The first one is to periodically
+invoke a suspending function that checks for cancellation. There is a [yield] function that is a good choice for that purpose.
+The other one is to explicitly check the cancellation status. Let us try the latter approach.
+
+Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val startTime = System.currentTimeMillis()
+ val job = launch(Dispatchers.Default) {
+ var nextPrintTime = startTime
+ var i = 0
+ while (isActive) { // cancellable computation loop
+ // print a message twice a second
+ if (System.currentTimeMillis() >= nextPrintTime) {
+ println("job: I'm sleeping ${i++} ...")
+ nextPrintTime += 500L
+ }
+ }
+ }
+ delay(1300L) // delay a bit
+ println("main: I'm tired of waiting!")
+ job.cancelAndJoin() // cancels the job and waits for its completion
+ println("main: Now I can quit.")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt).
+>
+{type="note"}
+
+As you can see, now this loop is cancelled. [isActive] is an extension property
+available inside the coroutine via the [CoroutineScope] object.
+
+<!--- TEST
+job: I'm sleeping 0 ...
+job: I'm sleeping 1 ...
+job: I'm sleeping 2 ...
+main: I'm tired of waiting!
+main: Now I can quit.
+-->
+
+## Closing resources with `finally`
+
+Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
+the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
+finalization actions normally when a coroutine is cancelled:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val job = launch {
+ try {
+ repeat(1000) { i ->
+ println("job: I'm sleeping $i ...")
+ delay(500L)
+ }
+ } finally {
+ println("job: I'm running finally")
+ }
+ }
+ delay(1300L) // delay a bit
+ println("main: I'm tired of waiting!")
+ job.cancelAndJoin() // cancels the job and waits for its completion
+ println("main: Now I can quit.")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt).
+>
+{type="note"}
+
+Both [join][Job.join] and [cancelAndJoin] wait for all finalization actions to complete,
+so the example above produces the following output:
+
+```text
+job: I'm sleeping 0 ...
+job: I'm sleeping 1 ...
+job: I'm sleeping 2 ...
+main: I'm tired of waiting!
+job: I'm running finally
+main: Now I can quit.
+```
+
+<!--- TEST -->
+
+## Run non-cancellable block
+
+Any attempt to use a suspending function in the `finally` block of the previous example causes
+[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
+problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
+communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
+rare case when you need to suspend in a cancelled coroutine you can wrap the corresponding code in
+`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val job = launch {
+ try {
+ repeat(1000) { i ->
+ println("job: I'm sleeping $i ...")
+ delay(500L)
+ }
+ } finally {
+ withContext(NonCancellable) {
+ println("job: I'm running finally")
+ delay(1000L)
+ println("job: And I've just delayed for 1 sec because I'm non-cancellable")
+ }
+ }
+ }
+ delay(1300L) // delay a bit
+ println("main: I'm tired of waiting!")
+ job.cancelAndJoin() // cancels the job and waits for its completion
+ println("main: Now I can quit.")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt).
+>
+{type="note"}
+
+<!--- TEST
+job: I'm sleeping 0 ...
+job: I'm sleeping 1 ...
+job: I'm sleeping 2 ...
+main: I'm tired of waiting!
+job: I'm running finally
+job: And I've just delayed for 1 sec because I'm non-cancellable
+main: Now I can quit.
+-->
+
+## Timeout
+
+The most obvious practical reason to cancel execution of a coroutine
+is because its execution time has exceeded some timeout.
+While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
+the tracked one after delay, there is a ready to use [withTimeout] function that does it.
+Look at the following example:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ withTimeout(1300L) {
+ repeat(1000) { i ->
+ println("I'm sleeping $i ...")
+ delay(500L)
+ }
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt).
+>
+{type="note"}
+
+It produces the following output:
+
+```text
+I'm sleeping 0 ...
+I'm sleeping 1 ...
+I'm sleeping 2 ...
+Exception in thread "main" kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1300 ms
+```
+
+<!--- TEST STARTS_WITH -->
+
+The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
+We have not seen its stack trace printed on the console before. That is because
+inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
+However, in this example we have used `withTimeout` right inside the `main` function.
+
+Since cancellation is just an exception, all resources are closed in the usual way.
+You can wrap the code with timeout in a `try {...} catch (e: TimeoutCancellationException) {...}` block if
+you need to do some additional action specifically on any kind of timeout or use the [withTimeoutOrNull] function
+that is similar to [withTimeout] but returns `null` on timeout instead of throwing an exception:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val result = withTimeoutOrNull(1300L) {
+ repeat(1000) { i ->
+ println("I'm sleeping $i ...")
+ delay(500L)
+ }
+ "Done" // will get cancelled before it produces this result
+ }
+ println("Result is $result")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt).
+>
+{type="note"}
+
+There is no longer an exception when running this code:
+
+```text
+I'm sleeping 0 ...
+I'm sleeping 1 ...
+I'm sleeping 2 ...
+Result is null
+```
+
+<!--- TEST -->
+
+## Asynchronous timeout and resources
+
+<!--
+ NOTE: Don't change this section name. It is being referenced to from within KDoc of withTimeout functions.
+-->
+
+The timeout event in [withTimeout] is asynchronous with respect to the code running in its block and may happen at any time,
+even right before the return from inside of the timeout block. Keep this in mind if you open or acquire some
+resource inside the block that needs closing or release outside of the block.
+
+For example, here we imitate a closeable resource with the `Resource` class, that simply keeps track of how many times
+it was created by incrementing the `acquired` counter and decrementing this counter from its `close` function.
+Let us run a lot of coroutines with the small timeout try acquire this resource from inside
+of the `withTimeout` block after a bit of delay and release it from outside.
+
+```kotlin
+import kotlinx.coroutines.*
+
+//sampleStart
+var acquired = 0
+
+class Resource {
+ init { acquired++ } // Acquire the resource
+ fun close() { acquired-- } // Release the resource
+}
+
+fun main() {
+ runBlocking {
+ repeat(100_000) { // Launch 100K coroutines
+ launch {
+ val resource = withTimeout(60) { // Timeout of 60 ms
+ delay(50) // Delay for 50 ms
+ Resource() // Acquire a resource and return it from withTimeout block
+ }
+ resource.close() // Release the resource
+ }
+ }
+ }
+ // Outside of runBlocking all coroutines have completed
+ println(acquired) // Print the number of resources still acquired
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt).
+>
+{type="note"}
+
+<!--- CLEAR -->
+
+If you run the above code you'll see that it does not always print zero, though it may depend on the timings
+of your machine you may need to tweak timeouts in this example to actually see non-zero values.
+
+> Note, that incrementing and decrementing `acquired` counter here from 100K coroutines is completely safe,
+> since it always happens from the same main thread. More on that will be explained in the next chapter
+> on coroutine context.
+>
+{type="note"}
+
+To workaround this problem you can store a reference to the resource in the variable as opposed to returning it
+from the `withTimeout` block.
+
+```kotlin
+import kotlinx.coroutines.*
+
+var acquired = 0
+
+class Resource {
+ init { acquired++ } // Acquire the resource
+ fun close() { acquired-- } // Release the resource
+}
+
+fun main() {
+//sampleStart
+ runBlocking {
+ repeat(100_000) { // Launch 100K coroutines
+ launch {
+ var resource: Resource? = null // Not acquired yet
+ try {
+ withTimeout(60) { // Timeout of 60 ms
+ delay(50) // Delay for 50 ms
+ resource = Resource() // Store a resource to the variable if acquired
+ }
+ // We can do something else with the resource here
+ } finally {
+ resource?.close() // Release the resource if it was acquired
+ }
+ }
+ }
+ }
+ // Outside of runBlocking all coroutines have completed
+ println(acquired) // Print the number of resources still acquired
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt).
+>
+{type="note"}
+
+This example always prints zero. Resources do not leak.
+
+<!--- TEST
+0
+-->
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
+[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/cancel-and-join.html
+[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
+[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
+[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
+[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/yield.html
+[isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html
+[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
+[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
+[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-non-cancellable.html
+[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout.html
+[withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html
+
+<!--- END -->
\ No newline at end of file
diff --git a/docs/topics/channels.md b/docs/topics/channels.md
new file mode 100644
index 0000000..9380b2b
--- /dev/null
+++ b/docs/topics/channels.md
@@ -0,0 +1,649 @@
+<!--- TEST_NAME ChannelsGuideTest -->
+
+[//]: # (title: Channels)
+
+Deferred values provide a convenient way to transfer a single value between coroutines.
+Channels provide a way to transfer a stream of values.
+
+## Channel basics
+
+A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
+instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
+a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking {
+//sampleStart
+ val channel = Channel<Int>()
+ launch {
+ // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
+ for (x in 1..5) channel.send(x * x)
+ }
+ // here we print five received integers:
+ repeat(5) { println(channel.receive()) }
+ println("Done!")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+1
+4
+9
+16
+25
+Done!
+```
+
+<!--- TEST -->
+
+## Closing and iteration over channels
+
+Unlike a queue, a channel can be closed to indicate that no more elements are coming.
+On the receiver side it is convenient to use a regular `for` loop to receive elements
+from the channel.
+
+Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
+The iteration stops as soon as this close token is received, so there is a guarantee
+that all previously sent elements before the close are received:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking {
+//sampleStart
+ val channel = Channel<Int>()
+ launch {
+ for (x in 1..5) channel.send(x * x)
+ channel.close() // we're done sending
+ }
+ // here we print received values using `for` loop (until the channel is closed)
+ for (y in channel) println(y)
+ println("Done!")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt).
+>
+{type="note"}
+
+<!--- TEST
+1
+4
+9
+16
+25
+Done!
+-->
+
+## Building channel producers
+
+The pattern where a coroutine is producing a sequence of elements is quite common.
+This is a part of _producer-consumer_ pattern that is often found in concurrent code.
+You could abstract such a producer into a function that takes channel as its parameter, but this goes contrary
+to common sense that results must be returned from functions.
+
+There is a convenient coroutine builder named [produce] that makes it easy to do it right on producer side,
+and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
+ for (x in 1..5) send(x * x)
+}
+
+fun main() = runBlocking {
+//sampleStart
+ val squares = produceSquares()
+ squares.consumeEach { println(it) }
+ println("Done!")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt).
+>
+{type="note"}
+
+<!--- TEST
+1
+4
+9
+16
+25
+Done!
+-->
+
+## Pipelines
+
+A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
+
+```kotlin
+fun CoroutineScope.produceNumbers() = produce<Int> {
+ var x = 1
+ while (true) send(x++) // infinite stream of integers starting from 1
+}
+```
+
+And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
+In the example below, the numbers are just squared:
+
+```kotlin
+fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
+ for (x in numbers) send(x * x)
+}
+```
+
+The main code starts and connects the whole pipeline:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking {
+//sampleStart
+ val numbers = produceNumbers() // produces integers from 1 and on
+ val squares = square(numbers) // squares integers
+ repeat(5) {
+ println(squares.receive()) // print first five
+ }
+ println("Done!") // we are done
+ coroutineContext.cancelChildren() // cancel children coroutines
+//sampleEnd
+}
+
+fun CoroutineScope.produceNumbers() = produce<Int> {
+ var x = 1
+ while (true) send(x++) // infinite stream of integers starting from 1
+}
+
+fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
+ for (x in numbers) send(x * x)
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt).
+>
+{type="note"}
+
+<!--- TEST
+1
+4
+9
+16
+25
+Done!
+-->
+
+> All functions that create coroutines are defined as extensions on [CoroutineScope],
+> so that we can rely on [structured concurrency](composing-suspending-functions.md#structured-concurrency-with-async) to make
+> sure that we don't have lingering global coroutines in our application.
+>
+{type="note"}
+
+## Prime numbers with pipeline
+
+Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
+of coroutines. We start with an infinite sequence of numbers.
+
+```kotlin
+fun CoroutineScope.numbersFrom(start: Int) = produce<Int> {
+ var x = start
+ while (true) send(x++) // infinite stream of integers from start
+}
+```
+
+The following pipeline stage filters an incoming stream of numbers, removing all the numbers
+that are divisible by the given prime number:
+
+```kotlin
+fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> {
+ for (x in numbers) if (x % prime != 0) send(x)
+}
+```
+
+Now we build our pipeline by starting a stream of numbers from 2, taking a prime number from the current channel,
+and launching new pipeline stage for each prime number found:
+
+```Plain Text
+numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
+```
+
+The following example prints the first ten prime numbers,
+running the whole pipeline in the context of the main thread. Since all the coroutines are launched in
+the scope of the main [runBlocking] coroutine
+we don't have to keep an explicit list of all the coroutines we have started.
+We use [cancelChildren][kotlin.coroutines.CoroutineContext.cancelChildren]
+extension function to cancel all the children coroutines after we have printed
+the first ten prime numbers.
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking {
+//sampleStart
+ var cur = numbersFrom(2)
+ repeat(10) {
+ val prime = cur.receive()
+ println(prime)
+ cur = filter(cur, prime)
+ }
+ coroutineContext.cancelChildren() // cancel all children to let main finish
+//sampleEnd
+}
+
+fun CoroutineScope.numbersFrom(start: Int) = produce<Int> {
+ var x = start
+ while (true) send(x++) // infinite stream of integers from start
+}
+
+fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> {
+ for (x in numbers) if (x % prime != 0) send(x)
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+2
+3
+5
+7
+11
+13
+17
+19
+23
+29
+```
+
+<!--- TEST -->
+
+Note that you can build the same pipeline using
+[`iterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/iterator.html)
+coroutine builder from the standard library.
+Replace `produce` with `iterator`, `send` with `yield`, `receive` with `next`,
+`ReceiveChannel` with `Iterator`, and get rid of the coroutine scope. You will not need `runBlocking` either.
+However, the benefit of a pipeline that uses channels as shown above is that it can actually use
+multiple CPU cores if you run it in [Dispatchers.Default] context.
+
+Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
+other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
+built using `sequence`/`iterator`, because they do not allow arbitrary suspension, unlike
+`produce`, which is fully asynchronous.
+
+## Fan-out
+
+Multiple coroutines may receive from the same channel, distributing work between themselves.
+Let us start with a producer coroutine that is periodically producing integers
+(ten numbers per second):
+
+```kotlin
+fun CoroutineScope.produceNumbers() = produce<Int> {
+ var x = 1 // start from 1
+ while (true) {
+ send(x++) // produce next
+ delay(100) // wait 0.1s
+ }
+}
+```
+
+Then we can have several processor coroutines. In this example, they just print their id and
+received number:
+
+```kotlin
+fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
+ for (msg in channel) {
+ println("Processor #$id received $msg")
+ }
+}
+```
+
+Now let us launch five processors and let them work for almost a second. See what happens:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val producer = produceNumbers()
+ repeat(5) { launchProcessor(it, producer) }
+ delay(950)
+ producer.cancel() // cancel producer coroutine and thus kill them all
+//sampleEnd
+}
+
+fun CoroutineScope.produceNumbers() = produce<Int> {
+ var x = 1 // start from 1
+ while (true) {
+ send(x++) // produce next
+ delay(100) // wait 0.1s
+ }
+}
+
+fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
+ for (msg in channel) {
+ println("Processor #$id received $msg")
+ }
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt).
+>
+{type="note"}
+
+The output will be similar to the the following one, albeit the processor ids that receive
+each specific integer may be different:
+
+```text
+Processor #2 received 1
+Processor #4 received 2
+Processor #0 received 3
+Processor #1 received 4
+Processor #3 received 5
+Processor #2 received 6
+Processor #4 received 7
+Processor #0 received 8
+Processor #1 received 9
+Processor #3 received 10
+```
+
+<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
+
+Note that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
+over the channel that processor coroutines are doing.
+
+Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
+Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
+coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
+always consumes (cancels) the underlying channel on its normal or abnormal completion.
+
+## Fan-in
+
+Multiple coroutines may send to the same channel.
+For example, let us have a channel of strings, and a suspending function that
+repeatedly sends a specified string to this channel with a specified delay:
+
+```kotlin
+suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
+ while (true) {
+ delay(time)
+ channel.send(s)
+ }
+}
+```
+
+Now, let us see what happens if we launch a couple of coroutines sending strings
+(in this example we launch them in the context of the main thread as main coroutine's children):
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking {
+//sampleStart
+ val channel = Channel<String>()
+ launch { sendString(channel, "foo", 200L) }
+ launch { sendString(channel, "BAR!", 500L) }
+ repeat(6) { // receive first six
+ println(channel.receive())
+ }
+ coroutineContext.cancelChildren() // cancel all children to let main finish
+//sampleEnd
+}
+
+suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
+ while (true) {
+ delay(time)
+ channel.send(s)
+ }
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt).
+>
+{type="note"}
+
+The output is:
+
+```text
+foo
+foo
+BAR!
+foo
+foo
+BAR!
+```
+
+<!--- TEST -->
+
+## Buffered channels
+
+The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
+meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
+if receive is invoked first, it is suspended until send is invoked.
+
+Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
+specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
+similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
+
+Take a look at the behavior of the following code:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val channel = Channel<Int>(4) // create buffered channel
+ val sender = launch { // launch sender coroutine
+ repeat(10) {
+ println("Sending $it") // print before sending each element
+ channel.send(it) // will suspend when buffer is full
+ }
+ }
+ // don't receive anything... just wait....
+ delay(1000)
+ sender.cancel() // cancel sender coroutine
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt).
+>
+{type="note"}
+
+It prints "sending" _five_ times using a buffered channel with capacity of _four_:
+
+```text
+Sending 0
+Sending 1
+Sending 2
+Sending 3
+Sending 4
+```
+
+<!--- TEST -->
+
+The first four elements are added to the buffer and the sender suspends when trying to send the fifth one.
+
+## Channels are fair
+
+Send and receive operations to channels are _fair_ with respect to the order of their invocation from
+multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
+gets the element. In the following example two coroutines "ping" and "pong" are
+receiving the "ball" object from the shared "table" channel.
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+//sampleStart
+data class Ball(var hits: Int)
+
+fun main() = runBlocking {
+ val table = Channel<Ball>() // a shared table
+ launch { player("ping", table) }
+ launch { player("pong", table) }
+ table.send(Ball(0)) // serve the ball
+ delay(1000) // delay 1 second
+ coroutineContext.cancelChildren() // game over, cancel them
+}
+
+suspend fun player(name: String, table: Channel<Ball>) {
+ for (ball in table) { // receive the ball in a loop
+ ball.hits++
+ println("$name $ball")
+ delay(300) // wait a bit
+ table.send(ball) // send the ball back
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt).
+>
+{type="note"}
+
+The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
+coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
+received by the "pong" coroutine, because it was already waiting for it:
+
+```text
+ping Ball(hits=1)
+pong Ball(hits=2)
+ping Ball(hits=3)
+pong Ball(hits=4)
+```
+
+<!--- TEST -->
+
+Note that sometimes channels may produce executions that look unfair due to the nature of the executor
+that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
+
+## Ticker channels
+
+Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
+Though it may seem to be useless standalone, it is a useful building block to create complex time-based [produce]
+pipelines and operators that do windowing and other time-dependent processing.
+Ticker channel can be used in [select] to perform "on tick" action.
+
+To create such channel use a factory method [ticker].
+To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
+
+Now let's see how it works in practice:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+
+fun main() = runBlocking<Unit> {
+ val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
+ var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
+ println("Initial element is available immediately: $nextElement") // no initial delay
+
+ nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
+ println("Next element is not ready in 50 ms: $nextElement")
+
+ nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
+ println("Next element is ready in 100 ms: $nextElement")
+
+ // Emulate large consumption delays
+ println("Consumer pauses for 150ms")
+ delay(150)
+ // Next element is available immediately
+ nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
+ println("Next element is available immediately after large consumer delay: $nextElement")
+ // Note that the pause between `receive` calls is taken into account and next element arrives faster
+ nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
+ println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
+
+ tickerChannel.cancel() // indicate that no more elements are needed
+}
+```
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt).
+>
+{type="note"}
+
+It prints following lines:
+
+```text
+Initial element is available immediately: kotlin.Unit
+Next element is not ready in 50 ms: null
+Next element is ready in 100 ms: kotlin.Unit
+Consumer pauses for 150ms
+Next element is available immediately after large consumer delay: kotlin.Unit
+Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
+```
+
+<!--- TEST -->
+
+Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
+delay if a pause occurs, trying to maintain a fixed rate of produced elements.
+
+Optionally, a `mode` parameter equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
+delay between elements.
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
+[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
+[kotlin.coroutines.CoroutineContext.cancelChildren]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/kotlin.coroutines.-coroutine-context/cancel-children.html
+[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
+
+<!--- INDEX kotlinx.coroutines.channels -->
+
+[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/index.html
+[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/send.html
+[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
+[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/close.html
+[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
+[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/consume-each.html
+[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel.html
+[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/ticker.html
+[ReceiveChannel.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/cancel.html
+[TickerMode.FIXED_DELAY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-ticker-mode/-f-i-x-e-d_-d-e-l-a-y.html
+
+<!--- INDEX kotlinx.coroutines.selects -->
+
+[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html
+
+<!--- END -->
diff --git a/docs/topics/compatibility.md b/docs/topics/compatibility.md
new file mode 100644
index 0000000..a941443
--- /dev/null
+++ b/docs/topics/compatibility.md
@@ -0,0 +1,129 @@
+<!--- TOC -->
+
+* [Compatibility](#compatibility)
+* [Public API types](#public-api-types)
+ * [Experimental API](#experimental-api)
+ * [Flow preview API](#flow-preview-api)
+ * [Obsolete API](#obsolete-api)
+ * [Internal API](#internal-api)
+ * [Stable API](#stable-api)
+ * [Deprecation cycle](#deprecation-cycle)
+* [Using annotated API](#using-annotated-api)
+ * [Programmatically](#programmatically)
+ * [Gradle](#gradle)
+ * [Maven](#maven)
+
+<!--- END -->
+
+## Compatibility
+This document describes the compatibility policy of `kotlinx.coroutines` library since version 1.0.0 and semantics of compatibility-specific annotations.
+
+
+## Public API types
+`kotlinx.coroutines` public API comes in five flavours: stable, experimental, obsolete, internal and deprecated.
+All public API except stable is marked with the corresponding annotation.
+
+### Experimental API
+Experimental API is marked with [@ExperimentalCoroutinesApi][ExperimentalCoroutinesApi] annotation.
+API is marked experimental when its design has potential open questions which may eventually lead to
+either semantics changes of the API or its deprecation.
+
+By default, most of the new API is marked as experimental and becomes stable in one of the next major releases if no new issues arise.
+Otherwise, either semantics is fixed without changes in ABI or API goes through deprecation cycle.
+
+When using experimental API may be dangerous:
+* You are writing a library which depends on `kotlinx.coroutines` and want to use experimental coroutines API in a stable library API.
+It may lead to undesired consequences when end users of your library update their `kotlinx.coroutines` version where experimental API
+has slightly different semantics.
+* You want to build core infrastructure of the application around experimental API.
+
+### Flow preview API
+All [Flow]-related API is marked with [@FlowPreview][FlowPreview] annotation.
+This annotation indicates that Flow API is in preview status.
+We provide no compatibility guarantees between releases for preview features, including binary, source and semantics compatibility.
+
+When using preview API may be dangerous:
+* You are writing a library/framework and want to use [Flow] API in a stable release or in a stable API.
+* You want to use [Flow] in the core infrastructure of your application.
+* You want to use [Flow] as "write-and-forget" solution and cannot afford additional maintenance cost when
+ it comes to `kotlinx.coroutines` updates.
+
+
+### Obsolete API
+Obsolete API is marked with [@ObsoleteCoroutinesApi][ObsoleteCoroutinesApi] annotation.
+Obsolete API is similar to experimental, but already known to have serious design flaws and its potential replacement,
+but replacement is not yet implemented.
+
+The semantics of this API won't be changed, but it will go through a deprecation cycle as soon as the replacement is ready.
+
+### Internal API
+Internal API is marked with [@InternalCoroutinesApi][InternalCoroutinesApi] or is part of `kotlinx.coroutines.internal` package.
+This API has no guarantees on its stability, can and will be changed and/or removed in the future releases.
+If you can't avoid using internal API, please report it to [issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues/new).
+
+### Stable API
+Stable API is guaranteed to preserve its ABI and documented semantics. If at some point unfixable design flaws will be discovered,
+this API will go through a deprecation cycle and remain binary compatible as long as possible.
+
+### Deprecation cycle
+When some API is deprecated, it goes through multiple stages and there is at least one major release between stages.
+* Feature is deprecated with compilation warning. Most of the time, proper replacement
+(and corresponding `replaceWith` declaration) is provided to automatically migrate deprecated usages with a help of IntelliJ IDEA.
+* Deprecation level is increased to `error` or `hidden`. It is no longer possible to compile new code against deprecated API,
+ though it is still present in the ABI.
+* API is completely removed. While we give our best efforts not to do so and have no plans of removing any API, we still are leaving
+this option in case of unforeseen problems such as security holes.
+
+## Using annotated API
+All API annotations are [kotlin.Experimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-experimental/index.html).
+It is done in order to produce compilation warning about using experimental or obsolete API.
+Warnings can be disabled either programmatically for a specific call site or globally for the whole module.
+
+### Programmatically
+For a specific call-site, warning can be disabled by using [UseExperimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-use-experimental/index.html) annotation:
+```kotlin
+@UseExperimental(ExperimentalCoroutinesApi::class) // Disables warning about experimental coroutines API
+fun experimentalApiUsage() {
+ someKotlinxCoroutinesExperimentalMethod()
+}
+```
+
+### Gradle
+For the Gradle project, a warning can be disabled by passing a compiler flag in your `build.gradle` file:
+
+```groovy
+tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all {
+ kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi"]
+}
+
+```
+
+### Maven
+For the Maven project, a warning can be disabled by passing a compiler flag in your `pom.xml` file:
+```xml
+<plugin>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <groupId>org.jetbrains.kotlin</groupId>
+ ... your configuration ...
+ <configuration>
+ <args>
+ <arg>-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi</arg>
+ </args>
+ </configuration>
+</plugin>
+```
+
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines.flow -->
+
+[Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html
+
+<!--- INDEX kotlinx.coroutines -->
+
+[ExperimentalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-experimental-coroutines-api/index.html
+[FlowPreview]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-flow-preview/index.html
+[ObsoleteCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-obsolete-coroutines-api/index.html
+[InternalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-internal-coroutines-api/index.html
+
+<!--- END -->
diff --git a/docs/topics/composing-suspending-functions.md b/docs/topics/composing-suspending-functions.md
new file mode 100644
index 0000000..0af60d0
--- /dev/null
+++ b/docs/topics/composing-suspending-functions.md
@@ -0,0 +1,406 @@
+<!--- TEST_NAME ComposingGuideTest -->
+
+[//]: # (title: Composing suspending functions)
+
+This section covers various approaches to composition of suspending functions.
+
+## Sequential by default
+
+Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
+remote service call or computation. We just pretend they are useful, but actually each one just
+delays for a second for the purpose of this example:
+
+```kotlin
+suspend fun doSomethingUsefulOne(): Int {
+ delay(1000L) // pretend we are doing something useful here
+ return 13
+}
+
+suspend fun doSomethingUsefulTwo(): Int {
+ delay(1000L) // pretend we are doing something useful here, too
+ return 29
+}
+```
+
+What do we do if we need them to be invoked _sequentially_ — first `doSomethingUsefulOne` _and then_
+`doSomethingUsefulTwo`, and compute the sum of their results?
+In practice we do this if we use the result of the first function to make a decision on whether we need
+to invoke the second one or to decide on how to invoke it.
+
+We use a normal sequential invocation, because the code in the coroutine, just like in the regular
+code, is _sequential_ by default. The following example demonstrates it by measuring the total
+time it takes to execute both suspending functions:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ val one = doSomethingUsefulOne()
+ val two = doSomethingUsefulTwo()
+ println("The answer is ${one + two}")
+ }
+ println("Completed in $time ms")
+//sampleEnd
+}
+
+suspend fun doSomethingUsefulOne(): Int {
+ delay(1000L) // pretend we are doing something useful here
+ return 13
+}
+
+suspend fun doSomethingUsefulTwo(): Int {
+ delay(1000L) // pretend we are doing something useful here, too
+ return 29
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt).
+>
+{type="note"}
+
+It produces something like this:
+
+```text
+The answer is 42
+Completed in 2017 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+## Concurrent using async
+
+What if there are no dependencies between invocations of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
+we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
+
+Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
+that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
+does not carry any resulting value, while `async` returns a [Deferred] — a light-weight non-blocking future
+that represents a promise to provide a result later. You can use `.await()` on a deferred value to get its eventual result,
+but `Deferred` is also a `Job`, so you can cancel it if needed.
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ val one = async { doSomethingUsefulOne() }
+ val two = async { doSomethingUsefulTwo() }
+ println("The answer is ${one.await() + two.await()}")
+ }
+ println("Completed in $time ms")
+//sampleEnd
+}
+
+suspend fun doSomethingUsefulOne(): Int {
+ delay(1000L) // pretend we are doing something useful here
+ return 13
+}
+
+suspend fun doSomethingUsefulTwo(): Int {
+ delay(1000L) // pretend we are doing something useful here, too
+ return 29
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt).
+>
+{type="note"}
+
+It produces something like this:
+
+```text
+The answer is 42
+Completed in 1017 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+This is twice as fast, because the two coroutines execute concurrently.
+Note that concurrency with coroutines is always explicit.
+
+## Lazily started async
+
+Optionally, [async] can be made lazy by setting its `start` parameter to [CoroutineStart.LAZY].
+In this mode it only starts the coroutine when its result is required by
+[await][Deferred.await], or if its `Job`'s [start][Job.start] function
+is invoked. Run the following example:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
+ val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
+ // some computation
+ one.start() // start the first one
+ two.start() // start the second one
+ println("The answer is ${one.await() + two.await()}")
+ }
+ println("Completed in $time ms")
+//sampleEnd
+}
+
+suspend fun doSomethingUsefulOne(): Int {
+ delay(1000L) // pretend we are doing something useful here
+ return 13
+}
+
+suspend fun doSomethingUsefulTwo(): Int {
+ delay(1000L) // pretend we are doing something useful here, too
+ return 29
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt).
+>
+{type="note"}
+
+It produces something like this:
+
+```text
+The answer is 42
+Completed in 1017 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+So, here the two coroutines are defined but not executed as in the previous example, but the control is given to
+the programmer on when exactly to start the execution by calling [start][Job.start]. We first
+start `one`, then start `two`, and then await for the individual coroutines to finish.
+
+Note that if we just call [await][Deferred.await] in `println` without first calling [start][Job.start] on individual
+coroutines, this will lead to sequential behavior, since [await][Deferred.await] starts the coroutine
+execution and waits for its finish, which is not the intended use-case for laziness.
+The use-case for `async(start = CoroutineStart.LAZY)` is a replacement for the
+standard `lazy` function in cases when computation of the value involves suspending functions.
+
+## Async-style functions
+
+We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
+_asynchronously_ using the [async] coroutine builder with an explicit [GlobalScope] reference.
+We name such functions with the
+"...Async" suffix to highlight the fact that they only start asynchronous computation and one needs
+to use the resulting deferred value to get the result.
+
+```kotlin
+// The result type of somethingUsefulOneAsync is Deferred<Int>
+fun somethingUsefulOneAsync() = GlobalScope.async {
+ doSomethingUsefulOne()
+}
+
+// The result type of somethingUsefulTwoAsync is Deferred<Int>
+fun somethingUsefulTwoAsync() = GlobalScope.async {
+ doSomethingUsefulTwo()
+}
+```
+
+Note that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
+However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
+with the invoking code.
+
+The following example shows their use outside of coroutine:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+//sampleStart
+// note that we don't have `runBlocking` to the right of `main` in this example
+fun main() {
+ val time = measureTimeMillis {
+ // we can initiate async actions outside of a coroutine
+ val one = somethingUsefulOneAsync()
+ val two = somethingUsefulTwoAsync()
+ // but waiting for a result must involve either suspending or blocking.
+ // here we use `runBlocking { ... }` to block the main thread while waiting for the result
+ runBlocking {
+ println("The answer is ${one.await() + two.await()}")
+ }
+ }
+ println("Completed in $time ms")
+}
+//sampleEnd
+
+fun somethingUsefulOneAsync() = GlobalScope.async {
+ doSomethingUsefulOne()
+}
+
+fun somethingUsefulTwoAsync() = GlobalScope.async {
+ doSomethingUsefulTwo()
+}
+
+suspend fun doSomethingUsefulOne(): Int {
+ delay(1000L) // pretend we are doing something useful here
+ return 13
+}
+
+suspend fun doSomethingUsefulTwo(): Int {
+ delay(1000L) // pretend we are doing something useful here, too
+ return 29
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+The answer is 42
+Completed in 1085 ms
+-->
+
+> This programming style with async functions is provided here only for illustration, because it is a popular style
+> in other programming languages. Using this style with Kotlin coroutines is **strongly discouraged** for the
+> reasons explained below.
+>
+{type="note"}
+
+Consider what happens if between the `val one = somethingUsefulOneAsync()` line and `one.await()` expression there is some logic
+error in the code and the program throws an exception and the operation that was being performed by the program aborts.
+Normally, a global error-handler could catch this exception, log and report the error for developers, but the program
+could otherwise continue doing other operations. But here we have `somethingUsefulOneAsync` still running in the background,
+even though the operation that initiated it was aborted. This problem does not happen with structured
+concurrency, as shown in the section below.
+
+## Structured concurrency with async
+
+Let us take the [Concurrent using async](#concurrent-using-async) example and extract a function that
+concurrently performs `doSomethingUsefulOne` and `doSomethingUsefulTwo` and returns the sum of their results.
+Because the [async] coroutine builder is defined as an extension on [CoroutineScope], we need to have it in the
+scope and that is what the [coroutineScope][_coroutineScope] function provides:
+
+```kotlin
+suspend fun concurrentSum(): Int = coroutineScope {
+ val one = async { doSomethingUsefulOne() }
+ val two = async { doSomethingUsefulTwo() }
+ one.await() + two.await()
+}
+```
+
+This way, if something goes wrong inside the code of the `concurrentSum` function and it throws an exception,
+all the coroutines that were launched in its scope will be cancelled.
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ println("The answer is ${concurrentSum()}")
+ }
+ println("Completed in $time ms")
+//sampleEnd
+}
+
+suspend fun concurrentSum(): Int = coroutineScope {
+ val one = async { doSomethingUsefulOne() }
+ val two = async { doSomethingUsefulTwo() }
+ one.await() + two.await()
+}
+
+suspend fun doSomethingUsefulOne(): Int {
+ delay(1000L) // pretend we are doing something useful here
+ return 13
+}
+
+suspend fun doSomethingUsefulTwo(): Int {
+ delay(1000L) // pretend we are doing something useful here, too
+ return 29
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt).
+>
+{type="note"}
+
+We still have concurrent execution of both operations, as evident from the output of the above `main` function:
+
+```text
+The answer is 42
+Completed in 1017 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+Cancellation is always propagated through coroutines hierarchy:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+ try {
+ failedConcurrentSum()
+ } catch(e: ArithmeticException) {
+ println("Computation failed with ArithmeticException")
+ }
+}
+
+suspend fun failedConcurrentSum(): Int = coroutineScope {
+ val one = async<Int> {
+ try {
+ delay(Long.MAX_VALUE) // Emulates very long computation
+ 42
+ } finally {
+ println("First child was cancelled")
+ }
+ }
+ val two = async<Int> {
+ println("Second child throws an exception")
+ throw ArithmeticException()
+ }
+ one.await() + two.await()
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt).
+>
+{type="note"}
+
+Note how both the first `async` and the awaiting parent are cancelled on failure of one of the children
+(namely, `two`):
+```text
+Second child throws an exception
+First child was cancelled
+Computation failed with ArithmeticException
+```
+
+<!--- TEST -->
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
+[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
+[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html
+[CoroutineStart.LAZY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-start/-l-a-z-y.html
+[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html
+[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/start.html
+[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
+[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
+[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
+
+<!--- END -->
\ No newline at end of file
diff --git a/docs/topics/coroutine-context-and-dispatchers.md b/docs/topics/coroutine-context-and-dispatchers.md
new file mode 100644
index 0000000..9aae1a7
--- /dev/null
+++ b/docs/topics/coroutine-context-and-dispatchers.md
@@ -0,0 +1,681 @@
+<!--- TEST_NAME DispatcherGuideTest -->
+
+[//]: # (title: Coroutine context and dispatchers)
+
+Coroutines always execute in some context represented by a value of the
+[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/)
+type, defined in the Kotlin standard library.
+
+The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
+which we've seen before, and its dispatcher, which is covered in this section.
+
+## Dispatchers and threads
+
+The coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
+the corresponding coroutine uses for its execution. The coroutine dispatcher can confine coroutine execution
+to a specific thread, dispatch it to a thread pool, or let it run unconfined.
+
+All coroutine builders like [launch] and [async] accept an optional
+[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/)
+parameter that can be used to explicitly specify the dispatcher for the new coroutine and other context elements.
+
+Try the following example:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ launch { // context of the parent, main runBlocking coroutine
+ println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
+ }
+ launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
+ println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
+ }
+ launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher
+ println("Default : I'm working in thread ${Thread.currentThread().name}")
+ }
+ launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
+ println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt).
+>
+{type="note"}
+
+It produces the following output (maybe in different order):
+
+```text
+Unconfined : I'm working in thread main
+Default : I'm working in thread DefaultDispatcher-worker-1
+newSingleThreadContext: I'm working in thread MyOwnThread
+main runBlocking : I'm working in thread main
+```
+
+<!--- TEST LINES_START_UNORDERED -->
+
+When `launch { ... }` is used without parameters, it inherits the context (and thus dispatcher)
+from the [CoroutineScope] it is being launched from. In this case, it inherits the
+context of the main `runBlocking` coroutine which runs in the `main` thread.
+
+[Dispatchers.Unconfined] is a special dispatcher that also appears to run in the `main` thread, but it is,
+in fact, a different mechanism that is explained later.
+
+The default dispatcher that is used when coroutines are launched in [GlobalScope]
+is represented by [Dispatchers.Default] and uses a shared background pool of threads,
+so `launch(Dispatchers.Default) { ... }` uses the same dispatcher as `GlobalScope.launch { ... }`.
+
+[newSingleThreadContext] creates a thread for the coroutine to run.
+A dedicated thread is a very expensive resource.
+In a real application it must be either released, when no longer needed, using the [close][ExecutorCoroutineDispatcher.close]
+function, or stored in a top-level variable and reused throughout the application.
+
+## Unconfined vs confined dispatcher
+
+The [Dispatchers.Unconfined] coroutine dispatcher starts a coroutine in the caller thread, but only until the
+first suspension point. After suspension it resumes the coroutine in the thread that is fully determined by the
+suspending function that was invoked. The unconfined dispatcher is appropriate for coroutines which neither
+consume CPU time nor update any shared data (like UI) confined to a specific thread.
+
+On the other side, the dispatcher is inherited from the outer [CoroutineScope] by default.
+The default dispatcher for the [runBlocking] coroutine, in particular,
+is confined to the invoker thread, so inheriting it has the effect of confining execution to
+this thread with predictable FIFO scheduling.
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
+ println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
+ delay(500)
+ println("Unconfined : After delay in thread ${Thread.currentThread().name}")
+ }
+ launch { // context of the parent, main runBlocking coroutine
+ println("main runBlocking: I'm working in thread ${Thread.currentThread().name}")
+ delay(1000)
+ println("main runBlocking: After delay in thread ${Thread.currentThread().name}")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt).
+>
+{type="note"}
+
+Produces the output:
+
+```text
+Unconfined : I'm working in thread main
+main runBlocking: I'm working in thread main
+Unconfined : After delay in thread kotlinx.coroutines.DefaultExecutor
+main runBlocking: After delay in thread main
+```
+
+<!--- TEST LINES_START -->
+
+So, the coroutine with the context inherited from `runBlocking {...}` continues to execute
+in the `main` thread, while the unconfined one resumes in the default executor thread that the [delay]
+function is using.
+
+> The unconfined dispatcher is an advanced mechanism that can be helpful in certain corner cases where
+> dispatching of a coroutine for its execution later is not needed or produces undesirable side-effects,
+> because some operation in a coroutine must be performed right away.
+> The unconfined dispatcher should not be used in general code.
+>
+{type="note"}
+
+## Debugging coroutines and threads
+
+Coroutines can suspend on one thread and resume on another thread.
+Even with a single-threaded dispatcher it might be hard to
+figure out what the coroutine was doing, where, and when if you don't have special tooling.
+
+### Debugging with IDEA
+
+The Coroutine Debugger of the Kotlin plugin simplifies debugging coroutines in IntelliJ IDEA.
+
+> Debugging works for versions 1.3.8 or later of `kotlinx-coroutines-core`.
+>
+{type="note"}
+
+The **Debug** tool window contains the **Coroutines** tab. In this tab, you can find information about both currently running and suspended coroutines.
+The coroutines are grouped by the dispatcher they are running on.
+
+
+
+With the coroutine debugger, you can:
+* Check the state of each coroutine.
+* See the values of local and captured variables for both running and suspended coroutines.
+* See a full coroutine creation stack, as well as a call stack inside the coroutine. The stack includes all frames with
+variable values, even those that would be lost during standard debugging.
+* Get a full report that contains the state of each coroutine and its stack. To obtain it, right-click inside the **Coroutines** tab, and then click **Get Coroutines Dump**.
+
+To start coroutine debugging, you just need to set breakpoints and run the application in debug mode.
+
+Learn more about coroutines debugging in the [tutorial](https://kotlinlang.org/docs/tutorials/coroutines/debug-coroutines-with-idea.html).
+
+### Debugging using logging
+
+Another approach to debugging applications with
+threads without Coroutine Debugger is to print the thread name in the log file on each log statement. This feature is universally supported
+by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
+`kotlinx.coroutines` includes debugging facilities to make it easier.
+
+Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val a = async {
+ log("I'm computing a piece of the answer")
+ 6
+ }
+ val b = async {
+ log("I'm computing another piece of the answer")
+ 7
+ }
+ log("The answer is ${a.await() * b.await()}")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt).
+>
+{type="note"}
+
+There are three coroutines. The main coroutine (#1) inside `runBlocking`
+and two coroutines computing the deferred values `a` (#2) and `b` (#3).
+They are all executing in the context of `runBlocking` and are confined to the main thread.
+The output of this code is:
+
+```text
+[main @coroutine#2] I'm computing a piece of the answer
+[main @coroutine#3] I'm computing another piece of the answer
+[main @coroutine#1] The answer is 42
+```
+
+<!--- TEST FLEXIBLE_THREAD -->
+
+The `log` function prints the name of the thread in square brackets, and you can see that it is the `main`
+thread with the identifier of the currently executing coroutine appended to it. This identifier
+is consecutively assigned to all created coroutines when the debugging mode is on.
+
+> Debugging mode is also turned on when JVM is run with `-ea` option.
+> You can read more about debugging facilities in the documentation of the [DEBUG_PROPERTY_NAME] property.
+>
+{type="note"}
+
+## Jumping between threads
+
+Run the following code with the `-Dkotlinx.coroutines.debug` JVM option (see [debug](#debugging-coroutines-and-threads)):
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
+
+fun main() {
+//sampleStart
+ newSingleThreadContext("Ctx1").use { ctx1 ->
+ newSingleThreadContext("Ctx2").use { ctx2 ->
+ runBlocking(ctx1) {
+ log("Started in ctx1")
+ withContext(ctx2) {
+ log("Working in ctx2")
+ }
+ log("Back to ctx1")
+ }
+ }
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt).
+>
+{type="note"}
+
+It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
+the other one is using the [withContext] function to change the context of a coroutine while still staying in the
+same coroutine, as you can see in the output below:
+
+```text
+[Ctx1 @coroutine#1] Started in ctx1
+[Ctx2 @coroutine#1] Working in ctx2
+[Ctx1 @coroutine#1] Back to ctx1
+```
+
+<!--- TEST -->
+
+Note that this example also uses the `use` function from the Kotlin standard library to release threads
+created with [newSingleThreadContext] when they are no longer needed.
+
+## Job in the context
+
+The coroutine's [Job] is part of its context, and can be retrieved from it
+using the `coroutineContext[Job]` expression:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ println("My job is ${coroutineContext[Job]}")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt).
+>
+{type="note"}
+
+In the [debug mode](#debugging-coroutines-and-threads), it outputs something like this:
+
+```
+My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
+```
+
+<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
+
+Note that [isActive] in [CoroutineScope] is just a convenient shortcut for
+`coroutineContext[Job]?.isActive == true`.
+
+## Children of a coroutine
+
+When a coroutine is launched in the [CoroutineScope] of another coroutine,
+it inherits its context via [CoroutineScope.coroutineContext] and
+the [Job] of the new coroutine becomes
+a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
+are recursively cancelled, too.
+
+However, when [GlobalScope] is used to launch a coroutine, there is no parent for the job of the new coroutine.
+It is therefore not tied to the scope it was launched from and operates independently.
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ // launch a coroutine to process some kind of incoming request
+ val request = launch {
+ // it spawns two other jobs, one with GlobalScope
+ GlobalScope.launch {
+ println("job1: I run in GlobalScope and execute independently!")
+ delay(1000)
+ println("job1: I am not affected by cancellation of the request")
+ }
+ // and the other inherits the parent context
+ launch {
+ delay(100)
+ println("job2: I am a child of the request coroutine")
+ delay(1000)
+ println("job2: I will not execute this line if my parent request is cancelled")
+ }
+ }
+ delay(500)
+ request.cancel() // cancel processing of the request
+ delay(1000) // delay a second to see what happens
+ println("main: Who has survived request cancellation?")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+job1: I run in GlobalScope and execute independently!
+job2: I am a child of the request coroutine
+job1: I am not affected by cancellation of the request
+main: Who has survived request cancellation?
+```
+
+<!--- TEST -->
+
+## Parental responsibilities
+
+A parent coroutine always waits for completion of all its children. A parent does not have to explicitly track
+all the children it launches, and it does not have to use [Job.join] to wait for them at the end:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ // launch a coroutine to process some kind of incoming request
+ val request = launch {
+ repeat(3) { i -> // launch a few children jobs
+ launch {
+ delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
+ println("Coroutine $i is done")
+ }
+ }
+ println("request: I'm done and I don't explicitly join my children that are still active")
+ }
+ request.join() // wait for completion of the request, including all its children
+ println("Now processing of the request is complete")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt).
+>
+{type="note"}
+
+The result is going to be:
+
+```text
+request: I'm done and I don't explicitly join my children that are still active
+Coroutine 0 is done
+Coroutine 1 is done
+Coroutine 2 is done
+Now processing of the request is complete
+```
+
+<!--- TEST -->
+
+## Naming coroutines for debugging
+
+Automatically assigned ids are good when coroutines log often and you just need to correlate log records
+coming from the same coroutine. However, when a coroutine is tied to the processing of a specific request
+or doing some specific background task, it is better to name it explicitly for debugging purposes.
+The [CoroutineName] context element serves the same purpose as the thread name. It is included in the thread name that
+is executing this coroutine when the [debugging mode](#debugging-coroutines-and-threads) is turned on.
+
+The following example demonstrates this concept:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
+
+fun main() = runBlocking(CoroutineName("main")) {
+//sampleStart
+ log("Started main coroutine")
+ // run two background value computations
+ val v1 = async(CoroutineName("v1coroutine")) {
+ delay(500)
+ log("Computing v1")
+ 252
+ }
+ val v2 = async(CoroutineName("v2coroutine")) {
+ delay(1000)
+ log("Computing v2")
+ 6
+ }
+ log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt).
+>
+{type="note"}
+
+The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
+
+```text
+[main @main#1] Started main coroutine
+[main @v1coroutine#2] Computing v1
+[main @v2coroutine#3] Computing v2
+[main @main#1] The answer for v1 / v2 = 42
+```
+
+<!--- TEST FLEXIBLE_THREAD -->
+
+## Combining context elements
+
+Sometimes we need to define multiple elements for a coroutine context. We can use the `+` operator for that.
+For example, we can launch a coroutine with an explicitly specified dispatcher and an explicitly specified
+name at the same time:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ launch(Dispatchers.Default + CoroutineName("test")) {
+ println("I'm working in thread ${Thread.currentThread().name}")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt).
+>
+{type="note"}
+
+The output of this code with the `-Dkotlinx.coroutines.debug` JVM option is:
+
+```text
+I'm working in thread DefaultDispatcher-worker-1 @test#2
+```
+
+<!--- TEST FLEXIBLE_THREAD -->
+
+## Coroutine scope
+
+Let us put our knowledge about contexts, children and jobs together. Assume that our application has
+an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
+and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
+and update data, do animations, etc. All of these coroutines must be cancelled when the activity is destroyed
+to avoid memory leaks. We, of course, can manipulate contexts and jobs manually to tie the lifecycles of the activity
+and its coroutines, but `kotlinx.coroutines` provides an abstraction encapsulating that: [CoroutineScope].
+You should be already familiar with the coroutine scope as all coroutine builders are declared as extensions on it.
+
+We manage the lifecycles of our coroutines by creating an instance of [CoroutineScope] tied to
+the lifecycle of our activity. A `CoroutineScope` instance can be created by the [CoroutineScope()] or [MainScope()]
+factory functions. The former creates a general-purpose scope, while the latter creates a scope for UI applications and uses
+[Dispatchers.Main] as the default dispatcher:
+
+```kotlin
+class Activity {
+ private val mainScope = MainScope()
+
+ fun destroy() {
+ mainScope.cancel()
+ }
+ // to be continued ...
+```
+
+Now, we can launch coroutines in the scope of this `Activity` using the defined `scope`.
+For the demo, we launch ten coroutines that delay for a different time:
+
+```kotlin
+ // class Activity continues
+ fun doSomething() {
+ // launch ten coroutines for a demo, each working for a different time
+ repeat(10) { i ->
+ mainScope.launch {
+ delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
+ println("Coroutine $i is done")
+ }
+ }
+ }
+} // class Activity ends
+```
+
+In our main function we create the activity, call our test `doSomething` function, and destroy the activity after 500ms.
+This cancels all the coroutines that were launched from `doSomething`. We can see that because after the destruction
+of the activity no more messages are printed, even if we wait a little longer.
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+
+class Activity {
+ private val mainScope = CoroutineScope(Dispatchers.Default) // use Default for test purposes
+
+ fun destroy() {
+ mainScope.cancel()
+ }
+
+ fun doSomething() {
+ // launch ten coroutines for a demo, each working for a different time
+ repeat(10) { i ->
+ mainScope.launch {
+ delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
+ println("Coroutine $i is done")
+ }
+ }
+ }
+} // class Activity ends
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val activity = Activity()
+ activity.doSomething() // run test function
+ println("Launched coroutines")
+ delay(500L) // delay for half a second
+ println("Destroying activity!")
+ activity.destroy() // cancels all coroutines
+ delay(1000) // visually confirm that they don't work
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt).
+>
+{type="note"}
+
+The output of this example is:
+
+```text
+Launched coroutines
+Coroutine 0 is done
+Coroutine 1 is done
+Destroying activity!
+```
+
+<!--- TEST -->
+
+As you can see, only the first two coroutines print a message and the others are cancelled
+by a single invocation of `job.cancel()` in `Activity.destroy()`.
+
+> Note, that Android has first-party support for coroutine scope in all entities with the lifecycle.
+> See [the corresponding documentation](https://developer.android.com/topic/libraries/architecture/coroutines#lifecyclescope).
+>
+{type="note"}
+
+### Thread-local data
+
+Sometimes it is convenient to have an ability to pass some thread-local data to or between coroutines.
+However, since they are not bound to any particular thread, this will likely lead to boilerplate if done manually.
+
+For [`ThreadLocal`](https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html),
+the [asContextElement] extension function is here for the rescue. It creates an additional context element
+which keeps the value of the given `ThreadLocal` and restores it every time the coroutine switches its context.
+
+It is easy to demonstrate it in action:
+
+```kotlin
+import kotlinx.coroutines.*
+
+val threadLocal = ThreadLocal<String?>() // declare thread-local variable
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ threadLocal.set("main")
+ println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
+ val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) {
+ println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
+ yield()
+ println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
+ }
+ job.join()
+ println("Post-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt).
+>
+{type="note"}
+
+In this example we launch a new coroutine in a background thread pool using [Dispatchers.Default], so
+it works on a different thread from the thread pool, but it still has the value of the thread local variable
+that we specified using `threadLocal.asContextElement(value = "launch")`,
+no matter which thread the coroutine is executed on.
+Thus, the output (with [debug](#debugging-coroutines-and-threads)) is:
+
+```text
+Pre-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
+Launch start, current thread: Thread[DefaultDispatcher-worker-1 @coroutine#2,5,main], thread local value: 'launch'
+After yield, current thread: Thread[DefaultDispatcher-worker-2 @coroutine#2,5,main], thread local value: 'launch'
+Post-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
+```
+
+<!--- TEST FLEXIBLE_THREAD -->
+
+It's easy to forget to set the corresponding context element. The thread-local variable accessed from the coroutine may
+then have an unexpected value, if the thread running the coroutine is different.
+To avoid such situations, it is recommended to use the [ensurePresent] method
+and fail-fast on improper usages.
+
+`ThreadLocal` has first-class support and can be used with any primitive `kotlinx.coroutines` provides.
+It has one key limitation, though: when a thread-local is mutated, a new value is not propagated to the coroutine caller
+(because a context element cannot track all `ThreadLocal` object accesses), and the updated value is lost on the next suspension.
+Use [withContext] to update the value of the thread-local in a coroutine, see [asContextElement] for more details.
+
+Alternatively, a value can be stored in a mutable box like `class Counter(var i: Int)`, which is, in turn,
+stored in a thread-local variable. However, in this case you are fully responsible to synchronize
+potentially concurrent modifications to the variable in this mutable box.
+
+For advanced usage, for example for integration with logging MDC, transactional contexts or any other libraries
+which internally use thread-locals for passing data, see the documentation of the [ThreadContextElement] interface
+that should be implemented.
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html
+[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
+[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
+[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
+[Dispatchers.Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-unconfined.html
+[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
+[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
+[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/new-single-thread-context.html
+[ExecutorCoroutineDispatcher.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-executor-coroutine-dispatcher/close.html
+[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
+[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
+[DEBUG_PROPERTY_NAME]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-d-e-b-u-g_-p-r-o-p-e-r-t-y_-n-a-m-e.html
+[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
+[isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html
+[CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/coroutine-context.html
+[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
+[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html
+[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope.html
+[MainScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html
+[Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html
+[asContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/as-context-element.html
+[ensurePresent]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/ensure-present.html
+[ThreadContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/index.html
+
+<!--- END -->
\ No newline at end of file
diff --git a/docs/topics/coroutines-basic-jvm.md b/docs/topics/coroutines-basic-jvm.md
new file mode 100644
index 0000000..59cc432
--- /dev/null
+++ b/docs/topics/coroutines-basic-jvm.md
@@ -0,0 +1,277 @@
+[//]: # (title: Create a basic coroutine – tutorial)
+
+Kotlin 1.1 introduced coroutines, a new way of writing asynchronous, non-blocking code (and much more). In this tutorial you will go through some basics of using Kotlin coroutines with the help of the `kotlinx.coroutines` library, which is a collection of helpers and wrappers for existing Java libraries.
+
+## Set up a project
+
+### Gradle
+
+In IntelliJ IDEA go to **File** \| **New** \| **Project**.:
+
+
+
+Then follow the wizard steps. You'll have a `build.gradle` file created with Kotlin configured according to [this document](gradle.md).
+Make sure it's configured for Kotlin 1.3 or higher.
+
+Since we'll be using the [`kotlinx.coroutines`](https://github.com/Kotlin/kotlinx.coroutines), let's add its recent version to our dependencies:
+
+<tabs>
+
+```groovy
+dependencies {
+ ...
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%'
+}
+```
+
+```kotlin
+dependencies {
+ ...
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%")
+}
+```
+</tabs>
+
+This library is published to Bintray JCenter repository, so add the following:
+
+```groovy
+repositories {
+ jcenter()
+}
+```
+
+That's it, we are good to go and write code under `src/main/kotlin`.
+
+### Maven
+
+In IntelliJ IDEA go to **File** \| **New** \| **Project** and check the **Create from archetype** box:
+
+
+
+Then follow the wizard steps. You'll have a `pom.xml` file created with Kotlin configured according to [this document](maven.md).
+Make sure it's configured for Kotlin 1.3 or higher.
+
+```xml
+<plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ ...
+ <configuration>
+ <args>
+ <arg>-Xcoroutines=enable</arg>
+ </args>
+ </configuration>
+</plugin>
+```
+
+Since we'll be using the [`kotlinx.coroutines`](https://github.com/Kotlin/kotlinx.coroutines), let's add its recent version to our dependencies:
+
+```xml
+<dependencies>
+ ...
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-coroutines-core</artifactId>
+ <version>%coroutinesVersion%</version>
+ </dependency>
+</dependencies>
+```
+
+This library is published to Bintray JCenter repository, so let us add it:
+
+```xml
+<repositories>
+ ...
+ <repository>
+ <id>central</id>
+ <url>https://jcenter.bintray.com</url>
+ </repository>
+</repositories>
+```
+
+That's it, we are good to go and write code under `src/main/kotlin`.
+
+## My first coroutine
+
+One can think of a coroutine as a light-weight thread. Like threads, coroutines can run in parallel, wait for each other and communicate.
+The biggest difference is that coroutines are very cheap, almost free: we can create thousands of them, and pay very little in terms of performance.
+True threads, on the other hand, are expensive to start and keep around. A thousand threads can be a serious challenge for a modern machine.
+
+So, how do we start a coroutine? Let's use the `launch {}` function:
+
+```kotlin
+launch {
+ ...
+}
+```
+
+This starts a new coroutine. By default, coroutines are run on a shared pool of threads.
+Threads still exist in a program based on coroutines, but one thread can run many coroutines, so there's no need for
+too many threads.
+
+Let's look at a full program that uses `launch`:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main(args: Array<String>) {
+//sampleStart
+ println("Start")
+
+ // Start a coroutine
+ GlobalScope.launch {
+ delay(1000)
+ println("Hello")
+ }
+
+ Thread.sleep(2000) // wait for 2 seconds
+ println("Stop")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+Here we start a coroutine that waits for 1 second and prints `Hello`.
+
+We are using the `delay()` function that's like `Thread.sleep()`, but better: it _doesn't block a thread_, but only suspends the coroutine itself.
+The thread is returned to the pool while the coroutine is waiting, and when the waiting is done, the coroutine resumes on a free thread in the pool.
+
+The main thread (that runs the `main()` function) must wait until our coroutine completes, otherwise the program ends before `Hello` is printed.
+
+_Exercise: try removing the `sleep()` from the program above and see the result._
+
+ If we try to use the same non-blocking `delay()` function directly inside `main()`, we'll get a compiler error:
+
+> Suspend functions are only allowed to be called from a coroutine or another suspend function.
+>
+{type="note"}
+
+This is because we are not inside any coroutine. We can use delay if we wrap it into `runBlocking {}` that starts a coroutine and waits until it's done:
+
+```kotlin
+runBlocking {
+ delay(2000)
+}
+```
+
+So, first the resulting program prints `Start`, then it runs a coroutine through `launch {}`, then it runs another one through `runBlocking {}` and blocks until it's done, then prints `Stop`. Meanwhile the first coroutine completes and prints `Hello`. Just like threads, we told you :)
+
+## Let's run a lot of them
+
+Now, let's make sure that coroutines are really cheaper than threads. How about starting a million of them? Let's try starting a million threads first:
+
+```kotlin
+val c = AtomicLong()
+
+for (i in 1..1_000_000L)
+ thread(start = true) {
+ c.addAndGet(i)
+ }
+
+println(c.get())
+```
+
+This runs a 1'000'000 threads each of which adds to a common counter. My patience runs out before this program completes on my machine (definitely over a minute).
+
+Let's try the same with coroutines:
+
+```kotlin
+val c = AtomicLong()
+
+for (i in 1..1_000_000L)
+ GlobalScope.launch {
+ c.addAndGet(i)
+ }
+
+println(c.get())
+```
+
+This example completes in less than a second for me, but it prints some arbitrary number, because some coroutines don't finish before `main()` prints the result. Let's fix that.
+
+We could use the same means of synchronization that are applicable to threads (a `CountDownLatch` is what crosses my mind in this case), but let's take a safer and cleaner path.
+
+## Async: returning a value from a coroutine
+
+Another way of starting a coroutine is `async {}`. It is like `launch {}`, but returns an instance of `Deferred<T>`, which has an `await()` function that returns the result of the coroutine. `Deferred<T>` is a very basic [future](https://en.wikipedia.org/wiki/Futures_and_promises) (fully-fledged JDK futures are also supported, but here we'll confine ourselves to `Deferred` for now).
+
+Let's create a million coroutines again, keeping their `Deferred` objects. Now there's no need in the atomic counter, as we can just return the numbers to be added from our coroutines:
+
+```kotlin
+val deferred = (1..1_000_000).map { n ->
+ GlobalScope.async {
+ n
+ }
+}
+```
+
+All these have already started, all we need is collect the results:
+
+```kotlin
+val sum = deferred.sumOf { it.await().toLong() }
+```
+
+We simply take every coroutine and await its result here, then all results are added together by the standard library function `sumOf()`. But the compiler rightfully complains:
+
+> Suspend functions are only allowed to be called from a coroutine or another suspend function.
+>
+{type="note"}
+
+`await()` can not be called outside a coroutine, because it needs to suspend until the computation finishes, and only coroutines can suspend in a non-blocking way. So, let's put this inside a coroutine:
+
+```kotlin
+runBlocking {
+ val sum = deferred.sumOf { it.await().toLong() }
+ println("Sum: $sum")
+}
+```
+
+Now it prints something sensible: `500000500000`, because all coroutines complete.
+
+Let's also make sure that our coroutines actually run in parallel. If we add a 1-second `delay()` to each of the `async`'s, the resulting program won't run for 1'000'000 seconds (over 11,5 days):
+
+```kotlin
+val deferred = (1..1_000_000).map { n ->
+ GlobalScope.async {
+ delay(1000)
+ n
+ }
+}
+```
+
+This takes about 10 seconds on my machine, so yes, coroutines do run in parallel.
+
+## Suspending functions
+
+Now, let's say we want to extract our _workload_ (which is "wait 1 second and return a number") into a separate function:
+
+```kotlin
+fun workload(n: Int): Int {
+ delay(1000)
+ return n
+}
+```
+
+A familiar error pops up:
+
+> Suspend functions are only allowed to be called from a coroutine or another suspend function.
+>
+{type="note"}
+
+Let's dig a little into what it means. The biggest merit of coroutines is that they can _suspend_ without blocking a thread. The compiler has to emit some special code to make this possible, so we have to mark functions that _may suspend_ explicitly in the code. We use the `suspend` modifier for it:
+
+```kotlin
+suspend fun workload(n: Int): Int {
+ delay(1000)
+ return n
+}
+```
+
+Now when we call `workload()` from a coroutine, the compiler knows that it may suspend and will prepare accordingly:
+
+```kotlin
+GlobalScope.async {
+ workload(n)
+}
+```
+
+Our `workload()` function can be called from a coroutine (or another suspending function), but _cannot_ be called from outside a coroutine. Naturally, `delay()` and `await()` that we used above are themselves declared as `suspend`, and this is why we had to put them inside `runBlocking {}`, `launch {}` or `async {}`.
diff --git a/docs/topics/coroutines-guide.md b/docs/topics/coroutines-guide.md
new file mode 100644
index 0000000..21a64cc
--- /dev/null
+++ b/docs/topics/coroutines-guide.md
@@ -0,0 +1,37 @@
+[//]: # (title: Coroutines guide)
+
+Kotlin, as a language, provides only minimal low-level APIs in its standard library to enable various other
+libraries to utilize coroutines. Unlike many other languages with similar capabilities, `async` and `await`
+are not keywords in Kotlin and are not even part of its standard library. Moreover, Kotlin's concept
+of _suspending function_ provides a safer and less error-prone abstraction for asynchronous
+operations than futures and promises.
+
+`kotlinx.coroutines` is a rich library for coroutines developed by JetBrains. It contains a number of high-level
+coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
+
+This is a guide on core features of `kotlinx.coroutines` with a series of examples, divided up into different topics.
+
+In order to use coroutines as well as follow the examples in this guide, you need to add a dependency on the `kotlinx-coroutines-core` module as explained
+[in the project README](https://github.com/Kotlin/kotlinx.coroutines/blob/master/README.md#using-in-your-projects).
+
+## Table of contents
+
+* [Coroutines basics](basics.md)
+* [Tutorial: Create a basic coroutine](coroutines-basic-jvm.md)
+* [Hands-on: Intro to coroutines and channels](https://play.kotlinlang.org/hands-on/Introduction%20to%20Coroutines%20and%20Channels)
+* [Cancellation and timeouts](cancellation-and-timeouts.md)
+* [Composing suspending functions](composing-suspending-functions.md)
+* [Coroutine context and dispatchers](coroutine-context-and-dispatchers.md)
+* [Asynchronous Flow](flow.md)
+* [Channels](channels.md)
+* [Coroutine exceptions handling](exception-handling.md)
+* [Shared mutable state and concurrency](shared-mutable-state-and-concurrency.md)
+* [Select expression (experimental)](select-expression.md)
+* [Tutorial: Debug coroutines using IntelliJ IDEA](debug-coroutines-with-idea.md)
+* [Tutorial: Debug Kotlin Flow using IntelliJ IDEA](debug-flow-with-idea.md)
+
+## Additional references
+
+* [Guide to UI programming with coroutines](../../ui/coroutines-guide-ui.md)
+* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
+* [Full kotlinx.coroutines API reference](https://kotlin.github.io/kotlinx.coroutines)
diff --git a/docs/topics/debug-coroutines-with-idea.md b/docs/topics/debug-coroutines-with-idea.md
new file mode 100644
index 0000000..c44bafc
--- /dev/null
+++ b/docs/topics/debug-coroutines-with-idea.md
@@ -0,0 +1,82 @@
+[//]: # (title: Debug coroutines using IntelliJ IDEA – tutorial)
+
+This tutorial demonstrates how to create Kotlin coroutines and debug them using IntelliJ IDEA.
+
+The tutorial assumes you have prior knowledge of the [coroutines](coroutines-guide.md) concept.
+
+> Debugging works for `kotlinx-coroutines-core` version 1.3.8 or later.
+>
+{type="note"}
+
+## Create coroutines
+
+1. Open a Kotlin project in IntelliJ IDEA. If you don't have a project, [create one](jvm-get-started.md#create-an-application).
+
+2. Open the `main.kt` file in `src/main/kotlin`.
+
+ The `src` directory contains Kotlin source files and resources. The `main.kt` file contains sample code that will print `Hello World!`.
+
+2. Change code in the `main()` function:
+
+ * Use the [`runBlocking()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) block to wrap a coroutine.
+ * Use the [`async()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html) function to create coroutines that compute deferred values `a` and `b`.
+ * Use the [`await()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html) function to await the computation result.
+ * Use the [`println()`](https://kotlinlang.org//api/latest/jvm/stdlib/stdlib/kotlin.io/println.html) function to print computing status and the result of multiplication to the output.
+
+ ```kotlin
+ import kotlinx.coroutines.*
+
+ fun main() = runBlocking<Unit> {
+ val a = async {
+ println("I'm computing part of the answer")
+ 6
+ }
+ val b = async {
+ println("I'm computing another part of the answer")
+ 7
+ }
+ println("The answer is ${a.await() * b.await()}")
+ }
+ ```
+
+4. Build the code by clicking **Build Project**.
+
+ 
+
+## Debug coroutines
+
+1. Set breakpoints at the lines with the `println()` function call:
+
+ 
+
+2. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
+
+ 
+
+ The **Debug** tool window appears:
+ * The **Frames** tab contains the call stack.
+ * The **Variables** tab contains variables in the current context.
+ * The **Coroutines** tab contains information on running or suspended coroutines. It shows that there are three coroutines.
+ The first one has the **RUNNING** status, and the other two have the **CREATED** status.
+
+ 
+
+3. Resume the debugger session by clicking **Resume program** in the **Debug** tool window:
+
+ 
+
+ Now the **Coroutines** tab shows the following:
+ * The first coroutine has the **SUSPENDED** status – it is waiting for the values so it can multiply them.
+ * The second coroutine is calculating the `a` value – it has the **RUNNING** status.
+ * The third coroutine has the **CREATED** status and isn’t calculating the value of `b`.
+
+4. Resume the debugger session by clicking **Resume program** in the **Debug** tool window:
+
+ 
+
+ Now the **Coroutines** tab shows the following:
+ * The first coroutine has the **SUSPENDED** status – it is waiting for the values so it can multiply them.
+ * The second coroutine has computed its value and disappeared.
+ * The third coroutine is calculating the value of `b` – it has the **RUNNING** status.
+
+Using IntelliJ IDEA debugger, you can dig deeper into each coroutine to debug your code.
\ No newline at end of file
diff --git a/docs/topics/debug-flow-with-idea.md b/docs/topics/debug-flow-with-idea.md
new file mode 100644
index 0000000..745dcb1
--- /dev/null
+++ b/docs/topics/debug-flow-with-idea.md
@@ -0,0 +1,126 @@
+[//]: # (title: Debug Kotlin Flow using IntelliJ IDEA – tutorial)
+
+This tutorial demonstrates how to create Kotlin Flow and debug it using IntelliJ IDEA.
+
+The tutorial assumes you have prior knowledge of the [coroutines](coroutines-guide.md) and [Kotlin Flow](flow.md#flows) concepts.
+
+> Debugging works for `kotlinx-coroutines-core` version 1.3.8 or later.
+>
+{type="note"}
+
+## Create a Kotlin flow
+
+Create a Kotlin [flow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow.html) with a slow emitter and a slow collector:
+
+1. Open a Kotlin project in IntelliJ IDEA. If you don't have a project, [create one](jvm-get-started.md#create-an-application).
+
+2. Open the `main.kt` file in `src/main/kotlin`.
+
+ The `src` directory contains Kotlin source files and resources. The `main.kt` file contains sample code that will print `Hello World!`.
+
+2. Create the `simple()` function that returns a flow of three numbers:
+
+ * Use the [`delay()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html) function to imitate CPU-consuming blocking code. It suspends the coroutine for 100 ms without blocking the thread.
+ * Produce the values in the `for` loop using the [`emit()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow-collector/emit.html) function.
+
+ ```kotlin
+ import kotlinx.coroutines.*
+ import kotlinx.coroutines.flow.*
+ import kotlin.system.*
+
+ fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ delay(100)
+ emit(i)
+ }
+ }
+ ```
+
+3. Change the code in the `main()` function:
+
+ * Use the [`runBlocking()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) block to wrap a coroutine.
+ * Collect the emitted values using the [`collect()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect.html) function.
+ * Use the [`delay()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html) function to imitate CPU-consuming code. It suspends the coroutine for 300 ms without blocking the thread.
+ * Print the collected value from the flow using the [`println()`](https://kotlinlang.org/api/latest/jvm/stdlib/stdlib/kotlin.io/println.html) function.
+
+ ```kotlin
+ fun main() = runBlocking {
+ simple()
+ .collect { value ->
+ delay(300)
+ println(value)
+ }
+ }
+ ```
+
+4. Build the code by clicking **Build Project**.
+
+ 
+
+## Debug the coroutine
+
+1. Set a breakpoint at the at the line where the `emit()` function is called:
+
+ 
+
+2. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
+
+ 
+
+ The **Debug** tool window appears:
+ * The **Frames** tab contains the call stack.
+ * The **Variables** tab contains variables in the current context. It tells us that the flow is emitting the first value.
+ * The **Coroutines** tab contains information on running or suspended coroutines.
+
+ 
+
+3. Resume the debugger session by clicking **Resume program** in the **Debug** tool window. The program stops at the same breakpoint.
+
+ 
+
+ Now the flow emits the second value.
+
+ 
+
+## Add a concurrently running coroutine
+
+1. Open the `main.kt` file in `src/main/kotlin`.
+
+2. Enhance the code to run the emitter and collector concurrently:
+
+ * Add a call to the [`buffer()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/buffer.html) function to run the emitter and collector concurrently. `buffer()` stores emitted values and runs the flow collector in a separate coroutine.
+
+ ```kotlin
+ fun main() = runBlocking<Unit> {
+ simple()
+ .buffer()
+ .collect { value ->
+ delay(300)
+ println(value)
+ }
+ }
+ ```
+
+4. Build the code by clicking **Build Project**.
+
+## Debug a Kotlin flow with two coroutines
+
+1. Set a new breakpoint at `println(value)`.
+
+2. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
+
+ 
+
+ The **Debug** tool window appears.
+
+ In the **Coroutines** tab, you can see that there are two coroutines running concurrently. The flow collector and emitter run in separate coroutines because of the `buffer()` function.
+ The `buffer()` function buffers emitted values from the flow.
+ The emitter coroutine has the **RUNNING** status, and the collector coroutine has the **SUSPENDED** status.
+
+2. Resume the debugger session by clicking **Resume program** in the **Debug** tool window.
+
+ 
+
+ Now the collector coroutine has the **RUNNING** status, while the emitter coroutine has the **SUSPENDED** status.
+
+ You can dig deeper into each coroutine to debug your code.
\ No newline at end of file
diff --git a/docs/topics/debugging.md b/docs/topics/debugging.md
new file mode 100644
index 0000000..c0df045
--- /dev/null
+++ b/docs/topics/debugging.md
@@ -0,0 +1,108 @@
+**Table of contents**
+
+<!--- TOC -->
+
+* [Debugging coroutines](#debugging-coroutines)
+* [Debug mode](#debug-mode)
+* [Stacktrace recovery](#stacktrace-recovery)
+ * [Stacktrace recovery machinery](#stacktrace-recovery-machinery)
+* [Debug agent](#debug-agent)
+ * [Debug agent and Android](#debug-agent-and-android)
+* [Android optimization](#android-optimization)
+
+<!--- END -->
+
+## Debugging coroutines
+
+Debugging asynchronous programs is challenging, because multiple concurrent coroutines are typically working at the same time.
+To help with that, `kotlinx.coroutines` comes with additional features for debugging: debug mode, stacktrace recovery
+and debug agent.
+
+## Debug mode
+
+The first debugging feature of `kotlinx.coroutines` is debug mode.
+It can be enabled either by setting system property [DEBUG_PROPERTY_NAME] or by running Java with enabled assertions (`-ea` flag).
+The latter is helpful to have debug mode enabled by default in unit tests.
+
+Debug mode attaches a unique [name][CoroutineName] to every launched coroutine.
+Coroutine name can be seen in a regular Java debugger,
+in a string representation of the coroutine or in the thread name executing named coroutine.
+Overhead of this feature is negligible and it can be safely turned on by default to simplify logging and diagnostic.
+
+## Stacktrace recovery
+
+Stacktrace recovery is another useful feature of debug mode. It is enabled by default in the debug mode,
+but can be separately disabled by setting `kotlinx.coroutines.stacktrace.recovery` system property to `false`.
+
+Stacktrace recovery tries to stitch asynchronous exception stacktrace with a stacktrace of the receiver by copying it, providing
+not only information where an exception was thrown, but also where it was asynchronously rethrown or caught.
+
+It is easy to demonstrate with actual stacktraces of the same program that awaits asynchronous operation in `main` function
+(runnable code is [here](../../kotlinx-coroutines-debug/test/RecoveryExample.kt)):
+
+| Without recovery | With recovery |
+| - | - |
+|  |  |
+
+The only downside of this approach is losing referential transparency of the exception.
+
+### Stacktrace recovery machinery
+
+This section explains the inner mechanism of stacktrace recovery and can be skipped.
+
+When an exception is rethrown between coroutines (e.g. through `withContext` or `Deferred.await` boundary), stacktrace recovery
+machinery tries to create a copy of the original exception (with the original exception as the cause), then rewrite stacktrace
+of the copy with coroutine-related stack frames (using [Throwable.setStackTrace](https://docs.oracle.com/javase/9/docs/api/java/lang/Throwable.html#setStackTrace-java.lang.StackTraceElement:A-))
+and then throws the resulting exception instead of the original one.
+
+Exception copy logic is straightforward:
+ 1) If the exception class implements [CopyableThrowable], [CopyableThrowable.createCopy] is used.
+ `null` can be returned from `createCopy` to opt-out specific exception from being recovered.
+ 2) If the exception class has class-specific fields not inherited from Throwable, the exception is not copied.
+ 3) Otherwise, one of the public exception's constructor is invoked reflectively with an optional `initCause` call.
+
+## Debug agent
+
+[kotlinx-coroutines-debug](../../kotlinx-coroutines-debug) module provides one of the most powerful debug capabilities in `kotlinx.coroutines`.
+
+This is a separate module with a JVM agent that keeps track of all alive coroutines, introspects and dumps them similar to thread dump command,
+additionally enhancing stacktraces with information where coroutine was created.
+
+The full tutorial of how to use debug agent can be found in the corresponding [readme](../../kotlinx-coroutines-debug/README.md).
+
+### Debug agent and Android
+
+Unfortunately, Android runtime does not support Instrument API necessary for `kotlinx-coroutines-debug` to function, triggering `java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;`.
+
+Nevertheless, it will be possible to support debug agent on Android as soon as [GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj) will support android-gradle 3.3
+
+<!---
+Make an exception googlable
+java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;
+ at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm$ForLegacyVm.resolve(ByteBuddyAgent.java:1055)
+ at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm.resolve(ByteBuddyAgent.java:1038)
+ at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:374)
+ at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:342)
+ at kotlinx.coroutines.repackaged.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:328)
+ at kotlinx.coroutines.debug.internal.DebugProbesImpl.install(DebugProbesImpl.kt:39)
+ at kotlinx.coroutines.debug.DebugProbes.install(DebugProbes.kt:49)
+-->
+
+## Android optimization
+
+In optimized (release) builds with R8 version 1.6.0 or later both
+[Debugging mode](../../docs/debugging.md#debug-mode) and
+[Stacktrace recovery](../../docs/debugging.md#stacktrace-recovery)
+are permanently turned off.
+For more details see ["Optimization" section for Android](../../ui/kotlinx-coroutines-android/README.md#optimization).
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[DEBUG_PROPERTY_NAME]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-d-e-b-u-g_-p-r-o-p-e-r-t-y_-n-a-m-e.html
+[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html
+[CopyableThrowable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-copyable-throwable/index.html
+[CopyableThrowable.createCopy]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-copyable-throwable/create-copy.html
+
+<!--- MODULE kotlinx-coroutines-debug -->
+<!--- END -->
diff --git a/docs/topics/exception-handling.md b/docs/topics/exception-handling.md
new file mode 100644
index 0000000..fbd1131
--- /dev/null
+++ b/docs/topics/exception-handling.md
@@ -0,0 +1,513 @@
+<!--- TEST_NAME ExceptionsGuideTest -->
+
+[//]: # (title: Coroutine exceptions handling)
+
+This section covers exception handling and cancellation on exceptions.
+We already know that a cancelled coroutine throws [CancellationException] in suspension points and that it
+is ignored by the coroutines' machinery. Here we look at what happens if an exception is thrown during cancellation or multiple children of the same
+coroutine throw an exception.
+
+## Exception propagation
+
+Coroutine builders come in two flavors: propagating exceptions automatically ([launch] and [actor]) or
+exposing them to users ([async] and [produce]).
+When these builders are used to create a _root_ coroutine, that is not a _child_ of another coroutine,
+the former builders treat exceptions as **uncaught** exceptions, similar to Java's `Thread.uncaughtExceptionHandler`,
+while the latter are relying on the user to consume the final
+exception, for example via [await][Deferred.await] or [receive][ReceiveChannel.receive]
+([produce] and [receive][ReceiveChannel.receive] are covered later in [Channels](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/channels.md) section).
+
+It can be demonstrated by a simple example that creates root coroutines using the [GlobalScope]:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ val job = GlobalScope.launch { // root coroutine with launch
+ println("Throwing exception from launch")
+ throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
+ }
+ job.join()
+ println("Joined failed job")
+ val deferred = GlobalScope.async { // root coroutine with async
+ println("Throwing exception from async")
+ throw ArithmeticException() // Nothing is printed, relying on user to call await
+ }
+ try {
+ deferred.await()
+ println("Unreached")
+ } catch (e: ArithmeticException) {
+ println("Caught ArithmeticException")
+ }
+}
+```
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt).
+>
+{type="note"}
+
+The output of this code is (with [debug](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/coroutine-context-and-dispatchers.md#debugging-coroutines-and-threads)):
+
+```text
+Throwing exception from launch
+Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
+Joined failed job
+Throwing exception from async
+Caught ArithmeticException
+```
+
+<!--- TEST EXCEPTION-->
+
+## CoroutineExceptionHandler
+
+It is possible to customize the default behavior of printing **uncaught** exceptions to the console.
+[CoroutineExceptionHandler] context element on a _root_ coroutine can be used as generic `catch` block for
+this root coroutine and all its children where custom exception handling may take place.
+It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
+You cannot recover from the exception in the `CoroutineExceptionHandler`. The coroutine had already completed
+with the corresponding exception when the handler is called. Normally, the handler is used to
+log the exception, show some kind of error message, terminate, and/or restart the application.
+
+On JVM it is possible to redefine global exception handler for all coroutines by registering [CoroutineExceptionHandler] via
+[`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
+Global exception handler is similar to
+[`Thread.defaultUncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler))
+which is used when no more specific handlers are registered.
+On Android, `uncaughtExceptionPreHandler` is installed as a global coroutine exception handler.
+
+`CoroutineExceptionHandler` is invoked only on **uncaught** exceptions — exceptions that were not handled in any other way.
+In particular, all _children_ coroutines (coroutines created in the context of another [Job]) delegate handling of
+their exceptions to their parent coroutine, which also delegates to the parent, and so on until the root,
+so the `CoroutineExceptionHandler` installed in their context is never used.
+In addition to that, [async] builder always catches all exceptions and represents them in the resulting [Deferred] object,
+so its `CoroutineExceptionHandler` has no effect either.
+
+> Coroutines running in supervision scope do not propagate exceptions to their parent and are
+> excluded from this rule. A further [Supervision](#supervision) section of this document gives more details.
+>
+{type="note"}
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val handler = CoroutineExceptionHandler { _, exception ->
+ println("CoroutineExceptionHandler got $exception")
+ }
+ val job = GlobalScope.launch(handler) { // root coroutine, running in GlobalScope
+ throw AssertionError()
+ }
+ val deferred = GlobalScope.async(handler) { // also root, but async instead of launch
+ throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
+ }
+ joinAll(job, deferred)
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+CoroutineExceptionHandler got java.lang.AssertionError
+```
+
+<!--- TEST-->
+
+## Cancellation and exceptions
+
+Cancellation is closely related to exceptions. Coroutines internally use `CancellationException` for cancellation, these
+exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can
+be obtained by `catch` block.
+When a coroutine is cancelled using [Job.cancel], it terminates, but it does not cancel its parent.
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val job = launch {
+ val child = launch {
+ try {
+ delay(Long.MAX_VALUE)
+ } finally {
+ println("Child is cancelled")
+ }
+ }
+ yield()
+ println("Cancelling child")
+ child.cancel()
+ child.join()
+ yield()
+ println("Parent is not cancelled")
+ }
+ job.join()
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+Cancelling child
+Child is cancelled
+Parent is not cancelled
+```
+
+<!--- TEST-->
+
+If a coroutine encounters an exception other than `CancellationException`, it cancels its parent with that exception.
+This behaviour cannot be overridden and is used to provide stable coroutines hierarchies for
+[structured concurrency](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/composing-suspending-functions.md#structured-concurrency-with-async).
+[CoroutineExceptionHandler] implementation is not used for child coroutines.
+
+> In these examples, [CoroutineExceptionHandler] is always installed to a coroutine
+> that is created in [GlobalScope]. It does not make sense to install an exception handler to a coroutine that
+> is launched in the scope of the main [runBlocking], since the main coroutine is going to be always cancelled
+> when its child completes with exception despite the installed handler.
+>
+{type="note"}
+
+The original exception is handled by the parent only when all its children terminate,
+which is demonstrated by the following example.
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+//sampleStart
+ val handler = CoroutineExceptionHandler { _, exception ->
+ println("CoroutineExceptionHandler got $exception")
+ }
+ val job = GlobalScope.launch(handler) {
+ launch { // the first child
+ try {
+ delay(Long.MAX_VALUE)
+ } finally {
+ withContext(NonCancellable) {
+ println("Children are cancelled, but exception is not handled until all children terminate")
+ delay(100)
+ println("The first child finished its non cancellable block")
+ }
+ }
+ }
+ launch { // the second child
+ delay(10)
+ println("Second child throws an exception")
+ throw ArithmeticException()
+ }
+ }
+ job.join()
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+Second child throws an exception
+Children are cancelled, but exception is not handled until all children terminate
+The first child finished its non cancellable block
+CoroutineExceptionHandler got java.lang.ArithmeticException
+```
+
+<!--- TEST-->
+
+## Exceptions aggregation
+
+When multiple children of a coroutine fail with an exception, the
+general rule is "the first exception wins", so the first exception gets handled.
+All additional exceptions that happen after the first one are attached to the first exception as suppressed ones.
+
+<!--- INCLUDE
+import kotlinx.coroutines.exceptions.*
+-->
+
+```kotlin
+import kotlinx.coroutines.*
+import java.io.*
+
+fun main() = runBlocking {
+ val handler = CoroutineExceptionHandler { _, exception ->
+ println("CoroutineExceptionHandler got $exception with suppressed ${exception.suppressed.contentToString()}")
+ }
+ val job = GlobalScope.launch(handler) {
+ launch {
+ try {
+ delay(Long.MAX_VALUE) // it gets cancelled when another sibling fails with IOException
+ } finally {
+ throw ArithmeticException() // the second exception
+ }
+ }
+ launch {
+ delay(100)
+ throw IOException() // the first exception
+ }
+ delay(Long.MAX_VALUE)
+ }
+ job.join()
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt).
+>
+{type="note"}
+
+> Note: This above code will work properly only on JDK7+ that supports `suppressed` exceptions
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+CoroutineExceptionHandler got java.io.IOException with suppressed [java.lang.ArithmeticException]
+```
+
+<!--- TEST-->
+
+> Note that this mechanism currently only works on Java version 1.7+.
+> The JS and Native restrictions are temporary and will be lifted in the future.
+>
+{type="note"}
+
+Cancellation exceptions are transparent and are unwrapped by default:
+
+```kotlin
+import kotlinx.coroutines.*
+import java.io.*
+
+fun main() = runBlocking {
+//sampleStart
+ val handler = CoroutineExceptionHandler { _, exception ->
+ println("CoroutineExceptionHandler got $exception")
+ }
+ val job = GlobalScope.launch(handler) {
+ val inner = launch { // all this stack of coroutines will get cancelled
+ launch {
+ launch {
+ throw IOException() // the original exception
+ }
+ }
+ }
+ try {
+ inner.join()
+ } catch (e: CancellationException) {
+ println("Rethrowing CancellationException with original cause")
+ throw e // cancellation exception is rethrown, yet the original IOException gets to the handler
+ }
+ }
+ job.join()
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+Rethrowing CancellationException with original cause
+CoroutineExceptionHandler got java.io.IOException
+```
+
+<!--- TEST-->
+
+## Supervision
+
+As we have studied before, cancellation is a bidirectional relationship propagating through the whole
+hierarchy of coroutines. Let us take a look at the case when unidirectional cancellation is required.
+
+A good example of such a requirement is a UI component with the job defined in its scope. If any of the UI's child tasks
+have failed, it is not always necessary to cancel (effectively kill) the whole UI component,
+but if UI component is destroyed (and its job is cancelled), then it is necessary to fail all child jobs as their results are no longer needed.
+
+Another example is a server process that spawns multiple child jobs and needs to _supervise_
+their execution, tracking their failures and only restarting the failed ones.
+
+### Supervision job
+
+The [SupervisorJob][SupervisorJob()] can be used for these purposes.
+It is similar to a regular [Job][Job()] with the only exception that cancellation is propagated
+only downwards. This can easily be demonstrated using the following example:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ val supervisor = SupervisorJob()
+ with(CoroutineScope(coroutineContext + supervisor)) {
+ // launch the first child -- its exception is ignored for this example (don't do this in practice!)
+ val firstChild = launch(CoroutineExceptionHandler { _, _ -> }) {
+ println("The first child is failing")
+ throw AssertionError("The first child is cancelled")
+ }
+ // launch the second child
+ val secondChild = launch {
+ firstChild.join()
+ // Cancellation of the first child is not propagated to the second child
+ println("The first child is cancelled: ${firstChild.isCancelled}, but the second one is still active")
+ try {
+ delay(Long.MAX_VALUE)
+ } finally {
+ // But cancellation of the supervisor is propagated
+ println("The second child is cancelled because the supervisor was cancelled")
+ }
+ }
+ // wait until the first child fails & completes
+ firstChild.join()
+ println("Cancelling the supervisor")
+ supervisor.cancel()
+ secondChild.join()
+ }
+}
+```
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+The first child is failing
+The first child is cancelled: true, but the second one is still active
+Cancelling the supervisor
+The second child is cancelled because the supervisor was cancelled
+```
+
+<!--- TEST-->
+
+### Supervision scope
+
+Instead of [coroutineScope][_coroutineScope], we can use [supervisorScope][_supervisorScope] for _scoped_ concurrency. It propagates the cancellation
+in one direction only and cancels all its children only if it failed itself. It also waits for all children before completion
+just like [coroutineScope][_coroutineScope] does.
+
+```kotlin
+import kotlin.coroutines.*
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ try {
+ supervisorScope {
+ val child = launch {
+ try {
+ println("The child is sleeping")
+ delay(Long.MAX_VALUE)
+ } finally {
+ println("The child is cancelled")
+ }
+ }
+ // Give our child a chance to execute and print using yield
+ yield()
+ println("Throwing an exception from the scope")
+ throw AssertionError()
+ }
+ } catch(e: AssertionError) {
+ println("Caught an assertion error")
+ }
+}
+```
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+The child is sleeping
+Throwing an exception from the scope
+The child is cancelled
+Caught an assertion error
+```
+
+<!--- TEST-->
+
+#### Exceptions in supervised coroutines
+
+Another crucial difference between regular and supervisor jobs is exception handling.
+Every child should handle its exceptions by itself via the exception handling mechanism.
+This difference comes from the fact that child's failure does not propagate to the parent.
+It means that coroutines launched directly inside the [supervisorScope][_supervisorScope] _do_ use the [CoroutineExceptionHandler]
+that is installed in their scope in the same way as root coroutines do
+(see the [CoroutineExceptionHandler](#coroutineexceptionhandler) section for details).
+
+```kotlin
+import kotlin.coroutines.*
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ val handler = CoroutineExceptionHandler { _, exception ->
+ println("CoroutineExceptionHandler got $exception")
+ }
+ supervisorScope {
+ val child = launch(handler) {
+ println("The child throws an exception")
+ throw AssertionError()
+ }
+ println("The scope is completing")
+ }
+ println("The scope is completed")
+}
+```
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+The scope is completing
+The child throws an exception
+CoroutineExceptionHandler got java.lang.AssertionError
+The scope is completed
+```
+
+<!--- TEST-->
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
+[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
+[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
+[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html
+[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
+[CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/index.html
+[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html
+[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
+[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
+[SupervisorJob()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-supervisor-job.html
+[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job.html
+[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
+[_supervisorScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/supervisor-scope.html
+
+<!--- INDEX kotlinx.coroutines.channels -->
+
+[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
+[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
+[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
+
+<!--- END -->
\ No newline at end of file
diff --git a/docs/topics/flow.md b/docs/topics/flow.md
new file mode 100644
index 0000000..9dd84f3
--- /dev/null
+++ b/docs/topics/flow.md
@@ -0,0 +1,1896 @@
+<!--- TEST_NAME FlowGuideTest -->
+
+[//]: # (title: Asynchronous Flow)
+
+A suspending function asynchronously returns a single value, but how can we return
+multiple asynchronously computed values? This is where Kotlin Flows come in.
+
+## Representing multiple values
+
+Multiple values can be represented in Kotlin using [collections].
+For example, we can have a `simple` function that returns a [List]
+of three numbers and then print them all using [forEach]:
+
+```kotlin
+fun simple(): List<Int> = listOf(1, 2, 3)
+
+fun main() {
+ simple().forEach { value -> println(value) }
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt).
+>
+{type="note"}
+
+This code outputs:
+
+```text
+1
+2
+3
+```
+
+<!--- TEST -->
+
+### Sequences
+
+If we are computing the numbers with some CPU-consuming blocking code
+(each computation taking 100ms), then we can represent the numbers using a [Sequence]:
+
+```kotlin
+fun simple(): Sequence<Int> = sequence { // sequence builder
+ for (i in 1..3) {
+ Thread.sleep(100) // pretend we are computing it
+ yield(i) // yield next value
+ }
+}
+
+fun main() {
+ simple().forEach { value -> println(value) }
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt).
+>
+{type="note"}
+
+This code outputs the same numbers, but it waits 100ms before printing each one.
+
+<!--- TEST
+1
+2
+3
+-->
+
+### Suspending functions
+
+However, this computation blocks the main thread that is running the code.
+When these values are computed by asynchronous code we can mark the `simple` function with a `suspend` modifier,
+so that it can perform its work without blocking and return the result as a list:
+
+```kotlin
+import kotlinx.coroutines.*
+
+//sampleStart
+suspend fun simple(): List<Int> {
+ delay(1000) // pretend we are doing something asynchronous here
+ return listOf(1, 2, 3)
+}
+
+fun main() = runBlocking<Unit> {
+ simple().forEach { value -> println(value) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt).
+>
+{type="note"}
+
+This code prints the numbers after waiting for a second.
+
+<!--- TEST
+1
+2
+3
+-->
+
+### Flows
+
+Using the `List<Int>` result type, means we can only return all the values at once. To represent
+the stream of values that are being asynchronously computed, we can use a [`Flow<Int>`][Flow] type just like we would use the `Sequence<Int>` type for synchronously computed values:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow { // flow builder
+ for (i in 1..3) {
+ delay(100) // pretend we are doing something useful here
+ emit(i) // emit next value
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ // Launch a concurrent coroutine to check if the main thread is blocked
+ launch {
+ for (k in 1..3) {
+ println("I'm not blocked $k")
+ delay(100)
+ }
+ }
+ // Collect the flow
+ simple().collect { value -> println(value) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt).
+>
+{type="note"}
+
+This code waits 100ms before printing each number without blocking the main thread. This is verified
+by printing "I'm not blocked" every 100ms from a separate coroutine that is running in the main thread:
+
+```text
+I'm not blocked 1
+1
+I'm not blocked 2
+2
+I'm not blocked 3
+3
+```
+
+<!--- TEST -->
+
+Notice the following differences in the code with the [Flow] from the earlier examples:
+
+* A builder function for [Flow] type is called [flow][_flow].
+* Code inside the `flow { ... }` builder block can suspend.
+* The `simple` function is no longer marked with `suspend` modifier.
+* Values are _emitted_ from the flow using [emit][FlowCollector.emit] function.
+* Values are _collected_ from the flow using [collect][collect] function.
+
+> We can replace [delay] with `Thread.sleep` in the body of `foo`'s `flow { ... }` and see that the main
+> thread is blocked in this case.
+>
+{type="note"}
+
+## Flows are cold
+
+Flows are _cold_ streams similar to sequences — the code inside a [flow][_flow] builder does not
+run until the flow is collected. This becomes clear in the following example:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ println("Flow started")
+ for (i in 1..3) {
+ delay(100)
+ emit(i)
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ println("Calling simple function...")
+ val flow = simple()
+ println("Calling collect...")
+ flow.collect { value -> println(value) }
+ println("Calling collect again...")
+ flow.collect { value -> println(value) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt).
+>
+{type="note"}
+
+Which prints:
+
+```text
+Calling simple function...
+Calling collect...
+Flow started
+1
+2
+3
+Calling collect again...
+Flow started
+1
+2
+3
+```
+
+<!--- TEST -->
+
+This is a key reason the `simple` function (which returns a flow) is not marked with `suspend` modifier.
+By itself, `simple()` call returns quickly and does not wait for anything. The flow starts every time it is collected,
+that is why we see "Flow started" when we call `collect` again.
+
+## Flow cancellation basics
+
+Flow adheres to the general cooperative cancellation of coroutines. As usual, flow collection can be
+cancelled when the flow is suspended in a cancellable suspending function (like [delay]).
+The following example shows how the flow gets cancelled on a timeout when running in a [withTimeoutOrNull] block
+and stops executing its code:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ delay(100)
+ println("Emitting $i")
+ emit(i)
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ withTimeoutOrNull(250) { // Timeout after 250ms
+ simple().collect { value -> println(value) }
+ }
+ println("Done")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt).
+>
+{type="note"}
+
+Notice how only two numbers get emitted by the flow in the `simple` function, producing the following output:
+
+```text
+Emitting 1
+1
+Emitting 2
+2
+Done
+```
+
+<!--- TEST -->
+
+See [Flow cancellation checks](#flow-cancellation-checks) section for more details.
+
+## Flow builders
+
+The `flow { ... }` builder from the previous examples is the most basic one. There are other builders for
+easier declaration of flows:
+
+* [flowOf] builder that defines a flow emitting a fixed set of values.
+* Various collections and sequences can be converted to flows using `.asFlow()` extension functions.
+
+So, the example that prints the numbers from 1 to 3 from a flow can be written as:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ // Convert an integer range to a flow
+ (1..3).asFlow().collect { value -> println(value) }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt).
+>
+{type="note"}
+
+<!--- TEST
+1
+2
+3
+-->
+
+## Intermediate flow operators
+
+Flows can be transformed with operators, just as you would with collections and sequences.
+Intermediate operators are applied to an upstream flow and return a downstream flow.
+These operators are cold, just like flows are. A call to such an operator is not
+a suspending function itself. It works quickly, returning the definition of a new transformed flow.
+
+The basic operators have familiar names like [map] and [filter].
+The important difference to sequences is that blocks of
+code inside these operators can call suspending functions.
+
+For example, a flow of incoming requests can be
+mapped to the results with the [map] operator, even when performing a request is a long-running
+operation that is implemented by a suspending function:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+suspend fun performRequest(request: Int): String {
+ delay(1000) // imitate long-running asynchronous work
+ return "response $request"
+}
+
+fun main() = runBlocking<Unit> {
+ (1..3).asFlow() // a flow of requests
+ .map { request -> performRequest(request) }
+ .collect { response -> println(response) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt).
+>
+{type="note"}
+
+It produces the following three lines, each line appearing after each second:
+
+```text
+response 1
+response 2
+response 3
+```
+
+<!--- TEST -->
+
+### Transform operator
+
+Among the flow transformation operators, the most general one is called [transform]. It can be used to imitate
+simple transformations like [map] and [filter], as well as implement more complex transformations.
+Using the `transform` operator, we can [emit][FlowCollector.emit] arbitrary values an arbitrary number of times.
+
+For example, using `transform` we can emit a string before performing a long-running asynchronous request
+and follow it with a response:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+suspend fun performRequest(request: Int): String {
+ delay(1000) // imitate long-running asynchronous work
+ return "response $request"
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ (1..3).asFlow() // a flow of requests
+ .transform { request ->
+ emit("Making request $request")
+ emit(performRequest(request))
+ }
+ .collect { response -> println(response) }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt).
+>
+{type="note"}
+
+The output of this code is:
+
+```text
+Making request 1
+response 1
+Making request 2
+response 2
+Making request 3
+response 3
+```
+
+<!--- TEST -->
+
+### Size-limiting operators
+
+Size-limiting intermediate operators like [take] cancel the execution of the flow when the corresponding limit
+is reached. Cancellation in coroutines is always performed by throwing an exception, so that all the resource-management
+functions (like `try { ... } finally { ... }` blocks) operate normally in case of cancellation:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun numbers(): Flow<Int> = flow {
+ try {
+ emit(1)
+ emit(2)
+ println("This line will not execute")
+ emit(3)
+ } finally {
+ println("Finally in numbers")
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ numbers()
+ .take(2) // take only the first two
+ .collect { value -> println(value) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt).
+>
+{type="note"}
+
+The output of this code clearly shows that the execution of the `flow { ... }` body in the `numbers()` function
+stopped after emitting the second number:
+
+```text
+1
+2
+Finally in numbers
+```
+
+<!--- TEST -->
+
+## Terminal flow operators
+
+Terminal operators on flows are _suspending functions_ that start a collection of the flow.
+The [collect] operator is the most basic one, but there are other terminal operators, which can make it easier:
+
+* Conversion to various collections like [toList] and [toSet].
+* Operators to get the [first] value and to ensure that a flow emits a [single] value.
+* Reducing a flow to a value with [reduce] and [fold].
+
+For example:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val sum = (1..5).asFlow()
+ .map { it * it } // squares of numbers from 1 to 5
+ .reduce { a, b -> a + b } // sum them (terminal operator)
+ println(sum)
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt).
+>
+{type="note"}
+
+Prints a single number:
+
+```text
+55
+```
+
+<!--- TEST -->
+
+## Flows are sequential
+
+Each individual collection of a flow is performed sequentially unless special operators that operate
+on multiple flows are used. The collection works directly in the coroutine that calls a terminal operator.
+No new coroutines are launched by default.
+Each emitted value is processed by all the intermediate operators from
+upstream to downstream and is then delivered to the terminal operator after.
+
+See the following example that filters the even integers and maps them to strings:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ (1..5).asFlow()
+ .filter {
+ println("Filter $it")
+ it % 2 == 0
+ }
+ .map {
+ println("Map $it")
+ "string $it"
+ }.collect {
+ println("Collect $it")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt).
+>
+{type="note"}
+
+Producing:
+
+```text
+Filter 1
+Filter 2
+Map 2
+Collect string 2
+Filter 3
+Filter 4
+Map 4
+Collect string 4
+Filter 5
+```
+
+<!--- TEST -->
+
+## Flow context
+
+Collection of a flow always happens in the context of the calling coroutine. For example, if there is
+a `simple` flow, then the following code runs in the context specified
+by the author of this code, regardless of the implementation details of the `simple` flow:
+
+```kotlin
+withContext(context) {
+ simple().collect { value ->
+ println(value) // run in the specified context
+ }
+}
+```
+
+<!--- CLEAR -->
+
+This property of a flow is called _context preservation_.
+
+So, by default, code in the `flow { ... }` builder runs in the context that is provided by a collector
+of the corresponding flow. For example, consider the implementation of a `simple` function that prints the thread
+it is called on and emits three numbers:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ log("Started simple flow")
+ for (i in 1..3) {
+ emit(i)
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ simple().collect { value -> log("Collected $value") }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt).
+>
+{type="note"}
+
+Running this code produces:
+
+```text
+[main @coroutine#1] Started simple flow
+[main @coroutine#1] Collected 1
+[main @coroutine#1] Collected 2
+[main @coroutine#1] Collected 3
+```
+
+<!--- TEST FLEXIBLE_THREAD -->
+
+Since `simple().collect` is called from the main thread, the body of `simple`'s flow is also called in the main thread.
+This is the perfect default for fast-running or asynchronous code that does not care about the execution context and
+does not block the caller.
+
+### Wrong emission withContext
+
+However, the long-running CPU-consuming code might need to be executed in the context of [Dispatchers.Default] and UI-updating
+code might need to be executed in the context of [Dispatchers.Main]. Usually, [withContext] is used
+to change the context in the code using Kotlin coroutines, but code in the `flow { ... }` builder has to honor the context
+preservation property and is not allowed to [emit][FlowCollector.emit] from a different context.
+
+Try running the following code:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ // The WRONG way to change context for CPU-consuming code in flow builder
+ kotlinx.coroutines.withContext(Dispatchers.Default) {
+ for (i in 1..3) {
+ Thread.sleep(100) // pretend we are computing it in CPU-consuming way
+ emit(i) // emit next value
+ }
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ simple().collect { value -> println(value) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt).
+>
+{type="note"}
+
+This code produces the following exception:
+
+```text
+Exception in thread "main" java.lang.IllegalStateException: Flow invariant is violated:
+ Flow was collected in [CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@5511c7f8, BlockingEventLoop@2eac3323],
+ but emission happened in [CoroutineId(1), "coroutine#1":DispatchedCoroutine{Active}@2dae0000, Dispatchers.Default].
+ Please refer to 'flow' documentation or use 'flowOn' instead
+ at ...
+```
+
+<!--- TEST EXCEPTION -->
+
+### flowOn operator
+
+The exception refers to the [flowOn] function that shall be used to change the context of the flow emission.
+The correct way to change the context of a flow is shown in the example below, which also prints the
+names of the corresponding threads to show how it all works:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ Thread.sleep(100) // pretend we are computing it in CPU-consuming way
+ log("Emitting $i")
+ emit(i) // emit next value
+ }
+}.flowOn(Dispatchers.Default) // RIGHT way to change context for CPU-consuming code in flow builder
+
+fun main() = runBlocking<Unit> {
+ simple().collect { value ->
+ log("Collected $value")
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt).
+>
+{type="note"}
+
+Notice how `flow { ... }` works in the background thread, while collection happens in the main thread:
+
+<!--- TEST FLEXIBLE_THREAD
+[DefaultDispatcher-worker-1 @coroutine#2] Emitting 1
+[main @coroutine#1] Collected 1
+[DefaultDispatcher-worker-1 @coroutine#2] Emitting 2
+[main @coroutine#1] Collected 2
+[DefaultDispatcher-worker-1 @coroutine#2] Emitting 3
+[main @coroutine#1] Collected 3
+-->
+
+Another thing to observe here is that the [flowOn] operator has changed the default sequential nature of the flow.
+Now collection happens in one coroutine ("coroutine#1") and emission happens in another coroutine
+("coroutine#2") that is running in another thread concurrently with the collecting coroutine. The [flowOn] operator
+creates another coroutine for an upstream flow when it has to change the [CoroutineDispatcher] in its context.
+
+## Buffering
+
+Running different parts of a flow in different coroutines can be helpful from the standpoint of the overall time it takes
+to collect the flow, especially when long-running asynchronous operations are involved. For example, consider a case when
+the emission by a `simple` flow is slow, taking 100 ms to produce an element; and collector is also slow,
+taking 300 ms to process an element. Let's see how long it takes to collect such a flow with three numbers:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+import kotlin.system.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ delay(100) // pretend we are asynchronously waiting 100 ms
+ emit(i) // emit next value
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ val time = measureTimeMillis {
+ simple().collect { value ->
+ delay(300) // pretend we are processing it for 300 ms
+ println(value)
+ }
+ }
+ println("Collected in $time ms")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt).
+>
+{type="note"}
+
+It produces something like this, with the whole collection taking around 1200 ms (three numbers, 400 ms for each):
+
+```text
+1
+2
+3
+Collected in 1220 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+We can use a [buffer] operator on a flow to run emitting code of the `simple` flow concurrently with collecting code,
+as opposed to running them sequentially:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+import kotlin.system.*
+
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ delay(100) // pretend we are asynchronously waiting 100 ms
+ emit(i) // emit next value
+ }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ simple()
+ .buffer() // buffer emissions, don't wait
+ .collect { value ->
+ delay(300) // pretend we are processing it for 300 ms
+ println(value)
+ }
+ }
+ println("Collected in $time ms")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt).
+>
+{type="note"}
+
+It produces the same numbers just faster, as we have effectively created a processing pipeline,
+having to only wait 100 ms for the first number and then spending only 300 ms to process
+each number. This way it takes around 1000 ms to run:
+
+```text
+1
+2
+3
+Collected in 1071 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+> Note that the [flowOn] operator uses the same buffering mechanism when it has to change a [CoroutineDispatcher],
+> but here we explicitly request buffering without changing the execution context.
+>
+{type="note"}
+
+### Conflation
+
+When a flow represents partial results of the operation or operation status updates, it may not be necessary
+to process each value, but instead, only most recent ones. In this case, the [conflate] operator can be used to skip
+intermediate values when a collector is too slow to process them. Building on the previous example:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+import kotlin.system.*
+
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ delay(100) // pretend we are asynchronously waiting 100 ms
+ emit(i) // emit next value
+ }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ simple()
+ .conflate() // conflate emissions, don't process each one
+ .collect { value ->
+ delay(300) // pretend we are processing it for 300 ms
+ println(value)
+ }
+ }
+ println("Collected in $time ms")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt).
+>
+{type="note"}
+
+We see that while the first number was still being processed the second, and third were already produced, so
+the second one was _conflated_ and only the most recent (the third one) was delivered to the collector:
+
+```text
+1
+3
+Collected in 758 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+### Processing the latest value
+
+Conflation is one way to speed up processing when both the emitter and collector are slow. It does it by dropping emitted values.
+The other way is to cancel a slow collector and restart it every time a new value is emitted. There is
+a family of `xxxLatest` operators that perform the same essential logic of a `xxx` operator, but cancel the
+code in their block on a new value. Let's try changing [conflate] to [collectLatest] in the previous example:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+import kotlin.system.*
+
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ delay(100) // pretend we are asynchronously waiting 100 ms
+ emit(i) // emit next value
+ }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val time = measureTimeMillis {
+ simple()
+ .collectLatest { value -> // cancel & restart on the latest value
+ println("Collecting $value")
+ delay(300) // pretend we are processing it for 300 ms
+ println("Done $value")
+ }
+ }
+ println("Collected in $time ms")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt).
+>
+{type="note"}
+
+Since the body of [collectLatest] takes 300 ms, but new values are emitted every 100 ms, we see that the block
+is run on every value, but completes only for the last value:
+
+```text
+Collecting 1
+Collecting 2
+Collecting 3
+Done 3
+Collected in 741 ms
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+## Composing multiple flows
+
+There are lots of ways to compose multiple flows.
+
+### Zip
+
+Just like the [Sequence.zip] extension function in the Kotlin standard library,
+flows have a [zip] operator that combines the corresponding values of two flows:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val nums = (1..3).asFlow() // numbers 1..3
+ val strs = flowOf("one", "two", "three") // strings
+ nums.zip(strs) { a, b -> "$a -> $b" } // compose a single string
+ .collect { println(it) } // collect and print
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt).
+>
+{type="note"}
+
+This example prints:
+
+```text
+1 -> one
+2 -> two
+3 -> three
+```
+
+<!--- TEST -->
+
+### Combine
+
+When flow represents the most recent value of a variable or operation (see also the related
+section on [conflation](#conflation)), it might be needed to perform a computation that depends on
+the most recent values of the corresponding flows and to recompute it whenever any of the upstream
+flows emit a value. The corresponding family of operators is called [combine].
+
+For example, if the numbers in the previous example update every 300ms, but strings update every 400 ms,
+then zipping them using the [zip] operator will still produce the same result,
+albeit results that are printed every 400 ms:
+
+> We use a [onEach] intermediate operator in this example to delay each element and make the code
+> that emits sample flows more declarative and shorter.
+>
+{type="note"}
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val nums = (1..3).asFlow().onEach { delay(300) } // numbers 1..3 every 300 ms
+ val strs = flowOf("one", "two", "three").onEach { delay(400) } // strings every 400 ms
+ val startTime = System.currentTimeMillis() // remember the start time
+ nums.zip(strs) { a, b -> "$a -> $b" } // compose a single string with "zip"
+ .collect { value -> // collect and print
+ println("$value at ${System.currentTimeMillis() - startTime} ms from start")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+1 -> one at 437 ms from start
+2 -> two at 837 ms from start
+3 -> three at 1243 ms from start
+-->
+
+However, when using a [combine] operator here instead of a [zip]:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val nums = (1..3).asFlow().onEach { delay(300) } // numbers 1..3 every 300 ms
+ val strs = flowOf("one", "two", "three").onEach { delay(400) } // strings every 400 ms
+ val startTime = System.currentTimeMillis() // remember the start time
+ nums.combine(strs) { a, b -> "$a -> $b" } // compose a single string with "combine"
+ .collect { value -> // collect and print
+ println("$value at ${System.currentTimeMillis() - startTime} ms from start")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt).
+>
+{type="note"}
+
+We get quite a different output, where a line is printed at each emission from either `nums` or `strs` flows:
+
+```text
+1 -> one at 452 ms from start
+2 -> one at 651 ms from start
+2 -> two at 854 ms from start
+3 -> two at 952 ms from start
+3 -> three at 1256 ms from start
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+## Flattening flows
+
+Flows represent asynchronously received sequences of values, so it is quite easy to get in a situation where
+each value triggers a request for another sequence of values. For example, we can have the following
+function that returns a flow of two strings 500 ms apart:
+
+```kotlin
+fun requestFlow(i: Int): Flow<String> = flow {
+ emit("$i: First")
+ delay(500) // wait 500 ms
+ emit("$i: Second")
+}
+```
+
+<!--- CLEAR -->
+
+Now if we have a flow of three integers and call `requestFlow` for each of them like this:
+
+```kotlin
+(1..3).asFlow().map { requestFlow(it) }
+```
+
+<!--- CLEAR -->
+
+Then we end up with a flow of flows (`Flow<Flow<String>>`) that needs to be _flattened_ into a single flow for
+further processing. Collections and sequences have [flatten][Sequence.flatten] and [flatMap][Sequence.flatMap]
+operators for this. However, due to the asynchronous nature of flows they call for different _modes_ of flattening,
+as such, there is a family of flattening operators on flows.
+
+### flatMapConcat
+
+Concatenating mode is implemented by [flatMapConcat] and [flattenConcat] operators. They are the most direct
+analogues of the corresponding sequence operators. They wait for the inner flow to complete before
+starting to collect the next one as the following example shows:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun requestFlow(i: Int): Flow<String> = flow {
+ emit("$i: First")
+ delay(500) // wait 500 ms
+ emit("$i: Second")
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val startTime = System.currentTimeMillis() // remember the start time
+ (1..3).asFlow().onEach { delay(100) } // a number every 100 ms
+ .flatMapConcat { requestFlow(it) }
+ .collect { value -> // collect and print
+ println("$value at ${System.currentTimeMillis() - startTime} ms from start")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt).
+>
+{type="note"}
+
+The sequential nature of [flatMapConcat] is clearly seen in the output:
+
+```text
+1: First at 121 ms from start
+1: Second at 622 ms from start
+2: First at 727 ms from start
+2: Second at 1227 ms from start
+3: First at 1328 ms from start
+3: Second at 1829 ms from start
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+### flatMapMerge
+
+Another flattening mode is to concurrently collect all the incoming flows and merge their values into
+a single flow so that values are emitted as soon as possible.
+It is implemented by [flatMapMerge] and [flattenMerge] operators. They both accept an optional
+`concurrency` parameter that limits the number of concurrent flows that are collected at the same time
+(it is equal to [DEFAULT_CONCURRENCY] by default).
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun requestFlow(i: Int): Flow<String> = flow {
+ emit("$i: First")
+ delay(500) // wait 500 ms
+ emit("$i: Second")
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val startTime = System.currentTimeMillis() // remember the start time
+ (1..3).asFlow().onEach { delay(100) } // a number every 100 ms
+ .flatMapMerge { requestFlow(it) }
+ .collect { value -> // collect and print
+ println("$value at ${System.currentTimeMillis() - startTime} ms from start")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt).
+>
+{type="note"}
+
+The concurrent nature of [flatMapMerge] is obvious:
+
+```text
+1: First at 136 ms from start
+2: First at 231 ms from start
+3: First at 333 ms from start
+1: Second at 639 ms from start
+2: Second at 732 ms from start
+3: Second at 833 ms from start
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+> Note that the [flatMapMerge] calls its block of code (`{ requestFlow(it) }` in this example) sequentially, but
+> collects the resulting flows concurrently, it is the equivalent of performing a sequential
+> `map { requestFlow(it) }` first and then calling [flattenMerge] on the result.
+>
+{type="note"}
+
+### flatMapLatest
+
+In a similar way to the [collectLatest] operator, that was shown in
+["Processing the latest value"](#processing-the-latest-value) section, there is the corresponding "Latest"
+flattening mode where a collection of the previous flow is cancelled as soon as new flow is emitted.
+It is implemented by the [flatMapLatest] operator.
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun requestFlow(i: Int): Flow<String> = flow {
+ emit("$i: First")
+ delay(500) // wait 500 ms
+ emit("$i: Second")
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val startTime = System.currentTimeMillis() // remember the start time
+ (1..3).asFlow().onEach { delay(100) } // a number every 100 ms
+ .flatMapLatest { requestFlow(it) }
+ .collect { value -> // collect and print
+ println("$value at ${System.currentTimeMillis() - startTime} ms from start")
+ }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt).
+>
+{type="note"}
+
+The output here in this example is a good demonstration of how [flatMapLatest] works:
+
+```text
+1: First at 142 ms from start
+2: First at 322 ms from start
+3: First at 425 ms from start
+3: Second at 931 ms from start
+```
+
+<!--- TEST ARBITRARY_TIME -->
+
+> Note that [flatMapLatest] cancels all the code in its block (`{ requestFlow(it) }` in this example) on a new value.
+> It makes no difference in this particular example, because the call to `requestFlow` itself is fast, not-suspending,
+> and cannot be cancelled. However, it would show up if we were to use suspending functions like `delay` in there.
+>
+{type="note"}
+
+## Flow exceptions
+
+Flow collection can complete with an exception when an emitter or code inside the operators throw an exception.
+There are several ways to handle these exceptions.
+
+### Collector try and catch
+
+A collector can use Kotlin's [`try/catch`][exceptions] block to handle exceptions:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ println("Emitting $i")
+ emit(i) // emit next value
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ try {
+ simple().collect { value ->
+ println(value)
+ check(value <= 1) { "Collected $value" }
+ }
+ } catch (e: Throwable) {
+ println("Caught $e")
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt).
+>
+{type="note"}
+
+This code successfully catches an exception in [collect] terminal operator and,
+as we see, no more values are emitted after that:
+
+```text
+Emitting 1
+1
+Emitting 2
+2
+Caught java.lang.IllegalStateException: Collected 2
+```
+
+<!--- TEST -->
+
+### Everything is caught
+
+The previous example actually catches any exception happening in the emitter or in any intermediate or terminal operators.
+For example, let's change the code so that emitted values are [mapped][map] to strings,
+but the corresponding code produces an exception:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<String> =
+ flow {
+ for (i in 1..3) {
+ println("Emitting $i")
+ emit(i) // emit next value
+ }
+ }
+ .map { value ->
+ check(value <= 1) { "Crashed on $value" }
+ "string $value"
+ }
+
+fun main() = runBlocking<Unit> {
+ try {
+ simple().collect { value -> println(value) }
+ } catch (e: Throwable) {
+ println("Caught $e")
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt).
+>
+{type="note"}
+
+This exception is still caught and collection is stopped:
+
+```text
+Emitting 1
+string 1
+Emitting 2
+Caught java.lang.IllegalStateException: Crashed on 2
+```
+
+<!--- TEST -->
+
+## Exception transparency
+
+But how can code of the emitter encapsulate its exception handling behavior?
+
+Flows must be _transparent to exceptions_ and it is a violation of the exception transparency to [emit][FlowCollector.emit] values in the
+`flow { ... }` builder from inside of a `try/catch` block. This guarantees that a collector throwing an exception
+can always catch it using `try/catch` as in the previous example.
+
+The emitter can use a [catch] operator that preserves this exception transparency and allows encapsulation
+of its exception handling. The body of the `catch` operator can analyze an exception
+and react to it in different ways depending on which exception was caught:
+
+* Exceptions can be rethrown using `throw`.
+* Exceptions can be turned into emission of values using [emit][FlowCollector.emit] from the body of [catch].
+* Exceptions can be ignored, logged, or processed by some other code.
+
+For example, let us emit the text on catching an exception:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun simple(): Flow<String> =
+ flow {
+ for (i in 1..3) {
+ println("Emitting $i")
+ emit(i) // emit next value
+ }
+ }
+ .map { value ->
+ check(value <= 1) { "Crashed on $value" }
+ "string $value"
+ }
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ simple()
+ .catch { e -> emit("Caught $e") } // emit on exception
+ .collect { value -> println(value) }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt).
+>
+{type="note"}
+
+The output of the example is the same, even though we do not have `try/catch` around the code anymore.
+
+<!--- TEST
+Emitting 1
+string 1
+Emitting 2
+Caught java.lang.IllegalStateException: Crashed on 2
+-->
+
+### Transparent catch
+
+The [catch] intermediate operator, honoring exception transparency, catches only upstream exceptions
+(that is an exception from all the operators above `catch`, but not below it).
+If the block in `collect { ... }` (placed below `catch`) throws an exception then it escapes:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ println("Emitting $i")
+ emit(i)
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ simple()
+ .catch { e -> println("Caught $e") } // does not catch downstream exceptions
+ .collect { value ->
+ check(value <= 1) { "Collected $value" }
+ println(value)
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt).
+>
+{type="note"}
+
+A "Caught ..." message is not printed despite there being a `catch` operator:
+
+```text
+Emitting 1
+1
+Emitting 2
+Exception in thread "main" java.lang.IllegalStateException: Collected 2
+ at ...
+```
+
+<!--- TEST EXCEPTION -->
+
+### Catching declaratively
+
+We can combine the declarative nature of the [catch] operator with a desire to handle all the exceptions, by moving the body
+of the [collect] operator into [onEach] and putting it before the `catch` operator. Collection of this flow must
+be triggered by a call to `collect()` without parameters:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun simple(): Flow<Int> = flow {
+ for (i in 1..3) {
+ println("Emitting $i")
+ emit(i)
+ }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ simple()
+ .onEach { value ->
+ check(value <= 1) { "Collected $value" }
+ println(value)
+ }
+ .catch { e -> println("Caught $e") }
+ .collect()
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt).
+>
+{type="note"}
+
+Now we can see that a "Caught ..." message is printed and so we can catch all the exceptions without explicitly
+using a `try/catch` block:
+
+```text
+Emitting 1
+1
+Emitting 2
+Caught java.lang.IllegalStateException: Collected 2
+```
+
+<!--- TEST EXCEPTION -->
+
+## Flow completion
+
+When flow collection completes (normally or exceptionally) it may need to execute an action.
+As you may have already noticed, it can be done in two ways: imperative or declarative.
+
+### Imperative finally block
+
+In addition to `try`/`catch`, a collector can also use a `finally` block to execute an action
+upon `collect` completion.
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = (1..3).asFlow()
+
+fun main() = runBlocking<Unit> {
+ try {
+ simple().collect { value -> println(value) }
+ } finally {
+ println("Done")
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt).
+>
+{type="note"}
+
+This code prints three numbers produced by the `simple` flow followed by a "Done" string:
+
+```text
+1
+2
+3
+Done
+```
+
+<!--- TEST -->
+
+### Declarative handling
+
+For the declarative approach, flow has [onCompletion] intermediate operator that is invoked
+when the flow has completely collected.
+
+The previous example can be rewritten using an [onCompletion] operator and produces the same output:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+fun simple(): Flow<Int> = (1..3).asFlow()
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ simple()
+ .onCompletion { println("Done") }
+ .collect { value -> println(value) }
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt).
+>
+{type="note"}
+
+<!--- TEST
+1
+2
+3
+Done
+-->
+
+The key advantage of [onCompletion] is a nullable `Throwable` parameter of the lambda that can be used
+to determine whether the flow collection was completed normally or exceptionally. In the following
+example the `simple` flow throws an exception after emitting the number 1:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = flow {
+ emit(1)
+ throw RuntimeException()
+}
+
+fun main() = runBlocking<Unit> {
+ simple()
+ .onCompletion { cause -> if (cause != null) println("Flow completed exceptionally") }
+ .catch { cause -> println("Caught exception") }
+ .collect { value -> println(value) }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt).
+>
+{type="note"}
+
+As you may expect, it prints:
+
+```text
+1
+Flow completed exceptionally
+Caught exception
+```
+
+<!--- TEST -->
+
+The [onCompletion] operator, unlike [catch], does not handle the exception. As we can see from the above
+example code, the exception still flows downstream. It will be delivered to further `onCompletion` operators
+and can be handled with a `catch` operator.
+
+### Successful completion
+
+Another difference with [catch] operator is that [onCompletion] sees all exceptions and receives
+a `null` exception only on successful completion of the upstream flow (without cancellation or failure).
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun simple(): Flow<Int> = (1..3).asFlow()
+
+fun main() = runBlocking<Unit> {
+ simple()
+ .onCompletion { cause -> println("Flow completed with $cause") }
+ .collect { value ->
+ check(value <= 1) { "Collected $value" }
+ println(value)
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt).
+>
+{type="note"}
+
+We can see the completion cause is not null, because the flow was aborted due to downstream exception:
+
+```text
+1
+Flow completed with java.lang.IllegalStateException: Collected 2
+Exception in thread "main" java.lang.IllegalStateException: Collected 2
+```
+
+<!--- TEST EXCEPTION -->
+
+## Imperative versus declarative
+
+Now we know how to collect flow, and handle its completion and exceptions in both imperative and declarative ways.
+The natural question here is, which approach is preferred and why?
+As a library, we do not advocate for any particular approach and believe that both options
+are valid and should be selected according to your own preferences and code style.
+
+## Launching flow
+
+It is easy to use flows to represent asynchronous events that are coming from some source.
+In this case, we need an analogue of the `addEventListener` function that registers a piece of code with a reaction
+for incoming events and continues further work. The [onEach] operator can serve this role.
+However, `onEach` is an intermediate operator. We also need a terminal operator to collect the flow.
+Otherwise, just calling `onEach` has no effect.
+
+If we use the [collect] terminal operator after `onEach`, then the code after it will wait until the flow is collected:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+// Imitate a flow of events
+fun events(): Flow<Int> = (1..3).asFlow().onEach { delay(100) }
+
+fun main() = runBlocking<Unit> {
+ events()
+ .onEach { event -> println("Event: $event") }
+ .collect() // <--- Collecting the flow waits
+ println("Done")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt).
+>
+{type="note"}
+
+As you can see, it prints:
+
+```text
+Event: 1
+Event: 2
+Event: 3
+Done
+```
+
+<!--- TEST -->
+
+The [launchIn] terminal operator comes in handy here. By replacing `collect` with `launchIn` we can
+launch a collection of the flow in a separate coroutine, so that execution of further code
+immediately continues:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+// Imitate a flow of events
+fun events(): Flow<Int> = (1..3).asFlow().onEach { delay(100) }
+
+//sampleStart
+fun main() = runBlocking<Unit> {
+ events()
+ .onEach { event -> println("Event: $event") }
+ .launchIn(this) // <--- Launching the flow in a separate coroutine
+ println("Done")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt).
+>
+{type="note"}
+
+It prints:
+
+```text
+Done
+Event: 1
+Event: 2
+Event: 3
+```
+
+<!--- TEST -->
+
+The required parameter to `launchIn` must specify a [CoroutineScope] in which the coroutine to collect the flow is
+launched. In the above example this scope comes from the [runBlocking]
+coroutine builder, so while the flow is running, this [runBlocking] scope waits for completion of its child coroutine
+and keeps the main function from returning and terminating this example.
+
+In actual applications a scope will come from an entity with a limited
+lifetime. As soon as the lifetime of this entity is terminated the corresponding scope is cancelled, cancelling
+the collection of the corresponding flow. This way the pair of `onEach { ... }.launchIn(scope)` works
+like the `addEventListener`. However, there is no need for the corresponding `removeEventListener` function,
+as cancellation and structured concurrency serve this purpose.
+
+Note that [launchIn] also returns a [Job], which can be used to [cancel][Job.cancel] the corresponding flow collection
+coroutine only without cancelling the whole scope or to [join][Job.join] it.
+
+### Flow cancellation checks
+
+For convenience, the [flow][_flow] builder performs additional [ensureActive] checks for cancellation on each emitted value.
+It means that a busy loop emitting from a `flow { ... }` is cancellable:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun foo(): Flow<Int> = flow {
+ for (i in 1..5) {
+ println("Emitting $i")
+ emit(i)
+ }
+}
+
+fun main() = runBlocking<Unit> {
+ foo().collect { value ->
+ if (value == 3) cancel()
+ println(value)
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-37.kt).
+>
+{type="note"}
+
+We get only numbers up to 3 and a [CancellationException] after trying to emit number 4:
+
+```text
+Emitting 1
+1
+Emitting 2
+2
+Emitting 3
+3
+Emitting 4
+Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@6d7b4f4c
+```
+
+<!--- TEST EXCEPTION -->
+
+However, most other flow operators do not do additional cancellation checks on their own for performance reasons.
+For example, if you use [IntRange.asFlow] extension to write the same busy loop and don't suspend anywhere,
+then there are no checks for cancellation:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun main() = runBlocking<Unit> {
+ (1..5).asFlow().collect { value ->
+ if (value == 3) cancel()
+ println(value)
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-38.kt).
+>
+{type="note"}
+
+All numbers from 1 to 5 are collected and cancellation gets detected only before return from `runBlocking`:
+
+```text
+1
+2
+3
+4
+5
+Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@3327bd23
+```
+
+<!--- TEST EXCEPTION -->
+
+#### Making busy flow cancellable
+
+In the case where you have a busy loop with coroutines you must explicitly check for cancellation.
+You can add `.onEach { currentCoroutineContext().ensureActive() }`, but there is a ready-to-use
+[cancellable] operator provided to do that:
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+
+//sampleStart
+fun main() = runBlocking<Unit> {
+ (1..5).asFlow().cancellable().collect { value ->
+ if (value == 3) cancel()
+ println(value)
+ }
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code from [here](../../kotlinx-coroutines-core/jvm/test/guide/example-flow-39.kt).
+>
+{type="note"}
+
+With the `cancellable` operator only the numbers from 1 to 3 are collected:
+
+```text
+1
+2
+3
+Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@5ec0a365
+```
+
+<!--- TEST EXCEPTION -->
+
+## Flow and Reactive Streams
+
+For those who are familiar with [Reactive Streams](https://www.reactive-streams.org/) or reactive frameworks such as RxJava and project Reactor,
+design of the Flow may look very familiar.
+
+Indeed, its design was inspired by Reactive Streams and its various implementations. But Flow main goal is to have as simple design as possible,
+be Kotlin and suspension friendly and respect structured concurrency. Achieving this goal would be impossible without reactive pioneers and their tremendous work. You can read the complete story in [Reactive Streams and Kotlin Flows](https://medium.com/@elizarov/reactive-streams-and-kotlin-flows-bfd12772cda4) article.
+
+While being different, conceptually, Flow *is* a reactive stream and it is possible to convert it to the reactive (spec and TCK compliant) Publisher and vice versa.
+Such converters are provided by `kotlinx.coroutines` out-of-the-box and can be found in corresponding reactive modules (`kotlinx-coroutines-reactive` for Reactive Streams, `kotlinx-coroutines-reactor` for Project Reactor and `kotlinx-coroutines-rx2`/`kotlinx-coroutines-rx3` for RxJava2/RxJava3).
+Integration modules include conversions from and to `Flow`, integration with Reactor's `Context` and suspension-friendly ways to work with various reactive entities.
+
+<!-- stdlib references -->
+
+[collections]: https://kotlinlang.org/docs/reference/collections-overview.html
+[List]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html
+[forEach]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/for-each.html
+[Sequence]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/index.html
+[Sequence.zip]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/zip.html
+[Sequence.flatten]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/flatten.html
+[Sequence.flatMap]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/flat-map.html
+[exceptions]: https://kotlinlang.org/docs/reference/exceptions.html
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
+[withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-timeout-or-null.html
+[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
+[Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html
+[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
+[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html
+[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
+[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
+[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/cancel.html
+[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
+[ensureActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/ensure-active.html
+[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html
+
+<!--- INDEX kotlinx.coroutines.flow -->
+
+[Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html
+[_flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow.html
+[FlowCollector.emit]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow-collector/emit.html
+[collect]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect.html
+[flowOf]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow-of.html
+[map]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/map.html
+[filter]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/filter.html
+[transform]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/transform.html
+[take]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/take.html
+[toList]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-list.html
+[toSet]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-set.html
+[first]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/first.html
+[single]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/single.html
+[reduce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/reduce.html
+[fold]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/fold.html
+[flowOn]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow-on.html
+[buffer]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/buffer.html
+[conflate]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/conflate.html
+[collectLatest]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect-latest.html
+[zip]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/zip.html
+[combine]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/combine.html
+[onEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/on-each.html
+[flatMapConcat]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flat-map-concat.html
+[flattenConcat]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flatten-concat.html
+[flatMapMerge]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flat-map-merge.html
+[flattenMerge]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flatten-merge.html
+[DEFAULT_CONCURRENCY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-d-e-f-a-u-l-t_-c-o-n-c-u-r-r-e-n-c-y.html
+[flatMapLatest]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flat-map-latest.html
+[catch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/catch.html
+[onCompletion]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/on-completion.html
+[launchIn]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/launch-in.html
+[IntRange.asFlow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/kotlin.ranges.-int-range/as-flow.html
+[cancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/cancellable.html
+
+<!--- END -->
diff --git a/docs/knit.properties b/docs/topics/knit.properties
similarity index 62%
rename from docs/knit.properties
rename to docs/topics/knit.properties
index 2028ecb..7db4da6 100644
--- a/docs/knit.properties
+++ b/docs/topics/knit.properties
@@ -3,8 +3,8 @@
#
knit.package=kotlinx.coroutines.guide
-knit.dir=../kotlinx-coroutines-core/jvm/test/guide/
+knit.dir=../../kotlinx-coroutines-core/jvm/test/guide/
test.package=kotlinx.coroutines.guide.test
-test.dir=../kotlinx-coroutines-core/jvm/test/guide/test/
+test.dir=../../kotlinx-coroutines-core/jvm/test/guide/test/
diff --git a/docs/topics/select-expression.md b/docs/topics/select-expression.md
new file mode 100644
index 0000000..082a50d
--- /dev/null
+++ b/docs/topics/select-expression.md
@@ -0,0 +1,502 @@
+<!--- TEST_NAME SelectGuideTest -->
+
+[//]: # (title: Select expression \(experimental\))
+
+Select expression makes it possible to await multiple suspending functions simultaneously and _select_
+the first one that becomes available.
+
+> Select expressions are an experimental feature of `kotlinx.coroutines`. Their API is expected to
+> evolve in the upcoming updates of the `kotlinx.coroutines` library with potentially
+> breaking changes.
+>
+{type="note"}
+
+## Selecting from channels
+
+Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
+
+```kotlin
+fun CoroutineScope.fizz() = produce<String> {
+ while (true) { // sends "Fizz" every 300 ms
+ delay(300)
+ send("Fizz")
+ }
+}
+```
+
+And the `buzz` produces "Buzz!" string every 500 ms:
+
+```kotlin
+fun CoroutineScope.buzz() = produce<String> {
+ while (true) { // sends "Buzz!" every 500 ms
+ delay(500)
+ send("Buzz!")
+ }
+}
+```
+
+Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
+other. But [select] expression allows us to receive from _both_ simultaneously using its
+[onReceive][ReceiveChannel.onReceive] clauses:
+
+```kotlin
+suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
+ select<Unit> { // <Unit> means that this select expression does not produce any result
+ fizz.onReceive { value -> // this is the first select clause
+ println("fizz -> '$value'")
+ }
+ buzz.onReceive { value -> // this is the second select clause
+ println("buzz -> '$value'")
+ }
+ }
+}
+```
+
+Let us run it all seven times:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.selects.*
+
+fun CoroutineScope.fizz() = produce<String> {
+ while (true) { // sends "Fizz" every 300 ms
+ delay(300)
+ send("Fizz")
+ }
+}
+
+fun CoroutineScope.buzz() = produce<String> {
+ while (true) { // sends "Buzz!" every 500 ms
+ delay(500)
+ send("Buzz!")
+ }
+}
+
+suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
+ select<Unit> { // <Unit> means that this select expression does not produce any result
+ fizz.onReceive { value -> // this is the first select clause
+ println("fizz -> '$value'")
+ }
+ buzz.onReceive { value -> // this is the second select clause
+ println("buzz -> '$value'")
+ }
+ }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val fizz = fizz()
+ val buzz = buzz()
+ repeat(7) {
+ selectFizzBuzz(fizz, buzz)
+ }
+ coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt).
+>
+{type="note"}
+
+The result of this code is:
+
+```text
+fizz -> 'Fizz'
+buzz -> 'Buzz!'
+fizz -> 'Fizz'
+fizz -> 'Fizz'
+buzz -> 'Buzz!'
+fizz -> 'Fizz'
+buzz -> 'Buzz!'
+```
+
+<!--- TEST -->
+
+## Selecting on close
+
+The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
+`select` to throw an exception. We can use [onReceiveOrNull][onReceiveOrNull] clause to perform a
+specific action when the channel is closed. The following example also shows that `select` is an expression that returns
+the result of its selected clause:
+
+```kotlin
+suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
+ select<String> {
+ a.onReceiveOrNull { value ->
+ if (value == null)
+ "Channel 'a' is closed"
+ else
+ "a -> '$value'"
+ }
+ b.onReceiveOrNull { value ->
+ if (value == null)
+ "Channel 'b' is closed"
+ else
+ "b -> '$value'"
+ }
+ }
+```
+
+Note that [onReceiveOrNull][onReceiveOrNull] is an extension function defined only
+for channels with non-nullable elements so that there is no accidental confusion between a closed channel
+and a null value.
+
+Let's use it with channel `a` that produces "Hello" string four times and
+channel `b` that produces "World" four times:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.selects.*
+
+suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
+ select<String> {
+ a.onReceiveOrNull { value ->
+ if (value == null)
+ "Channel 'a' is closed"
+ else
+ "a -> '$value'"
+ }
+ b.onReceiveOrNull { value ->
+ if (value == null)
+ "Channel 'b' is closed"
+ else
+ "b -> '$value'"
+ }
+ }
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val a = produce<String> {
+ repeat(4) { send("Hello $it") }
+ }
+ val b = produce<String> {
+ repeat(4) { send("World $it") }
+ }
+ repeat(8) { // print first eight results
+ println(selectAorB(a, b))
+ }
+ coroutineContext.cancelChildren()
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt).
+>
+{type="note"}
+
+The result of this code is quite interesting, so we'll analyze it in more detail:
+
+```text
+a -> 'Hello 0'
+a -> 'Hello 1'
+b -> 'World 0'
+a -> 'Hello 2'
+a -> 'Hello 3'
+b -> 'World 1'
+Channel 'a' is closed
+Channel 'a' is closed
+```
+
+<!--- TEST -->
+
+There are couple of observations to make out of it.
+
+First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
+the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
+being the first clause in select, wins. However, because we are using unbuffered channel, the `a` gets suspended from
+time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
+
+The second observation, is that [onReceiveOrNull][onReceiveOrNull] gets immediately selected when the
+channel is already closed.
+
+## Selecting to send
+
+Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
+with a biased nature of selection.
+
+Let us write an example of producer of integers that sends its values to a `side` channel when
+the consumers on its primary channel cannot keep up with it:
+
+```kotlin
+fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
+ for (num in 1..10) { // produce 10 numbers from 1 to 10
+ delay(100) // every 100 ms
+ select<Unit> {
+ onSend(num) {} // Send to the primary channel
+ side.onSend(num) {} // or to the side channel
+ }
+ }
+}
+```
+
+Consumer is going to be quite slow, taking 250 ms to process each number:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.selects.*
+
+fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
+ for (num in 1..10) { // produce 10 numbers from 1 to 10
+ delay(100) // every 100 ms
+ select<Unit> {
+ onSend(num) {} // Send to the primary channel
+ side.onSend(num) {} // or to the side channel
+ }
+ }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val side = Channel<Int>() // allocate side channel
+ launch { // this is a very fast consumer for the side channel
+ side.consumeEach { println("Side channel has $it") }
+ }
+ produceNumbers(side).consumeEach {
+ println("Consuming $it")
+ delay(250) // let us digest the consumed number properly, do not hurry
+ }
+ println("Done consuming")
+ coroutineContext.cancelChildren()
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt).
+>
+{type="note"}
+
+So let us see what happens:
+
+```text
+Consuming 1
+Side channel has 2
+Side channel has 3
+Consuming 4
+Side channel has 5
+Side channel has 6
+Consuming 7
+Side channel has 8
+Side channel has 9
+Consuming 10
+Done consuming
+```
+
+<!--- TEST -->
+
+## Selecting deferred values
+
+Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
+Let us start with an async function that returns a deferred string value after
+a random delay:
+
+```kotlin
+fun CoroutineScope.asyncString(time: Int) = async {
+ delay(time.toLong())
+ "Waited for $time ms"
+}
+```
+
+Let us start a dozen of them with a random delay.
+
+```kotlin
+fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
+ val random = Random(3)
+ return List(12) { asyncString(random.nextInt(1000)) }
+}
+```
+
+Now the main function awaits for the first of them to complete and counts the number of deferred values
+that are still active. Note that we've used here the fact that `select` expression is a Kotlin DSL,
+so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
+of deferred values to provide `onAwait` clause for each deferred value.
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.selects.*
+import java.util.*
+
+fun CoroutineScope.asyncString(time: Int) = async {
+ delay(time.toLong())
+ "Waited for $time ms"
+}
+
+fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
+ val random = Random(3)
+ return List(12) { asyncString(random.nextInt(1000)) }
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val list = asyncStringsList()
+ val result = select<String> {
+ list.withIndex().forEach { (index, deferred) ->
+ deferred.onAwait { answer ->
+ "Deferred $index produced answer '$answer'"
+ }
+ }
+ }
+ println(result)
+ val countActive = list.count { it.isActive }
+ println("$countActive coroutines are still active")
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt).
+>
+{type="note"}
+
+The output is:
+
+```text
+Deferred 4 produced answer 'Waited for 128 ms'
+11 coroutines are still active
+```
+
+<!--- TEST -->
+
+## Switch over a channel of deferred values
+
+Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
+deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
+[onReceiveOrNull][onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
+
+```kotlin
+fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
+ var current = input.receive() // start with first received deferred value
+ while (isActive) { // loop while not cancelled/closed
+ val next = select<Deferred<String>?> { // return next deferred value from this select or null
+ input.onReceiveOrNull { update ->
+ update // replaces next value to wait
+ }
+ current.onAwait { value ->
+ send(value) // send value that current deferred has produced
+ input.receiveOrNull() // and use the next deferred from the input channel
+ }
+ }
+ if (next == null) {
+ println("Channel was closed")
+ break // out of loop
+ } else {
+ current = next
+ }
+ }
+}
+```
+
+To test it, we'll use a simple async function that resolves to a specified string after a specified time:
+
+```kotlin
+fun CoroutineScope.asyncString(str: String, time: Long) = async {
+ delay(time)
+ str
+}
+```
+
+The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
+data to it:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+import kotlinx.coroutines.selects.*
+
+fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
+ var current = input.receive() // start with first received deferred value
+ while (isActive) { // loop while not cancelled/closed
+ val next = select<Deferred<String>?> { // return next deferred value from this select or null
+ input.onReceiveOrNull { update ->
+ update // replaces next value to wait
+ }
+ current.onAwait { value ->
+ send(value) // send value that current deferred has produced
+ input.receiveOrNull() // and use the next deferred from the input channel
+ }
+ }
+ if (next == null) {
+ println("Channel was closed")
+ break // out of loop
+ } else {
+ current = next
+ }
+ }
+}
+
+fun CoroutineScope.asyncString(str: String, time: Long) = async {
+ delay(time)
+ str
+}
+
+fun main() = runBlocking<Unit> {
+//sampleStart
+ val chan = Channel<Deferred<String>>() // the channel for test
+ launch { // launch printing coroutine
+ for (s in switchMapDeferreds(chan))
+ println(s) // print each received string
+ }
+ chan.send(asyncString("BEGIN", 100))
+ delay(200) // enough time for "BEGIN" to be produced
+ chan.send(asyncString("Slow", 500))
+ delay(100) // not enough time to produce slow
+ chan.send(asyncString("Replace", 100))
+ delay(500) // give it time before the last one
+ chan.send(asyncString("END", 500))
+ delay(1000) // give it time to process
+ chan.close() // close the channel ...
+ delay(500) // and wait some time to let it finish
+//sampleEnd
+}
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt).
+>
+{type="note"}
+
+The result of this code:
+
+```text
+BEGIN
+Replace
+END
+Channel was closed
+```
+
+<!--- TEST -->
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[Deferred.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/on-await.html
+
+<!--- INDEX kotlinx.coroutines.channels -->
+
+[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
+[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/on-receive.html
+[onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/on-receive-or-null.html
+[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/send.html
+[SendChannel.onSend]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/on-send.html
+
+<!--- INDEX kotlinx.coroutines.selects -->
+
+[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html
+
+<!--- END -->
\ No newline at end of file
diff --git a/docs/topics/shared-mutable-state-and-concurrency.md b/docs/topics/shared-mutable-state-and-concurrency.md
new file mode 100644
index 0000000..b4b68b3
--- /dev/null
+++ b/docs/topics/shared-mutable-state-and-concurrency.md
@@ -0,0 +1,513 @@
+<!--- TEST_NAME SharedStateGuideTest -->
+
+[//]: # (title: Shared mutable state and concurrency)
+
+Coroutines can be executed concurrently using a multi-threaded dispatcher like the [Dispatchers.Default]. It presents
+all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
+Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
+but others are unique.
+
+## The problem
+
+Let us launch a hundred coroutines all doing the same action thousand times.
+We'll also measure their completion time for further comparisons:
+
+```kotlin
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+```
+
+We start with a very simple action that increments a shared mutable variable using
+multi-threaded [Dispatchers.Default].
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+//sampleStart
+var counter = 0
+
+fun main() = runBlocking {
+ withContext(Dispatchers.Default) {
+ massiveRun {
+ counter++
+ }
+ }
+ println("Counter = $counter")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt).
+>
+{type="note"}
+
+<!--- TEST LINES_START
+Completed 100000 actions in
+Counter =
+-->
+
+What does it print at the end? It is highly unlikely to ever print "Counter = 100000", because a hundred coroutines
+increment the `counter` concurrently from multiple threads without any synchronization.
+
+## Volatiles are of no help
+
+There is a common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+//sampleStart
+@Volatile // in Kotlin `volatile` is an annotation
+var counter = 0
+
+fun main() = runBlocking {
+ withContext(Dispatchers.Default) {
+ massiveRun {
+ counter++
+ }
+ }
+ println("Counter = $counter")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt).
+>
+{type="note"}
+
+<!--- TEST LINES_START
+Completed 100000 actions in
+Counter =
+-->
+
+This code works slower, but we still don't get "Counter = 100000" at the end, because volatile variables guarantee
+linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
+do not provide atomicity of larger actions (increment in our case).
+
+## Thread-safe data structures
+
+The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
+linearizable, or atomic) data structure that provides all the necessary synchronization for the corresponding
+operations that needs to be performed on a shared state.
+In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import java.util.concurrent.atomic.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+//sampleStart
+val counter = AtomicInteger()
+
+fun main() = runBlocking {
+ withContext(Dispatchers.Default) {
+ massiveRun {
+ counter.incrementAndGet()
+ }
+ }
+ println("Counter = $counter")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+Completed 100000 actions in xxx ms
+Counter = 100000
+-->
+
+This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
+standard data structures and basic operations on them. However, it does not easily scale to complex
+state or to complex operations that do not have ready-to-use thread-safe implementations.
+
+## Thread confinement fine-grained
+
+_Thread confinement_ is an approach to the problem of shared mutable state where all access to the particular shared
+state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
+the single event-dispatch/application thread. It is easy to apply with coroutines by using a
+single-threaded context.
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+//sampleStart
+val counterContext = newSingleThreadContext("CounterContext")
+var counter = 0
+
+fun main() = runBlocking {
+ withContext(Dispatchers.Default) {
+ massiveRun {
+ // confine each increment to a single-threaded context
+ withContext(counterContext) {
+ counter++
+ }
+ }
+ }
+ println("Counter = $counter")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+Completed 100000 actions in xxx ms
+Counter = 100000
+-->
+
+This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
+from multi-threaded [Dispatchers.Default] context to the single-threaded context using
+[withContext(counterContext)][withContext] block.
+
+## Thread confinement coarse-grained
+
+In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
+are confined to the single thread. The following example does it like that, running each coroutine in
+the single-threaded context to start with.
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+//sampleStart
+val counterContext = newSingleThreadContext("CounterContext")
+var counter = 0
+
+fun main() = runBlocking {
+ // confine everything to a single-threaded context
+ withContext(counterContext) {
+ massiveRun {
+ counter++
+ }
+ }
+ println("Counter = $counter")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+Completed 100000 actions in xxx ms
+Counter = 100000
+-->
+
+This now works much faster and produces correct result.
+
+## Mutual exclusion
+
+Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
+that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
+Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
+delimit a critical section. The key difference is that `Mutex.lock()` is a suspending function. It does not block a thread.
+
+There is also [withLock] extension function that conveniently represents
+`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.sync.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+//sampleStart
+val mutex = Mutex()
+var counter = 0
+
+fun main() = runBlocking {
+ withContext(Dispatchers.Default) {
+ massiveRun {
+ // protect each increment with lock
+ mutex.withLock {
+ counter++
+ }
+ }
+ }
+ println("Counter = $counter")
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+Completed 100000 actions in xxx ms
+Counter = 100000
+-->
+
+The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
+where you absolutely must modify some shared state periodically, but there is no natural thread that this state
+is confined to.
+
+## Actors
+
+An [actor](https://en.wikipedia.org/wiki/Actor_model) is an entity made up of a combination of a coroutine,
+the state that is confined and encapsulated into this coroutine,
+and a channel to communicate with other coroutines. A simple actor can be written as a function,
+but an actor with a complex state is better suited for a class.
+
+There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
+scope to receive messages from and combines the send channel into the resulting job object, so that a
+single reference to the actor can be carried around as its handle.
+
+The first step of using an actor is to define a class of messages that an actor is going to process.
+Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
+We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
+to get its value. The later needs to send a response. A [CompletableDeferred] communication
+primitive, that represents a single value that will be known (communicated) in the future,
+is used here for that purpose.
+
+```kotlin
+// Message types for counterActor
+sealed class CounterMsg
+object IncCounter : CounterMsg() // one-way message to increment counter
+class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
+```
+
+Then we define a function that launches an actor using an [actor] coroutine builder:
+
+```kotlin
+// This function launches a new counter actor
+fun CoroutineScope.counterActor() = actor<CounterMsg> {
+ var counter = 0 // actor state
+ for (msg in channel) { // iterate over incoming messages
+ when (msg) {
+ is IncCounter -> counter++
+ is GetCounter -> msg.response.complete(counter)
+ }
+ }
+}
+```
+
+The main code is straightforward:
+
+<!--- CLEAR -->
+
+```kotlin
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.*
+import kotlin.system.*
+
+suspend fun massiveRun(action: suspend () -> Unit) {
+ val n = 100 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ coroutineScope { // scope for coroutines
+ repeat(n) {
+ launch {
+ repeat(k) { action() }
+ }
+ }
+ }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+// Message types for counterActor
+sealed class CounterMsg
+object IncCounter : CounterMsg() // one-way message to increment counter
+class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
+
+// This function launches a new counter actor
+fun CoroutineScope.counterActor() = actor<CounterMsg> {
+ var counter = 0 // actor state
+ for (msg in channel) { // iterate over incoming messages
+ when (msg) {
+ is IncCounter -> counter++
+ is GetCounter -> msg.response.complete(counter)
+ }
+ }
+}
+
+//sampleStart
+fun main() = runBlocking<Unit> {
+ val counter = counterActor() // create the actor
+ withContext(Dispatchers.Default) {
+ massiveRun {
+ counter.send(IncCounter)
+ }
+ }
+ // send a message to get a counter value from an actor
+ val response = CompletableDeferred<Int>()
+ counter.send(GetCounter(response))
+ println("Counter = ${response.await()}")
+ counter.close() // shutdown the actor
+}
+//sampleEnd
+```
+{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
+
+> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt).
+>
+{type="note"}
+
+<!--- TEST ARBITRARY_TIME
+Completed 100000 actions in xxx ms
+Counter = 100000
+-->
+
+It does not matter (for correctness) what context the actor itself is executed in. An actor is
+a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
+works as a solution to the problem of shared mutable state. Indeed, actors may modify their own private state,
+but can only affect each other through messages (avoiding the need for any locks).
+
+Actor is more efficient than locking under load, because in this case it always has work to do and it does not
+have to switch to a different context at all.
+
+> Note that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
+> with the channel that it receives messages from, while a producer is associated with the channel that it
+> sends elements to.
+>
+{type="note"}
+
+<!--- MODULE kotlinx-coroutines-core -->
+<!--- INDEX kotlinx.coroutines -->
+
+[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html
+[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html
+[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-completable-deferred/index.html
+
+<!--- INDEX kotlinx.coroutines.sync -->
+
+[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html
+[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/lock.html
+[Mutex.unlock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/unlock.html
+[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/with-lock.html
+
+<!--- INDEX kotlinx.coroutines.channels -->
+
+[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html
+[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html
+
+<!--- END -->
\ No newline at end of file