diff --git a/docs/images/run-icon.png b/docs/images/run-icon.png
new file mode 100644
index 0000000000..ebc6d3e91c
Binary files /dev/null and b/docs/images/run-icon.png differ
diff --git a/docs/topics/coroutines-basics.md b/docs/topics/coroutines-basics.md
index 5b467c58bf..950dd058d0 100644
--- a/docs/topics/coroutines-basics.md
+++ b/docs/topics/coroutines-basics.md
@@ -3,212 +3,326 @@
[//]: # (title: Coroutines basics)
-This section covers basic coroutine concepts.
+To create applications that perform multiple tasks at once, a concept known as concurrency,
+Kotlin uses coroutines. Coroutines let you write concurrent code in a clear and sequential style.
-## Your first coroutine
+The most basic building block of coroutines is the suspending function.
+It makes it possible to pause a running operation and resume it later without losing the structure of your code.
-A _coroutine_ is an instance of a suspendable computation. It is conceptually similar to a thread, in the sense that it
-takes a block of code to run that works concurrently with the rest of the code.
-However, a coroutine is not bound to any particular thread. It may suspend its execution in one thread and resume in another one.
+To mark a function as suspendable, use the `suspend` keyword:
-Coroutines can be thought of as light-weight threads, but there is a number
-of important differences that make their real-life usage very different from threads.
+```kotlin
+suspend fun greet() {
+ println("Hello world from a suspending function")
+}
+```
-Run the following code to get to your first working coroutine:
+You can only call a suspending function from another suspending function or from a coroutine.
+Even the `main()` function can be suspending:
```kotlin
-import kotlinx.coroutines.*
+suspend fun main() {
+ showUserInfo()
+}
-//sampleStart
-fun main() = runBlocking { // this: CoroutineScope
- launch { // launch a new coroutine and continue
- delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
- println("World!") // print after delay
- }
- println("Hello") // main coroutine continues while a previous one is delayed
+suspend fun showUserInfo() {
+ println("Loading user...")
+ greet()
+ println("User: John Smith")
+}
+
+suspend fun greet() {
+ println("Hello world from a suspending function")
}
-//sampleEnd
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
-You will see the following result:
+This example doesn’t use concurrency yet, but by marking the functions with the `suspend` keyword,
+you allow them to be used in concurrent code later.
-```text
-Hello
-World!
-```
+While the `suspend` keyword is part of the Kotlin standard library, most coroutine features
+are available through the [`kotlinx.coroutines`](https://github.com/Kotlin/kotlinx.coroutines) library.
-
+## Add the kotlinx.coroutines library to your project
-Let's dissect what this code does.
+To include the `kotlinx.coroutines` library in your project, add the corresponding dependency configuration based on your build tool.
-[launch] is a _coroutine builder_. It launches a new coroutine concurrently with
-the rest of the code, which continues to work independently. That's why `Hello` has been printed first.
+### Gradle
-[delay] is a special _suspending function_. It _suspends_ the coroutine for a specific time. Suspending a coroutine
-does not _block_ the underlying thread, but allows other coroutines to run and use the underlying thread for
-their code.
+Add the following dependency to your `build.gradle(.kts)` file:
-[runBlocking] is also a coroutine builder that bridges the non-coroutine world of a regular `fun main()` and
-the code with coroutines inside of `runBlocking { ... }` curly braces. This is highlighted in an IDE by
-`this: CoroutineScope` hint right after the `runBlocking` opening curly brace.
+
+
-If you remove or forget `runBlocking` in this code, you'll get an error on the [launch] call, since `launch`
-is declared only on the [CoroutineScope]:
+```kotlin
+// build.gradle.kts
+repositories {
+ mavenCentral()
+}
+dependencies {
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%")
+}
```
-Unresolved reference: launch
+
+
+
+
+```groovy
+// build.gradle
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%'
+}
```
+
+
+
+### Maven
+
+Add the following dependency to your `pom.xml` file.
+
+```xml
+
+
+
+ org.jetbrains.kotlin
+ kotlinx-coroutines-core
+ %coroutinesVersion%
+
+
+ ...
+
+```
+
+## Create your first coroutines
+
+Suspending functions are the basic building blocks for concurrency in Kotlin, but they can only run inside another suspending function or a coroutine.
+A coroutine is a suspendable computation that runs on _threads_ and can run concurrently or in parallel with other coroutines.
+
+On the JVM, all concurrent code, such as coroutines, runs on threads, which are managed by the operating system.
+Coroutines can suspend their execution instead of blocking a thread, which lets you run many tasks with less overhead.
-The name of `runBlocking` means that the thread that runs it (in this case — the main thread) gets _blocked_ for
-the duration of the call, until all the coroutines inside `runBlocking { ... }` complete their execution. You will
-often see `runBlocking` used like that at the very top-level of the application and quite rarely inside the real code,
-as threads are expensive resources and blocking them is inefficient and is often not desired.
+> You can display coroutine names next to thread names in the output of your code for additional information.
+> In IntelliJ IDEA, right-click the `Run` icon: {width=30} next to your `main()` function, select `Modify Run Configuration...`, and add `-Dkotlinx.coroutines.debug` in `VM options`.
+>
+> See [Debug coroutines using IntelliJ IDEA — Tutorial](debug-coroutines-with-idea.md) for more information.
+>
+{style="tip"}
-### Structured concurrency
+To create a coroutine in Kotlin, you need a suspending function, a scope, a builder to start it, and a dispatcher to control which threads it uses:
-Coroutines follow a principle of
-**structured concurrency** which means that new coroutines can only be launched in a specific [CoroutineScope]
-which delimits the lifetime of the coroutine. The above example shows that [runBlocking] establishes the corresponding
-scope and that is why the previous example waits until `World!` is printed after a second's delay and only then exits.
+1. Import the `kotlinx.coroutines` library:
-In a real application, you will be launching a lot of coroutines. Structured concurrency ensures that they are not
-lost and do not leak. An outer scope cannot complete until all its children coroutines complete.
-Structured concurrency also ensures that any errors in the code are properly reported and are never lost.
+ ```kotlin
+ import kotlinx.coroutines.*
+ ```
-## Extract function refactoring
+2. Mark functions that can pause and resume with the `suspend` keyword:
-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
+ suspend fun greet() {
+ println("Hello world from a suspending function on thread: ${Thread.currentThread().name}")
+ }
+
+ suspend fun main() {}
+ ```
+
+ > While you can mark the `main()` function as `suspend` in some projects, other projects or frameworks might not allow changing the `main()` function this way.
+ > In those cases, coroutine builder functions like [`runBlocking`](#runblocking) are the usual entry point for calling suspending code.
+ >
+ {style="note"}
+
+
+3. Use the [`coroutineScope()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html) function to [create a `CoroutineScope`](#coroutine-scope-and-structured-concurrency) that groups your coroutines and controls their lifecycle:
+
+ ```kotlin
+ suspend fun main() = coroutineScope {
+ // Add coroutine builder here
+ }
+ ```
+
+4. Use a [coroutine builder function](#coroutine-builder-functions) like [`.launch()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html) to start the coroutine:
+
+ ```kotlin
+ suspend fun main() = coroutineScope {
+ // Starts a coroutine inside the scope
+ launch {
+ greet()
+ }
+ println("This runs while the coroutine is active")
+ }
+ ```
+
+5. Specify a [coroutine dispatcher](coroutine-context-and-dispatchers.md) like [`Dispatchers.Default`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html) to control the [thread pool](#comparing-coroutines-and-jvm-threads) for your coroutine:
+
+ ```kotlin
+ suspend fun main() = coroutineScope {
+ // Starts a coroutine inside the scope with a specified dispatcher
+ launch(Dispatchers.Default) {
+ greet()
+ }
+ println("This runs while the coroutine is active")
+ }
+ ```
+
+ > If you don’t specify a coroutine dispatcher, a coroutine builder like `.launch()` inherits the dispatcher from its `CoroutineScope`.
+ > If the scope doesn’t define a dispatcher, the builder uses `Dispatchers.Default`.
+ >
+ {style="note"}
+
+6. Combine these pieces to run multiple coroutines at the same time on a shared pool of threads:
+
+ ```kotlin
+ // Imports the coroutines library
+ import kotlinx.coroutines.*
+
+ // Defines a suspending function
+ suspend fun greet() {
+ println("Hello from greet() on thread: ${Thread.currentThread().name}")
+ }
+
+ suspend fun main() = coroutineScope {
+ // Starts a coroutine with Dispatchers.Default
+ launch(Dispatchers.Default) {
+ greet()
+ }
+
+ // Starts another coroutine
+ launch(Dispatchers.Default) {
+ println("Second coroutine on thread: ${Thread.currentThread().name}")
+ }
+
+ // Runs code in the coroutine scope
+ println("This runs while the coroutine is active")
+ }
+ ```
+ {kotlin-runnable="true"}
+
+This example demonstrates simple multithreading with coroutines on a shared thread pool.
+
+> Try running the example multiple times.
+> You may notice that the output order and thread names may change each time you run the program.
+> This is because the JVM and OS decide when threads run and tasks complete.
+>
+{style="tip"}
+
+## Coroutine scope and structured concurrency
+
+Coroutines follow a principle of _structured concurrency_, which means new coroutines can only be launched in a specific [`CoroutineScope`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/) that defines their lifecycle.
+
+When you work with multiple coroutines, you often need to run many tasks at once, cancel them when they are no longer needed, and handle errors safely.
+Without clear structure, you risk leaving coroutines running longer than needed, wasting resources.
+
+Structured concurrency keeps coroutines organized in a hierarchy.
+When you launch a coroutine, it belongs to its scope.
+If the scope is canceled, all its child coroutines are canceled too.
+
+[Coroutine builder functions](#coroutine-builder-functions) are extension functions on `CoroutineScope`.
+When you start a coroutine inside another coroutine, it automatically becomes a child of its parent scope.
+The parent coroutine's scope waits for all its children to finish before it completes.
+
+To create a coroutine scope without launching a new coroutine, use the [`coroutineScope()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html) function:
```kotlin
import kotlinx.coroutines.*
-//sampleStart
-fun main() = runBlocking { // this: CoroutineScope
- launch { doWorld() }
- println("Hello")
-}
+suspend fun main() = coroutineScope {
+ // Starts a new coroutine in the coroutine scope
+ launch {
+ // Suspends for one second without blocking the thread
+ delay(1000L)
+ println("Child coroutine completed")
+ }
+ launch {
+ delay(2000L)
+ println("Another child coroutine completed")
+ }
-// this is your first suspending function
-suspend fun doWorld() {
- delay(1000L)
- println("World!")
+ // Runs immediately in the parent coroutine
+ println("Coroutine scope completed")
}
-//sampleEnd
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
-
+This example uses the [`delay()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html#) function to show how the coroutine scope waits for its child coroutines to finish.
+You can specify the wait time in milliseconds, so `delay(1000L)` suspends the coroutine for one second without blocking the thread.
-## Scope builder
+## Coroutine builder functions
-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.
+Coroutine builder functions create new coroutines inside an existing [coroutine scope](#coroutine-scope-and-structured-concurrency).
+Each builder defines how the coroutine starts and how you interact with its result.
-[runBlocking] and [coroutineScope][_coroutineScope] builders 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.
+### .launch()
-You can use `coroutineScope` from any suspending function.
-For example, you can move the concurrent printing of `Hello` and `World` into a `suspend fun doWorld()` function:
+The [`.launch()`()](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html#) coroutine builder function starts a new coroutine without blocking the rest of the scope.
+Use `.launch()` to run a task alongside other work when the result isn't needed or you don't want to wait for it:
```kotlin
import kotlinx.coroutines.*
-//sampleStart
-fun main() = runBlocking {
- doWorld()
-}
-
-suspend fun doWorld() = coroutineScope { // this: CoroutineScope
+suspend fun main() = coroutineScope {
+ // Starts a coroutine that runs without blocking the scope
launch {
- delay(1000L)
- println("World!")
+ println("Sending notification in background")
}
- println("Hello")
+
+ // Main coroutine continues while a previous one is delayed
+ println("Scope continues")
}
-//sampleEnd
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
+
+After running this example, you can see that the `main()` function isn’t blocked by `.launch()` and keeps running other code while the coroutine works in the background.
+
+### .async()
+
+Use the [`.async()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html) builder function to start an asynchronous computation that runs alongside other code and returns a result you can access later.
+The result is wrapped in a `Deferred` object, which you can access by calling the `.await()` function:
+
+```kotlin
+import kotlinx.coroutines.*
-This code also prints:
+suspend fun main() = coroutineScope {
+ // Starts a coroutine that returns a number
+ val result = async {
+ 2 + 3
+ }
-```text
-Hello
-World!
+ // Gets the result from the coroutine with the await() function
+ println("The result is ${result.await()}")
+}
```
+{kotlin-runnable="true"}
-
+### .runBlocking()
-## Scope builder and concurrency
+Use the [`.runBlocking()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) coroutine builder function to create a coroutine scope in a blocking context.
+Instead of using a shared thread pool, `.runBlocking()` blocks the [thread](#comparing-coroutines-and-jvm-threads) it runs on and waits for all coroutines inside it to finish before continuing.
-A [coroutineScope][_coroutineScope] builder can be used inside any suspending function to perform multiple concurrent operations.
-Let's launch two concurrent coroutines inside a `doWorld` suspending function:
+`.runBlocking()` creates a new `CoroutineScope` for the code inside it.
+This lets you call suspending functions without marking the surrounding function as `suspend`, for example, in the `main()` function:
```kotlin
import kotlinx.coroutines.*
-//sampleStart
-// Sequentially executes doWorld followed by "Done"
+// Runs the greet() function inside a blocking scope
fun main() = runBlocking {
- doWorld()
+ greet()
+ delay(1000L)
println("Done")
}
-// Concurrently executes both sections
-suspend fun doWorld() = coroutineScope { // this: CoroutineScope
- launch {
- delay(2000L)
- println("World 2")
- }
- launch {
- delay(1000L)
- println("World 1")
- }
- println("Hello")
+suspend fun greet() {
+ println("Hello from a suspending function")
}
-//sampleEnd
-```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt).
->
-{style="note"}
-
-Both pieces of code inside `launch { ... }` blocks execute _concurrently_, with
-`World 1` printed first, after a second from start, and `World 2` printed next, after two seconds from start.
-A [coroutineScope][_coroutineScope] in `doWorld` completes only after both are complete, so `doWorld` returns and
-allows `Done` string to be printed only after that:
-
-```text
-Hello
-World 1
-World 2
-Done
```
+{kotlin-runnable="true"}
-
-
+
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt).
+-->
+
+## Coroutine dispatchers
+
+A [coroutine dispatcher](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/#) controls which thread or thread pool coroutines use for their execution.
+Coroutines are not tied to a single thread.
+They can pause on one thread and resume on another, depending on the dispatcher.
+This lets you run many coroutines at the same time without blocking threads.
+
+A dispatcher works together with the [coroutine scope](#coroutine-scope-and-structured-concurrency) to define when coroutines run and where they run.
+While the coroutine scope controls the coroutine’s lifecycle, the dispatcher controls which threads are used for execution.
+
+> You don't have to create a dispatcher for every coroutine.
+> By default, coroutines inherit the dispatcher from their parent scope.
+> You can specify a dispatcher if you need to run a coroutine in a different context.
>
{style="note"}
-This code produces:
+The `kotlinx.coroutines` library includes different dispatchers for different use cases.
+For example, [`Dispatchers.Default`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html) runs coroutines on a shared pool of threads performing work in the background,
+separate from the main thread.
+This multithreaded dispatcher is optimized for CPU-intensive tasks like calculations or data processing:
+
+```kotlin
+import kotlinx.coroutines.*
+
+fun main() = runBlocking {
+ // Runs runBlocking on the main thread
+ println("runBlocking running on ${Thread.currentThread().name}")
+
+ val one = async(Dispatchers.Default) {
+ // Starts first calculation on a thread in the Default dispatcher’s thread pool
+ println("First calculation starting on ${Thread.currentThread().name}")
+ val sum = (1..500_000).sum()
+ // Suspends for 200 ms
+ delay(200L)
+ println("First calculation done on ${Thread.currentThread().name}")
+ sum
+ }
+
+ val two = async(Dispatchers.Default) {
+ // Starts second calculation on a thread in the Default dispatcher’s thread pool
+ println("Second calculation starting on ${Thread.currentThread().name}")
+ val sum = (500_001..1_000_000).sum()
+ println("Second calculation done on ${Thread.currentThread().name}")
+ sum
+ }
-```text
-Hello
-World!
-Done
+ // Waits for both calculations and prints the result
+ println("Combined total: ${one.await() + two.await()}")
+}
```
+{kotlin-runnable="true"}
+
+For more information, see [Coroutine context and dispatchers](coroutine-context-and-dispatchers.md)
+
+## Comparing coroutines and JVM threads
-
+While coroutines are suspendable computations that run code concurrently like threads on the JVM, they work differently under the hood.
-## Coroutines are light-weight
+A _thread_ is managed by the operating system. Threads can run tasks parallel on multiple CPU cores and represent a standard approach to concurrency on the JVM.
+When you create a thread, the operating system allocates memory for its stack and uses the kernel to switch between threads.
+This makes threads powerful but also resource-intensive.
+Each thread usually needs a few megabytes of memory, and typically the JVM can only handle a few thousand threads at once.
-Coroutines are less resource-intensive than JVM threads. Code that exhausts the
-JVM's available memory when using threads can be expressed using coroutines
-without hitting resource limits. For example, the following code launches
-50,000 distinct coroutines that each waits 5 seconds and then prints a period
-('.') while consuming very little memory:
+On the other hand, a coroutine isn't bound to a specific thread.
+It can suspend on one thread and resume on another, so many coroutines can share the same thread pool.
+When a coroutine suspends, the thread isn't blocked, and it remains free to run other tasks.
+This makes coroutines much lighter than threads and allows running hundreds of thousands in one process without exhausting system resources.
+
+Let’s look at an example where 50,000 coroutines each wait five seconds and then print a period (`.`):
```kotlin
import kotlinx.coroutines.*
@@ -268,26 +431,40 @@ fun main() = runBlocking {
```
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt).
+
-If you write the same program using threads (remove `runBlocking`, replace
-`launch` with `thread`, and replace `delay` with `Thread.sleep`), it will
-consume a lot of memory. Depending on your operating system, JDK version,
-and its settings, it will either throw an out-of-memory error or start threads slowly
-so that there are never too many concurrently running threads.
+Now let's look at the same example using JVM threads:
+
+```kotlin
+import kotlin.concurrent.thread
+
+fun main() {
+ repeat(50_000) {
+ thread {
+ Thread.sleep(5000L)
+ print(".")
+ }
+ }
+}
+```
+
+Running this version uses much more memory because each thread needs its own memory stack.
+Depending on your operating system, JDK version, and settings,
+it may either throw an out-of-memory error or slow down thread creation to avoid running too many threads at once.
-[launch]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[delay]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
-[runBlocking]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[CoroutineScope]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[_coroutineScope]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
-[Job]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+## What's next
+
+* Discover more about combining suspending functions in [Composing suspending functions](composing-suspending-functions.md).
+* Learn how to cancel coroutines and handle timeouts in [Cancellation and timeouts](cancellation-and-timeouts.md).
+* Dive deeper into coroutine execution and thread management in [Coroutine context and dispatchers](coroutine-context-and-dispatchers.md).
+* Learn how to return multiple asynchronously computed values in [Asynchronous flows](flow.md)