blob: 1b390cc0077e56519a2f3b692ae2d609edf10d91 [file] [log] [blame] [view]
Roman Elizarov43e90112017-05-10 11:25:20 +03001<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
Roman Elizarova5e653f2017-02-13 13:49:55 +03002/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03003 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarova5e653f2017-02-13 13:49:55 +03004 */
Roman Elizarovf16fd272017-02-07 11:26:00 +03005
Roman Elizarova5e653f2017-02-13 13:49:55 +03006// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarova9687a32018-06-29 17:28:38 +03007package kotlinx.coroutines.experimental.guide.$$1$$2
Roman Elizarovf16fd272017-02-07 11:26:00 +03008
Roman Elizarova5e653f2017-02-13 13:49:55 +03009import kotlinx.coroutines.experimental.*
Roman Elizarovf16fd272017-02-07 11:26:00 +030010-->
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +030011<!--- KNIT core/kotlinx-coroutines-core/test/guide/.*\.kt -->
12<!--- TEST_OUT core/kotlinx-coroutines-core/test/guide/test/GuideTest.kt
Roman Elizarov731f0ad2017-02-22 20:48:45 +030013// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarova9687a32018-06-29 17:28:38 +030014package kotlinx.coroutines.experimental.guide.test
Roman Elizarov731f0ad2017-02-22 20:48:45 +030015
16import org.junit.Test
17
18class GuideTest {
19-->
Roman Elizarovf16fd272017-02-07 11:26:00 +030020
Roman Elizarov7deefb82017-01-31 10:33:17 +030021# Guide to kotlinx.coroutines by example
22
Roman Elizarova4d45d22017-11-20 16:47:09 +030023This is a guide on core features of `kotlinx.coroutines` with a series of examples.
Roman Elizarov7deefb82017-01-31 10:33:17 +030024
Roman Elizarov2a638922017-03-04 10:22:43 +030025## Introduction and setup
26
27Kotlin, as a language, provides only minimal low-level APIs in its standard library to enable various other
28libraries to utilize coroutines. Unlike many other languages with similar capabilities, `async` and `await`
29are not keywords in Kotlin and are not even part of its standard library.
30
Robert Hencke497d3432017-04-11 00:14:29 -040031`kotlinx.coroutines` is one such rich library. It contains a number of high-level
Roman Elizarova4d45d22017-11-20 16:47:09 +030032coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
Roman Elizarov2a638922017-03-04 10:22:43 +030033You need to add a dependency on `kotlinx-coroutines-core` module as explained
34[here](README.md#using-in-your-projects) to use primitives from this guide in your projects.
35
Roman Elizarov1293ccd2017-02-01 18:49:54 +030036## Table of contents
37
Roman Elizarovfa7723e2017-02-06 11:17:51 +030038<!--- TOC -->
39
Roman Elizarov1293ccd2017-02-01 18:49:54 +030040* [Coroutine basics](#coroutine-basics)
41 * [Your first coroutine](#your-first-coroutine)
42 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
43 * [Waiting for a job](#waiting-for-a-job)
44 * [Extract function refactoring](#extract-function-refactoring)
45 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
46 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
47* [Cancellation and timeouts](#cancellation-and-timeouts)
48 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
49 * [Cancellation is cooperative](#cancellation-is-cooperative)
50 * [Making computation code cancellable](#making-computation-code-cancellable)
51 * [Closing resources with finally](#closing-resources-with-finally)
52 * [Run non-cancellable block](#run-non-cancellable-block)
53 * [Timeout](#timeout)
54* [Composing suspending functions](#composing-suspending-functions)
55 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030056 * [Concurrent using async](#concurrent-using-async)
57 * [Lazily started async](#lazily-started-async)
58 * [Async-style functions](#async-style-functions)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030059* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030060 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030061 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
62 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
63 * [Jumping between threads](#jumping-between-threads)
64 * [Job in the context](#job-in-the-context)
65 * [Children of a coroutine](#children-of-a-coroutine)
66 * [Combining contexts](#combining-contexts)
Roman Elizarov8b38fa22017-09-27 17:44:31 +030067 * [Parental responsibilities](#parental-responsibilities)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030068 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030069 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030070* [Channels](#channels)
71 * [Channel basics](#channel-basics)
72 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
73 * [Building channel producers](#building-channel-producers)
74 * [Pipelines](#pipelines)
75 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
76 * [Fan-out](#fan-out)
77 * [Fan-in](#fan-in)
78 * [Buffered channels](#buffered-channels)
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +030079 * [Ticker channels](#ticker-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030080 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030081* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
82 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030083 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030084 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030085 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
86 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030087 * [Mutual exclusion](#mutual-exclusion)
88 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +030089* [Select expression](#select-expression)
90 * [Selecting from channels](#selecting-from-channels)
91 * [Selecting on close](#selecting-on-close)
92 * [Selecting to send](#selecting-to-send)
93 * [Selecting deferred values](#selecting-deferred-values)
94 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +030095* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030096
Roman Elizarova5e653f2017-02-13 13:49:55 +030097<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +030098
99## Coroutine basics
100
101This section covers basic coroutine concepts.
102
103### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300104
105Run the following code:
106
107```kotlin
108fun main(args: Array<String>) {
Roman Elizarova4d45d22017-11-20 16:47:09 +0300109 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300110 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
111 println("World!") // print after delay
112 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300113 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300114 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
115}
116```
117
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300118> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300119
120Run this code:
121
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300122```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300123Hello,
124World!
125```
126
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300127<!--- TEST -->
128
Roman Elizarov419a6c82017-02-09 18:36:22 +0300129Essentially, coroutines are light-weight threads.
130They are launched with [launch] _coroutine builder_.
131You can achieve the same result replacing
Roman Elizarov66f018c2017-09-29 21:39:03 +0300132`launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300133
Roman Elizarov66f018c2017-09-29 21:39:03 +0300134If you start by replacing `launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300135
136```
137Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
138```
139
Roman Elizarov419a6c82017-02-09 18:36:22 +0300140That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300141coroutine and it can be only used from a coroutine.
142
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300143### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300144
Roman Elizarova4d45d22017-11-20 16:47:09 +0300145The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
146It is easy to get lost which one is blocking and which one is not.
147Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300148
149```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300150fun main(args: Array<String>) {
151 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300152 delay(1000L)
153 println("World!")
154 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300155 println("Hello,") // main thread continues here immediately
156 runBlocking { // but this expression blocks the main thread
157 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
158 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300159}
160```
161
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300162> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300163
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300164<!--- TEST
165Hello,
166World!
167-->
168
Roman Elizarov419a6c82017-02-09 18:36:22 +0300169The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100170The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300171
Roman Elizarova4d45d22017-11-20 16:47:09 +0300172This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
173the execution of the main function:
174
175```kotlin
176fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
177 launch { // launch new coroutine in background and continue
178 delay(1000L)
179 println("World!")
180 }
181 println("Hello,") // main coroutine continues here immediately
182 delay(2000L) // delaying for 2 seconds to keep JVM alive
183}
184```
185
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300186> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt)
Roman Elizarova4d45d22017-11-20 16:47:09 +0300187
188<!--- TEST
189Hello,
190World!
191-->
192
193Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
194We explicitly specify its `Unit` return type, because a well-formed `main` function in Kotlin has to return `Unit`.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300195
196This is also a way to write unit-tests for suspending functions:
197
198```kotlin
199class MyTest {
200 @Test
201 fun testMySuspendingFunction() = runBlocking<Unit> {
202 // here we can use suspending functions using any assertion style that we like
203 }
204}
205```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300206
207<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300208
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300209### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300210
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300211Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300212wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300213
214```kotlin
215fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300216 val job = launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300217 delay(1000L)
218 println("World!")
219 }
220 println("Hello,")
221 job.join() // wait until child coroutine completes
222}
223```
224
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300225> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300226
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300227<!--- TEST
228Hello,
229World!
230-->
231
Roman Elizarov7deefb82017-01-31 10:33:17 +0300232Now the result is still the same, but the code of the main coroutine is not tied to the duration of
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300233the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300234
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300235### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300236
Roman Elizarov66f018c2017-09-29 21:39:03 +0300237Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300238perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
239That is your first _suspending function_. Suspending functions can be used inside coroutines
240just like regular functions, but their additional feature is that they can, in turn,
241use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
242
243```kotlin
244fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300245 val job = launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300246 println("Hello,")
247 job.join()
248}
249
250// this is your first suspending function
251suspend fun doWorld() {
252 delay(1000L)
253 println("World!")
254}
255```
256
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300257> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300258
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300259<!--- TEST
260Hello,
261World!
262-->
263
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300264### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300265
266Run the following code:
267
268```kotlin
269fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300270 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
271 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300272 delay(1000L)
273 print(".")
274 }
275 }
276 jobs.forEach { it.join() } // wait for all jobs to complete
277}
278```
279
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300280> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300281
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300282<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
283
Roman Elizarov66f018c2017-09-29 21:39:03 +0300284It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300285Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
286
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300287### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300288
289The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300290returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300291
292```kotlin
293fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300294 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300295 repeat(1000) { i ->
296 println("I'm sleeping $i ...")
297 delay(500L)
298 }
299 }
300 delay(1300L) // just quit after delay
301}
302```
303
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300304> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300305
306You can run and see that it prints three lines and terminates:
307
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300308```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300309I'm sleeping 0 ...
310I'm sleeping 1 ...
311I'm sleeping 2 ...
312```
313
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300314<!--- TEST -->
315
Roman Elizarov7deefb82017-01-31 10:33:17 +0300316Active coroutines do not keep the process alive. They are like daemon threads.
317
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300318## Cancellation and timeouts
319
320This section covers coroutine cancellation and timeouts.
321
322### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300323
Brad977ada12018-07-19 16:01:40 -0400324In a small application the return from "main" method might sound like a good idea to get all coroutines
325implicitly terminated but in a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300326The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300327
328```kotlin
329fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300330 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300331 repeat(1000) { i ->
332 println("I'm sleeping $i ...")
333 delay(500L)
334 }
335 }
336 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300337 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300338 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300339 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300340 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300341}
342```
343
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300344> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300345
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300346It produces the following output:
347
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300348```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300349I'm sleeping 0 ...
350I'm sleeping 1 ...
351I'm sleeping 2 ...
352main: I'm tired of waiting!
353main: Now I can quit.
354```
355
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300356<!--- TEST -->
357
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300358As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
Roman Elizarov88396732017-09-27 21:30:47 +0300359There is also a [Job] extension function [cancelAndJoin]
360that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300361
362### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300363
Tair Rzayevaf734622017-02-01 22:30:16 +0200364Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300365All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300366coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300367a computation and does not check for cancellation, then it cannot be cancelled, like the following
368example shows:
369
370```kotlin
371fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700372 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300373 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700374 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300375 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300376 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700377 // print a message twice a second
378 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300379 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300380 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300381 }
382 }
383 }
384 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300385 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300386 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300387 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300388}
389```
390
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300391> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300392
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300393Run it to see that it continues to print "I'm sleeping" even after cancellation
394until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300395
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300396<!--- TEST
397I'm sleeping 0 ...
398I'm sleeping 1 ...
399I'm sleeping 2 ...
400main: I'm tired of waiting!
401I'm sleeping 3 ...
402I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300403main: Now I can quit.
404-->
405
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300406### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300407
408There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300409invoke a suspending function that checks for cancellation. There is a [yield] function that is a good choice for that purpose.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300410The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300411
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300412Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300413
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300414```kotlin
415fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700416 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300417 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700418 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300419 var i = 0
420 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700421 // print a message twice a second
422 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300423 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700424 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300425 }
426 }
427 }
428 delay(1300L) // delay a bit
429 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300430 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300431 println("main: Now I can quit.")
432}
433```
434
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300435> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300436
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300437As you can see, now this loop is cancelled. [isActive][CoroutineScope.isActive] is a property that is available inside
Roman Elizarov419a6c82017-02-09 18:36:22 +0300438the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300439
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300440<!--- TEST
441I'm sleeping 0 ...
442I'm sleeping 1 ...
443I'm sleeping 2 ...
444main: I'm tired of waiting!
445main: Now I can quit.
446-->
447
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300448### Closing resources with finally
449
Roman Elizarov419a6c82017-02-09 18:36:22 +0300450Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Brad977ada12018-07-19 16:01:40 -0400451the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300452finalization actions normally when coroutine is cancelled:
453
454```kotlin
455fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300456 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300457 try {
458 repeat(1000) { i ->
459 println("I'm sleeping $i ...")
460 delay(500L)
461 }
462 } finally {
463 println("I'm running finally")
464 }
465 }
466 delay(1300L) // delay a bit
467 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300468 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300469 println("main: Now I can quit.")
470}
471```
472
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300473> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300474
Roman Elizarov88396732017-09-27 21:30:47 +0300475Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
476so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300477
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300478```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300479I'm sleeping 0 ...
480I'm sleeping 1 ...
481I'm sleeping 2 ...
482main: I'm tired of waiting!
483I'm running finally
484main: Now I can quit.
485```
486
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300487<!--- TEST -->
488
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300489### Run non-cancellable block
490
491Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300492[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300493problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
494communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
495rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300496`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300497
498```kotlin
499fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300500 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300501 try {
502 repeat(1000) { i ->
503 println("I'm sleeping $i ...")
504 delay(500L)
505 }
506 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300507 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300508 println("I'm running finally")
509 delay(1000L)
510 println("And I've just delayed for 1 sec because I'm non-cancellable")
511 }
512 }
513 }
514 delay(1300L) // delay a bit
515 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300516 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300517 println("main: Now I can quit.")
518}
519```
520
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300521> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300522
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300523<!--- TEST
524I'm sleeping 0 ...
525I'm sleeping 1 ...
526I'm sleeping 2 ...
527main: I'm tired of waiting!
528I'm running finally
529And I've just delayed for 1 sec because I'm non-cancellable
530main: Now I can quit.
531-->
532
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300533### Timeout
534
Brad977ada12018-07-19 16:01:40 -0400535The most obvious reason to cancel coroutine execution in practice
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300536is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300537While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
538the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300539Look at the following example:
540
541```kotlin
542fun main(args: Array<String>) = runBlocking<Unit> {
543 withTimeout(1300L) {
544 repeat(1000) { i ->
545 println("I'm sleeping $i ...")
546 delay(500L)
547 }
548 }
549}
550```
551
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300552> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300553
554It produces the following output:
555
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300556```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300557I'm sleeping 0 ...
558I'm sleeping 1 ...
559I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300560Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300561```
562
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300563<!--- TEST STARTS_WITH -->
564
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300565The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300566We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300567inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300568However, in this example we have used `withTimeout` right inside the `main` function.
569
570Because cancellation is just an exception, all the resources will be closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300571You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
572you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300573that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
574
575```kotlin
576fun main(args: Array<String>) = runBlocking<Unit> {
577 val result = withTimeoutOrNull(1300L) {
578 repeat(1000) { i ->
579 println("I'm sleeping $i ...")
580 delay(500L)
581 }
582 "Done" // will get cancelled before it produces this result
583 }
584 println("Result is $result")
585}
586```
587
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300588> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300589
590There is no longer an exception when running this code:
591
592```text
593I'm sleeping 0 ...
594I'm sleeping 1 ...
595I'm sleeping 2 ...
596Result is null
597```
598
599<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300600
601## Composing suspending functions
602
603This section covers various approaches to composition of suspending functions.
604
605### Sequential by default
606
607Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300608remote service call or computation. We just pretend they are useful, but actually each one just
609delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300610
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300611<!--- INCLUDE .*/example-compose-([0-9]+).kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300612import kotlin.system.*
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300613-->
614
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300615```kotlin
616suspend fun doSomethingUsefulOne(): Int {
617 delay(1000L) // pretend we are doing something useful here
618 return 13
619}
620
621suspend fun doSomethingUsefulTwo(): Int {
622 delay(1000L) // pretend we are doing something useful here, too
623 return 29
624}
625```
626
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300627<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
628
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300629What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
630`doSomethingUsefulTwo` and compute the sum of their results?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200631In practice we do this if we use the results of the first function to make a decision on whether we need
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300632to invoke the second one or to decide on how to invoke it.
633
634We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300635code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300636time it takes to execute both suspending functions:
637
638```kotlin
639fun main(args: Array<String>) = runBlocking<Unit> {
640 val time = measureTimeMillis {
641 val one = doSomethingUsefulOne()
642 val two = doSomethingUsefulTwo()
643 println("The answer is ${one + two}")
644 }
645 println("Completed in $time ms")
646}
647```
648
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300649> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300650
651It produces something like this:
652
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300653```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300654The answer is 42
655Completed in 2017 ms
656```
657
Roman Elizarov35d2c342017-07-20 14:54:39 +0300658<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300659
Roman Elizarov32d95322017-02-09 15:57:31 +0300660### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300661
662What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300663we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300664
Roman Elizarov419a6c82017-02-09 18:36:22 +0300665Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
666that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
667does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300668that represents a promise to provide a result later. You can use `.await()` on a deferred value to get its eventual result,
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300669but `Deferred` is also a `Job`, so you can cancel it if needed.
670
671```kotlin
672fun main(args: Array<String>) = runBlocking<Unit> {
673 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300674 val one = async { doSomethingUsefulOne() }
675 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300676 println("The answer is ${one.await() + two.await()}")
677 }
678 println("Completed in $time ms")
679}
680```
681
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300682> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300683
684It produces something like this:
685
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300686```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300687The answer is 42
688Completed in 1017 ms
689```
690
Roman Elizarov35d2c342017-07-20 14:54:39 +0300691<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300692
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300693This is twice as fast, because we have concurrent execution of two coroutines.
694Note, that concurrency with coroutines is always explicit.
695
Roman Elizarov32d95322017-02-09 15:57:31 +0300696### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300697
Roman Elizarov66f018c2017-09-29 21:39:03 +0300698There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300699It starts coroutine only when its result is needed by some
700[await][Deferred.await] or if a [start][Job.start] function
Sahil Lone52a0ec02018-07-19 18:55:35 +0200701is invoked. Run the following example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300702
703```kotlin
704fun main(args: Array<String>) = runBlocking<Unit> {
705 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300706 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
707 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Sahil Lone52a0ec02018-07-19 18:55:35 +0200708 // some computation
709 one.start() // start the first one
710 two.start() // start the second one
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300711 println("The answer is ${one.await() + two.await()}")
712 }
713 println("Completed in $time ms")
714}
715```
716
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300717> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300718
719It produces something like this:
720
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300721```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300722The answer is 42
Sahil Lone52a0ec02018-07-19 18:55:35 +0200723Completed in 1017 ms
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300724```
725
Roman Elizarov35d2c342017-07-20 14:54:39 +0300726<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300727
Sahil Lone52a0ec02018-07-19 18:55:35 +0200728So, here the two coroutines are defined but not executed as in the previous example, but the control is given to
729the programmer about when exactly to start the execution by calling [start][Job.start] on it. We first
730start `one`, then start `two`, and then await for the individual coroutines to finish.
731
732Note, that if we have called [await][Deferred.await] in `println` and omitted [start][Job.start] on individual
733coroutines, then we would have got the sequential behaviour as [await][Deferred.await] starts the coroutine
734execution and waits for the execution to finish, which is not the intended use-case for laziness.
735The use-case for `async(start = CoroutineStart.LAZY)` is a replacement for the
736standard `lazy` function in cases when computation of the value involves suspending functions.
Roman Elizarov32d95322017-02-09 15:57:31 +0300737
738### Async-style functions
739
740We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300741_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100742"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
743to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300744
745```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100746// The result type of somethingUsefulOneAsync is Deferred<Int>
747fun somethingUsefulOneAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300748 doSomethingUsefulOne()
749}
750
Marcin Moskała7e94e702018-01-29 18:39:02 +0100751// The result type of somethingUsefulTwoAsync is Deferred<Int>
752fun somethingUsefulTwoAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300753 doSomethingUsefulTwo()
754}
755```
756
Marcin Moskała7e94e702018-01-29 18:39:02 +0100757Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300758However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
759with the invoking code.
760
761The following example shows their use outside of coroutine:
762
763```kotlin
764// note, that we don't have `runBlocking` to the right of `main` in this example
765fun main(args: Array<String>) {
766 val time = measureTimeMillis {
767 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100768 val one = somethingUsefulOneAsync()
769 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300770 // but waiting for a result must involve either suspending or blocking.
771 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
772 runBlocking {
773 println("The answer is ${one.await() + two.await()}")
774 }
775 }
776 println("Completed in $time ms")
777}
778```
779
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300780> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300781
Roman Elizarov35d2c342017-07-20 14:54:39 +0300782<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300783The answer is 42
784Completed in 1085 ms
785-->
786
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300787## Coroutine context and dispatchers
788
Roman Elizarov66f018c2017-09-29 21:39:03 +0300789Coroutines always execute in some context which is represented by the value of
790[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
791type, defined in the Kotlin standard library.
792
793The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
794which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300795
796### Dispatchers and threads
797
Roman Elizarov66f018c2017-09-29 21:39:03 +0300798Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300799the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +0300800to a specific thread, dispatch it to a thread pool, or let it run unconfined.
801
802All coroutines builders like [launch] and [async] accept an optional
803[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
804parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
805
806Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300807
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300808<!--- INCLUDE
809import kotlin.coroutines.experimental.*
810-->
811
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300812```kotlin
813fun main(args: Array<String>) = runBlocking<Unit> {
814 val jobs = arrayListOf<Job>()
815 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300816 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300817 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300818 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
819 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300820 }
821 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300822 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300823 }
824 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300825 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300826 }
827 jobs.forEach { it.join() }
828}
829```
830
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300831> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300832
833It produces the following output (maybe in different order):
834
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300835```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300836 'Unconfined': I'm working in thread main
837 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
838 'newSTC': I'm working in thread MyOwnThread
839'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300840```
841
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300842<!--- TEST LINES_START_UNORDERED -->
843
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800844The default dispatcher that we've used in previous sections is representend by [DefaultDispatcher], which
Roman Elizarov66f018c2017-09-29 21:39:03 +0300845is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same
Charles Muchenefa13beb2018-01-08 16:56:54 +0300846as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300847
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300848The difference between parent
849[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html) and
Roman Elizarov43e3af72017-07-21 16:01:31 +0300850[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300851
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800852Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource.
853In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
854function, or stored in a top-level variable and reused throughout the application.
855
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300856### Unconfined vs confined dispatcher
857
Roman Elizarov419a6c82017-02-09 18:36:22 +0300858The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300859first suspension point. After suspension it resumes in the thread that is fully determined by the
860suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
861consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
862
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300863On the other side,
864[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
865property, that is available inside any coroutine, is a reference to a context of this particular coroutine.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300866This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
867is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300868this thread with a predictable FIFO scheduling.
869
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300870<!--- INCLUDE
871import kotlin.coroutines.experimental.*
872-->
873
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300874```kotlin
875fun main(args: Array<String>) = runBlocking<Unit> {
876 val jobs = arrayListOf<Job>()
877 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300878 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300879 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300880 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300881 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300882 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
883 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300884 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300885 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300886 }
887 jobs.forEach { it.join() }
888}
889```
890
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300891> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300892
893Produces the output:
894
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300895```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300896 'Unconfined': I'm working in thread main
897'coroutineContext': I'm working in thread main
898 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
899'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300900```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300901
902<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300903
Roman Elizarov43e3af72017-07-21 16:01:31 +0300904So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
905in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
906function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300907
908### Debugging coroutines and threads
909
Roman Elizarov419a6c82017-02-09 18:36:22 +0300910Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
Roman Elizarov66f018c2017-09-29 21:39:03 +0300911with a default multi-threaded dispatcher. Even with a single-threaded dispatcher it might be hard to
paolopb019b102018-06-09 16:42:24 +0000912figure out what coroutine was doing, where, and when. The common approach to debugging applications with
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300913threads is to print the thread name in the log file on each log statement. This feature is universally supported
914by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
915`kotlinx.coroutines` includes debugging facilities to make it easier.
916
917Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
918
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300919<!--- INCLUDE
920import kotlin.coroutines.experimental.*
921-->
922
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300923```kotlin
924fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
925
926fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300927 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300928 log("I'm computing a piece of the answer")
929 6
930 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300931 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300932 log("I'm computing another piece of the answer")
933 7
934 }
935 log("The answer is ${a.await() * b.await()}")
936}
937```
938
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300939> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300940
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300941There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300942and two coroutines computing deferred values `a` (#2) and `b` (#3).
943They are all executing in the context of `runBlocking` and are confined to the main thread.
944The output of this code is:
945
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300946```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300947[main @coroutine#2] I'm computing a piece of the answer
948[main @coroutine#3] I'm computing another piece of the answer
949[main @coroutine#1] The answer is 42
950```
951
Kirill Timofeeva5186962017-10-25 14:25:47 +0300952<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300953
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300954The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
955thread, but the identifier of the currently executing coroutine is appended to it. This identifier
956is consecutively assigned to all created coroutines when debugging mode is turned on.
957
Roman Elizarov419a6c82017-02-09 18:36:22 +0300958You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300959
960### Jumping between threads
961
962Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
963
964```kotlin
965fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
966
967fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800968 newSingleThreadContext("Ctx1").use { ctx1 ->
969 newSingleThreadContext("Ctx2").use { ctx2 ->
970 runBlocking(ctx1) {
971 log("Started in ctx1")
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300972 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800973 log("Working in ctx2")
974 }
975 log("Back to ctx1")
976 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300977 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300978 }
979}
980```
981
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300982> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300983
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800984It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300985the other one is using [withContext] function to change a context of a coroutine while still staying in the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300986same coroutine as you can see in the output below:
987
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300988```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300989[Ctx1 @coroutine#1] Started in ctx1
990[Ctx2 @coroutine#1] Working in ctx2
991[Ctx1 @coroutine#1] Back to ctx1
992```
993
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300994<!--- TEST -->
995
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800996
Artsiom Chapialioue185ed62018-06-03 19:34:22 -0400997Note, that this example also uses `use` function from the Kotlin standard library to release threads that
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800998are created with [newSingleThreadContext] when they are no longer needed.
999
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001000### Job in the context
1001
Roman Elizarov66f018c2017-09-29 21:39:03 +03001002The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001003using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001004
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001005<!--- INCLUDE
1006import kotlin.coroutines.experimental.*
1007-->
1008
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001009```kotlin
1010fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001011 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001012}
1013```
1014
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001015> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001016
Roman Elizarov66f018c2017-09-29 21:39:03 +03001017It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001018
1019```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001020My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001021```
1022
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001023<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001024
Roman Elizarov43e3af72017-07-21 16:01:31 +03001025So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001026`coroutineContext[Job]?.isActive == true`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001027
1028### Children of a coroutine
1029
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001030When
1031[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
1032of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +03001033the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001034a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1035are recursively cancelled, too.
1036
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001037<!--- INCLUDE
1038import kotlin.coroutines.experimental.*
1039-->
1040
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001041```kotlin
1042fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001043 // launch a coroutine to process some kind of incoming request
1044 val request = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001045 // it spawns two other jobs, one with its separate context
Roman Elizarov66f018c2017-09-29 21:39:03 +03001046 val job1 = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001047 println("job1: I have my own context and execute independently!")
1048 delay(1000)
1049 println("job1: I am not affected by cancellation of the request")
1050 }
1051 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001052 val job2 = launch(coroutineContext) {
Roman Elizarov74619c12017-11-09 10:32:15 +03001053 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001054 println("job2: I am a child of the request coroutine")
1055 delay(1000)
1056 println("job2: I will not execute this line if my parent request is cancelled")
1057 }
1058 // request completes when both its sub-jobs complete:
1059 job1.join()
1060 job2.join()
1061 }
1062 delay(500)
1063 request.cancel() // cancel processing of the request
1064 delay(1000) // delay a second to see what happens
1065 println("main: Who has survived request cancellation?")
1066}
1067```
1068
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001069> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001070
1071The output of this code is:
1072
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001073```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001074job1: I have my own context and execute independently!
1075job2: I am a child of the request coroutine
1076job1: I am not affected by cancellation of the request
1077main: Who has survived request cancellation?
1078```
1079
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001080<!--- TEST -->
1081
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001082### Combining contexts
1083
Roman Elizarov66f018c2017-09-29 21:39:03 +03001084Coroutine contexts can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +03001085of the context on the left-hand side. For example, a [Job] of the parent coroutine can be inherited, while
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001086its dispatcher replaced:
1087
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001088<!--- INCLUDE
1089import kotlin.coroutines.experimental.*
1090-->
1091
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001092```kotlin
1093fun main(args: Array<String>) = runBlocking<Unit> {
1094 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +03001095 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001096 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +03001097 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001098 println("job: I am a child of the request coroutine, but with a different dispatcher")
1099 delay(1000)
1100 println("job: I will not execute this line if my parent request is cancelled")
1101 }
1102 job.join() // request completes when its sub-job completes
1103 }
1104 delay(500)
1105 request.cancel() // cancel processing of the request
1106 delay(1000) // delay a second to see what happens
1107 println("main: Who has survived request cancellation?")
1108}
1109```
1110
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001111> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001112
1113The expected outcome of this code is:
1114
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001115```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001116job: I am a child of the request coroutine, but with a different dispatcher
1117main: Who has survived request cancellation?
1118```
1119
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001120<!--- TEST -->
1121
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001122### Parental responsibilities
1123
1124A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001125all the children it launches and it does not have to use [Job.join] to wait for them at the end:
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001126
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001127<!--- INCLUDE
1128import kotlin.coroutines.experimental.*
1129-->
1130
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001131```kotlin
1132fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001133 // launch a coroutine to process some kind of incoming request
1134 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001135 repeat(3) { i -> // launch a few children jobs
1136 launch(coroutineContext) {
1137 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1138 println("Coroutine $i is done")
1139 }
1140 }
1141 println("request: I'm done and I don't explicitly join my children that are still active")
1142 }
1143 request.join() // wait for completion of the request, including all its children
1144 println("Now processing of the request is complete")
1145}
1146```
1147
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001148> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-08.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001149
1150The result is going to be:
1151
1152```text
1153request: I'm done and I don't explicitly join my children that are still active
1154Coroutine 0 is done
1155Coroutine 1 is done
1156Coroutine 2 is done
1157Now processing of the request is complete
1158```
1159
1160<!--- TEST -->
1161
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001162### Naming coroutines for debugging
1163
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001164Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001165coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1166or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001167[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1168is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001169
1170The following example demonstrates this concept:
1171
1172```kotlin
1173fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1174
1175fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1176 log("Started main coroutine")
1177 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001178 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001179 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001180 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001181 252
1182 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001183 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001184 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001185 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001186 6
1187 }
1188 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1189}
1190```
1191
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001192> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-09.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001193
1194The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1195
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001196```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001197[main @main#1] Started main coroutine
1198[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1199[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1200[main @main#1] The answer for v1 / v2 = 42
1201```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001202
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001203<!--- TEST FLEXIBLE_THREAD -->
1204
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001205### Cancellation via explicit job
1206
1207Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1208an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1209and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1210and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1211to avoid memory leaks.
1212
1213We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
Roman Elizarov88396732017-09-27 21:30:47 +03001214the lifecycle of our activity. A job instance is created using [Job()] factory function
Roman Elizarove8f694e2017-11-28 10:12:00 +03001215as the following example shows. For convenience, rather than using `launch(coroutineContext + job)` expression,
1216we can write `launch(coroutineContext, parent = job)` to make explicit the fact that the parent job is being used.
1217
1218Now, a single invocation of [Job.cancel] cancels all the children we've launched.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001219Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1220this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001221
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001222<!--- INCLUDE
1223import kotlin.coroutines.experimental.*
1224-->
1225
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001226```kotlin
1227fun main(args: Array<String>) = runBlocking<Unit> {
1228 val job = Job() // create a job object to manage our lifecycle
1229 // now launch ten coroutines for a demo, each working for a different time
1230 val coroutines = List(10) { i ->
1231 // they are all children of our job object
Roman Elizarove8f694e2017-11-28 10:12:00 +03001232 launch(coroutineContext, parent = job) { // we use the context of main runBlocking thread, but with our parent job
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001233 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001234 println("Coroutine $i is done")
1235 }
1236 }
1237 println("Launched ${coroutines.size} coroutines")
1238 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001239 println("Cancelling the job!")
1240 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001241}
1242```
1243
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001244> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-10.kt)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001245
1246The output of this example is:
1247
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001248```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001249Launched 10 coroutines
1250Coroutine 0 is done
1251Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001252Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001253```
1254
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001255<!--- TEST -->
1256
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001257As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001258by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001259application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001260and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1261since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1262resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001263
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001264## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001265
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001266Deferred values provide a convenient way to transfer a single value between coroutines.
1267Channels provide a way to transfer a stream of values.
1268
1269<!--- INCLUDE .*/example-channel-([0-9]+).kt
1270import kotlinx.coroutines.experimental.channels.*
1271-->
1272
1273### Channel basics
1274
Roman Elizarov419a6c82017-02-09 18:36:22 +03001275A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1276instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1277a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001278
1279```kotlin
1280fun main(args: Array<String>) = runBlocking<Unit> {
1281 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001282 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001283 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1284 for (x in 1..5) channel.send(x * x)
1285 }
1286 // here we print five received integers:
1287 repeat(5) { println(channel.receive()) }
1288 println("Done!")
1289}
1290```
1291
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001292> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-01.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001293
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001294The output of this code is:
1295
1296```text
12971
12984
12999
130016
130125
1302Done!
1303```
1304
1305<!--- TEST -->
1306
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001307### Closing and iteration over channels
1308
1309Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1310On the receiver side it is convenient to use a regular `for` loop to receive elements
1311from the channel.
1312
Roman Elizarov419a6c82017-02-09 18:36:22 +03001313Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001314The iteration stops as soon as this close token is received, so there is a guarantee
1315that all previously sent elements before the close are received:
1316
1317```kotlin
1318fun main(args: Array<String>) = runBlocking<Unit> {
1319 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001320 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001321 for (x in 1..5) channel.send(x * x)
1322 channel.close() // we're done sending
1323 }
1324 // here we print received values using `for` loop (until the channel is closed)
1325 for (y in channel) println(y)
1326 println("Done!")
1327}
1328```
1329
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001330> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001331
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001332<!--- TEST
13331
13344
13359
133616
133725
1338Done!
1339-->
1340
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001341### Building channel producers
1342
Roman Elizarova5e653f2017-02-13 13:49:55 +03001343The pattern where a coroutine is producing a sequence of elements is quite common.
1344This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001345You could abstract such a producer into a function that takes channel as its parameter, but this goes contrary
Roman Elizarova5e653f2017-02-13 13:49:55 +03001346to common sense that results must be returned from functions.
1347
Roman Elizarov86349be2017-03-17 16:47:37 +03001348There is a convenience coroutine builder named [produce] that makes it easy to do it right on producer side,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001349and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001350
1351```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001352fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001353 for (x in 1..5) send(x * x)
1354}
1355
1356fun main(args: Array<String>) = runBlocking<Unit> {
1357 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001358 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001359 println("Done!")
1360}
1361```
1362
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001363> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-03.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001364
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001365<!--- TEST
13661
13674
13689
136916
137025
1371Done!
1372-->
1373
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001374### Pipelines
1375
Roman Elizarov66f018c2017-09-29 21:39:03 +03001376A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001377
1378```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001379fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001380 var x = 1
1381 while (true) send(x++) // infinite stream of integers starting from 1
1382}
1383```
1384
Roman Elizarova5e653f2017-02-13 13:49:55 +03001385And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001386In the below example the numbers are just squared:
1387
1388```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001389fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001390 for (x in numbers) send(x * x)
1391}
1392```
1393
Roman Elizarova5e653f2017-02-13 13:49:55 +03001394The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001395
1396```kotlin
1397fun main(args: Array<String>) = runBlocking<Unit> {
1398 val numbers = produceNumbers() // produces integers from 1 and on
1399 val squares = square(numbers) // squares integers
1400 for (i in 1..5) println(squares.receive()) // print first five
1401 println("Done!") // we are done
1402 squares.cancel() // need to cancel these coroutines in a larger app
1403 numbers.cancel()
1404}
1405```
1406
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001407> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-04.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001408
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001409<!--- TEST
14101
14114
14129
141316
141425
1415Done!
1416-->
1417
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001418We don't have to cancel these coroutines in this example app, because
1419[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1420but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1421Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001422[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001423
1424### Prime numbers with pipeline
1425
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001426Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001427of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001428explicit `context` parameter and pass it to [produce] builder,
1429so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001430
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001431<!--- INCLUDE
1432import kotlin.coroutines.experimental.*
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001433-->
1434
1435```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001436fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001437 var x = start
1438 while (true) send(x++) // infinite stream of integers from start
1439}
1440```
1441
1442The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1443that are divisible by the given prime number:
1444
1445```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001446fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001447 for (x in numbers) if (x % prime != 0) send(x)
1448}
1449```
1450
1451Now we build our pipeline by starting a stream of numbers from 2, taking a prime number from the current channel,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001452and launching new pipeline stage for each prime number found:
1453
1454```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001455numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001456```
1457
1458The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001459running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001460children of the main [runBlocking] coroutine in its
1461[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html),
1462we don't have to keep an explicit list of all the coroutines we have started.
Roman Elizarov3e387b82017-12-04 13:49:11 +03001463We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
1464extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001465
1466```kotlin
1467fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001468 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001469 for (i in 1..10) {
1470 val prime = cur.receive()
1471 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001472 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001473 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001474 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001475}
1476```
1477
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001478> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-05.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001479
1480The output of this code is:
1481
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001482```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030014832
14843
14855
14867
148711
148813
148917
149019
149123
149229
1493```
1494
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001495<!--- TEST -->
1496
Roman Elizarov66f018c2017-09-29 21:39:03 +03001497Note, that you can build the same pipeline using
1498[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1499coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001500Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001501`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1502However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1503multiple CPU cores if you run it in [CommonPool] context.
1504
Roman Elizarova5e653f2017-02-13 13:49:55 +03001505Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001506other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
SashaKhyzhuncb2998b2018-07-31 11:51:35 +03001507built using `buildSequence`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001508`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001509
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001510### Fan-out
1511
1512Multiple coroutines may receive from the same channel, distributing work between themselves.
1513Let us start with a producer coroutine that is periodically producing integers
1514(ten numbers per second):
1515
1516```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001517fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001518 var x = 1 // start from 1
1519 while (true) {
1520 send(x++) // produce next
1521 delay(100) // wait 0.1s
1522 }
1523}
1524```
1525
1526Then we can have several processor coroutines. In this example, they just print their id and
1527received number:
1528
1529```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001530fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
bill58c61c72018-06-21 17:24:08 -05001531 for (msg in channel) {
1532 println("Processor #$id received $msg")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001533 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001534}
1535```
1536
Roman Elizarov35d2c342017-07-20 14:54:39 +03001537Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001538
1539```kotlin
1540fun main(args: Array<String>) = runBlocking<Unit> {
1541 val producer = produceNumbers()
1542 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001543 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001544 producer.cancel() // cancel producer coroutine and thus kill them all
1545}
1546```
1547
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001548> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-06.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001549
1550The output will be similar to the the following one, albeit the processor ids that receive
1551each specific integer may be different:
1552
1553```
1554Processor #2 received 1
1555Processor #4 received 2
1556Processor #0 received 3
1557Processor #1 received 4
1558Processor #3 received 5
1559Processor #2 received 6
1560Processor #4 received 7
1561Processor #0 received 8
1562Processor #1 received 9
1563Processor #3 received 10
1564```
1565
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001566<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1567
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001568Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1569over the channel that processor coroutines are doing.
1570
Roman Elizarov1ce6c0b2018-06-28 10:37:20 +03001571Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
1572Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
1573coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
1574always consumes (cancels) the underlying channel on its normal or abnormal termination.
1575
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001576### Fan-in
1577
1578Multiple coroutines may send to the same channel.
1579For example, let us have a channel of strings, and a suspending function that
1580repeatedly sends a specified string to this channel with a specified delay:
1581
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001582<!--- INCLUDE
1583import kotlin.coroutines.experimental.*
1584-->
1585
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001586```kotlin
1587suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1588 while (true) {
1589 delay(time)
1590 channel.send(s)
1591 }
1592}
1593```
1594
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001595Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001596(in this example we launch them in the context of the main thread as main coroutine's children):
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001597
1598```kotlin
1599fun main(args: Array<String>) = runBlocking<Unit> {
1600 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001601 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1602 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001603 repeat(6) { // receive first six
1604 println(channel.receive())
1605 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001606 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001607}
1608```
1609
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001610> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-07.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001611
1612The output is:
1613
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001614```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001615foo
1616foo
1617BAR!
1618foo
1619foo
1620BAR!
1621```
1622
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001623<!--- TEST -->
1624
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001625### Buffered channels
1626
1627The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1628meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1629if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001630
Roman Elizarov88396732017-09-27 21:30:47 +03001631Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001632specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1633similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1634
1635Take a look at the behavior of the following code:
1636
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001637<!--- INCLUDE
1638import kotlin.coroutines.experimental.*
1639-->
1640
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001641```kotlin
1642fun main(args: Array<String>) = runBlocking<Unit> {
1643 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001644 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001645 repeat(10) {
1646 println("Sending $it") // print before sending each element
1647 channel.send(it) // will suspend when buffer is full
1648 }
1649 }
1650 // don't receive anything... just wait....
1651 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001652 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001653}
1654```
1655
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001656> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001657
1658It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1659
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001660```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001661Sending 0
1662Sending 1
1663Sending 2
1664Sending 3
1665Sending 4
1666```
1667
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001668<!--- TEST -->
1669
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001670The first four elements are added to the buffer and the sender suspends when trying to send the fifth one.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001671
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001672### Ticker channels
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001673
Roman Elizarovb5328a72018-06-06 18:31:21 +03001674Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
1675Though it may seem to be useless standalone, it is a useful building block to create complex time-based [produce]
Roman Elizarov0c090ed2018-06-29 19:51:07 +03001676pipelines and operators that do windowing and other time-dependent processing.
Roman Elizarovb5328a72018-06-06 18:31:21 +03001677Ticker channel can be used in [select] to perform "on tick" action.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001678
Roman Elizarovb5328a72018-06-06 18:31:21 +03001679To create such channel use a factory method [ticker].
1680To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001681
1682Now let's see how it works in practice:
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001683
1684```kotlin
1685fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovb5328a72018-06-06 18:31:21 +03001686 val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001687 var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
paolop1d6e4932018-07-02 08:46:34 +00001688 println("Initial element is available immediately: $nextElement") // initial delay hasn't passed yet
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001689
paolop1d6e4932018-07-02 08:46:34 +00001690 nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements has 100ms delay
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001691 println("Next element is not ready in 50 ms: $nextElement")
1692
Roman Elizarovb5328a72018-06-06 18:31:21 +03001693 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001694 println("Next element is ready in 100 ms: $nextElement")
1695
1696 // Emulate large consumption delays
Roman Elizarovb5328a72018-06-06 18:31:21 +03001697 println("Consumer pauses for 150ms")
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001698 delay(150)
1699 // Next element is available immediately
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001700 nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001701 println("Next element is available immediately after large consumer delay: $nextElement")
1702 // Note that the pause between `receive` calls is taken into account and next element arrives faster
Roman Elizarovb5328a72018-06-06 18:31:21 +03001703 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001704 println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
1705
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001706 tickerChannel.cancel() // indicate that no more elements are needed
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001707}
1708```
1709
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001710> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-10.kt)
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001711
1712It prints following lines:
1713
1714```text
1715Initial element is available immediately: kotlin.Unit
1716Next element is not ready in 50 ms: null
1717Next element is ready in 100 ms: kotlin.Unit
Roman Elizarovb5328a72018-06-06 18:31:21 +03001718Consumer pauses for 150ms
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001719Next element is available immediately after large consumer delay: kotlin.Unit
1720Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
1721```
1722
1723<!--- TEST -->
1724
Roman Elizarovb5328a72018-06-06 18:31:21 +03001725Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
1726delay if a pause occurs, trying to maintain a fixed rate of produced elements.
1727
Roman Elizarov0c090ed2018-06-29 19:51:07 +03001728Optionally, a `mode` parameter equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
Roman Elizarovb5328a72018-06-06 18:31:21 +03001729delay between elements.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001730
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001731### Channels are fair
1732
1733Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1734multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1735gets the element. In the following example two coroutines "ping" and "pong" are
1736receiving the "ball" object from the shared "table" channel.
1737
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001738<!--- INCLUDE
1739import kotlin.coroutines.experimental.*
1740-->
1741
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001742```kotlin
1743data class Ball(var hits: Int)
1744
1745fun main(args: Array<String>) = runBlocking<Unit> {
1746 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001747 launch(coroutineContext) { player("ping", table) }
1748 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001749 table.send(Ball(0)) // serve the ball
1750 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001751 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001752}
1753
1754suspend fun player(name: String, table: Channel<Ball>) {
1755 for (ball in table) { // receive the ball in a loop
1756 ball.hits++
1757 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001758 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001759 table.send(ball) // send the ball back
1760 }
1761}
1762```
1763
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001764> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-09.kt)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001765
1766The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1767coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1768received by the "pong" coroutine, because it was already waiting for it:
1769
1770```text
1771ping Ball(hits=1)
1772pong Ball(hits=2)
1773ping Ball(hits=3)
1774pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001775```
1776
1777<!--- TEST -->
1778
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001779Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
1780that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
1781
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001782## Shared mutable state and concurrency
1783
Roman Elizarov66f018c2017-09-29 21:39:03 +03001784Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001785all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1786Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1787but others are unique.
1788
1789### The problem
1790
Roman Elizarov1e459602017-02-27 11:05:17 +03001791Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1792We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001793
Roman Elizarov1e459602017-02-27 11:05:17 +03001794<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001795import java.util.concurrent.atomic.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001796-->
1797
Roman Elizarov1e459602017-02-27 11:05:17 +03001798<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001799import kotlinx.coroutines.experimental.sync.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001800-->
1801
Roman Elizarov1e459602017-02-27 11:05:17 +03001802<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001803import kotlinx.coroutines.experimental.channels.*
1804-->
1805
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001806<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
1807import kotlin.system.*
1808import kotlin.coroutines.experimental.*
1809-->
1810
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001811```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001812suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1813 val n = 1000 // number of coroutines to launch
1814 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001815 val time = measureTimeMillis {
1816 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001817 launch(context) {
1818 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001819 }
1820 }
1821 jobs.forEach { it.join() }
1822 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001823 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001824}
1825```
1826
Roman Elizarov43e90112017-05-10 11:25:20 +03001827<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001828
Roman Elizarov1e459602017-02-27 11:05:17 +03001829We start with a very simple action that increments a shared mutable variable using
1830multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001831
1832```kotlin
1833var counter = 0
1834
1835fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001836 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001837 counter++
1838 }
1839 println("Counter = $counter")
1840}
1841```
1842
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001843> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001844
Roman Elizarov1e459602017-02-27 11:05:17 +03001845<!--- TEST LINES_START
1846Completed 1000000 actions in
1847Counter =
1848-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001849
Roman Elizarov1e459602017-02-27 11:05:17 +03001850What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1851increment the `counter` concurrently from multiple threads without any synchronization.
1852
Roman Elizarov43e90112017-05-10 11:25:20 +03001853> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1854`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1855following change:
1856
1857```kotlin
1858val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1859var counter = 0
1860
1861fun main(args: Array<String>) = runBlocking<Unit> {
1862 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1863 counter++
1864 }
1865 println("Counter = $counter")
1866}
1867```
1868
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001869> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt)
Roman Elizarov43e90112017-05-10 11:25:20 +03001870
1871<!--- TEST LINES_START
1872Completed 1000000 actions in
1873Counter =
1874-->
1875
Roman Elizarov1e459602017-02-27 11:05:17 +03001876### Volatiles are of no help
1877
1878There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1879
1880```kotlin
1881@Volatile // in Kotlin `volatile` is an annotation
1882var counter = 0
1883
1884fun main(args: Array<String>) = runBlocking<Unit> {
1885 massiveRun(CommonPool) {
1886 counter++
1887 }
1888 println("Counter = $counter")
1889}
1890```
1891
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001892> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001893
1894<!--- TEST LINES_START
1895Completed 1000000 actions in
1896Counter =
1897-->
1898
1899This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1900linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1901do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001902
1903### Thread-safe data structures
1904
1905The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1906linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1907operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001908In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001909
1910```kotlin
1911var counter = AtomicInteger()
1912
1913fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001914 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001915 counter.incrementAndGet()
1916 }
1917 println("Counter = ${counter.get()}")
1918}
1919```
1920
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001921> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001922
Roman Elizarov1e459602017-02-27 11:05:17 +03001923<!--- TEST ARBITRARY_TIME
1924Completed 1000000 actions in xxx ms
1925Counter = 1000000
1926-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001927
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001928This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1929standard data structures and basic operations on them. However, it does not easily scale to complex
1930state or to complex operations that do not have ready-to-use thread-safe implementations.
1931
Roman Elizarov1e459602017-02-27 11:05:17 +03001932### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001933
Roman Elizarov1e459602017-02-27 11:05:17 +03001934_Thread confinement_ is an approach to the problem of shared mutable state where all access to the particular shared
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001935state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1936the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1937single-threaded context:
1938
1939```kotlin
1940val counterContext = newSingleThreadContext("CounterContext")
1941var counter = 0
1942
1943fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001944 massiveRun(CommonPool) { // run each coroutine in CommonPool
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001945 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001946 counter++
1947 }
1948 }
1949 println("Counter = $counter")
1950}
1951```
1952
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001953> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001954
Roman Elizarov1e459602017-02-27 11:05:17 +03001955<!--- TEST ARBITRARY_TIME
1956Completed 1000000 actions in xxx ms
1957Counter = 1000000
1958-->
1959
1960This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001961from multi-threaded `CommonPool` context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03001962
1963### Thread confinement coarse-grained
1964
1965In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1966are confined to the single thread. The following example does it like that, running each coroutine in
1967the single-threaded context to start with.
1968
1969```kotlin
1970val counterContext = newSingleThreadContext("CounterContext")
1971var counter = 0
1972
1973fun main(args: Array<String>) = runBlocking<Unit> {
1974 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1975 counter++
1976 }
1977 println("Counter = $counter")
1978}
1979```
1980
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001981> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-05.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001982
1983<!--- TEST ARBITRARY_TIME
1984Completed 1000000 actions in xxx ms
1985Counter = 1000000
1986-->
1987
1988This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001989
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001990### Mutual exclusion
1991
1992Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1993that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1994Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
paolop1d6e4932018-07-02 08:46:34 +00001995delimit a critical section. The key difference is that `Mutex.lock()` is a suspending function. It does not block a thread.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001996
Roman Elizarov88396732017-09-27 21:30:47 +03001997There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001998`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
1999
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002000```kotlin
2001val mutex = Mutex()
2002var counter = 0
2003
2004fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002005 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002006 mutex.withLock {
2007 counter++
2008 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002009 }
2010 println("Counter = $counter")
2011}
2012```
2013
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002014> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002015
Roman Elizarov1e459602017-02-27 11:05:17 +03002016<!--- TEST ARBITRARY_TIME
2017Completed 1000000 actions in xxx ms
2018Counter = 1000000
2019-->
2020
2021The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
2022where you absolutely must modify some shared state periodically, but there is no natural thread that this state
2023is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002024
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002025### Actors
2026
paolop1d6e4932018-07-02 08:46:34 +00002027An [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,
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002028and a channel to communicate with other coroutines. A simple actor can be written as a function,
2029but an actor with a complex state is better suited for a class.
2030
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002031There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
2032scope to receive messages from and combines the send channel into the resulting job object, so that a
2033single reference to the actor can be carried around as its handle.
2034
Roman Elizarov256812a2017-07-22 01:00:30 +03002035The first step of using an actor is to define a class of messages that an actor is going to process.
2036Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
2037We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
2038to get its value. The later needs to send a response. A [CompletableDeferred] communication
2039primitive, that represents a single value that will be known (communicated) in the future,
2040is used here for that purpose.
2041
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002042```kotlin
2043// Message types for counterActor
2044sealed class CounterMsg
2045object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03002046class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
2047```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002048
Roman Elizarov256812a2017-07-22 01:00:30 +03002049Then we define a function that launches an actor using an [actor] coroutine builder:
2050
2051```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002052// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03002053fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002054 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002055 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002056 when (msg) {
2057 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03002058 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002059 }
2060 }
2061}
Roman Elizarov256812a2017-07-22 01:00:30 +03002062```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002063
Roman Elizarov256812a2017-07-22 01:00:30 +03002064The main code is straightforward:
2065
2066```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002067fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002068 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03002069 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002070 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002071 }
Roman Elizarov256812a2017-07-22 01:00:30 +03002072 // send a message to get a counter value from an actor
2073 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002074 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03002075 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002076 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002077}
2078```
2079
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002080> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002081
Roman Elizarov1e459602017-02-27 11:05:17 +03002082<!--- TEST ARBITRARY_TIME
2083Completed 1000000 actions in xxx ms
2084Counter = 1000000
2085-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002086
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002087It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002088a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
paolop1d6e4932018-07-02 08:46:34 +00002089works 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).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002090
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002091Actor is more efficient than locking under load, because in this case it always has work to do and it does not
2092have to switch to a different context at all.
2093
2094> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
2095 with the channel that it receives messages from, while a producer is associated with the channel that it
2096 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03002097
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002098## Select expression
2099
Roman Elizarova84730b2017-02-22 11:58:50 +03002100Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002101the first one that becomes available.
2102
2103<!--- INCLUDE .*/example-select-([0-9]+).kt
2104import kotlinx.coroutines.experimental.channels.*
2105import kotlinx.coroutines.experimental.selects.*
2106-->
2107
2108### Selecting from channels
2109
Roman Elizarov57857202017-03-02 23:17:25 +03002110Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2111
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002112<!--- INCLUDE
2113import kotlinx.coroutines.experimental.*
2114import kotlin.coroutines.experimental.*
Roman Elizarov57857202017-03-02 23:17:25 +03002115-->
2116
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002117```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002118fun fizz(context: CoroutineContext) = produce<String>(context) {
2119 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002120 delay(300)
2121 send("Fizz")
2122 }
2123}
2124```
2125
Roman Elizarov57857202017-03-02 23:17:25 +03002126And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002127
2128```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002129fun buzz(context: CoroutineContext) = produce<String>(context) {
2130 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002131 delay(500)
2132 send("Buzz!")
2133 }
2134}
2135```
2136
2137Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2138other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002139[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002140
2141```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002142suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002143 select<Unit> { // <Unit> means that this select expression does not produce any result
2144 fizz.onReceive { value -> // this is the first select clause
2145 println("fizz -> '$value'")
2146 }
2147 buzz.onReceive { value -> // this is the second select clause
2148 println("buzz -> '$value'")
2149 }
2150 }
2151}
2152```
2153
Roman Elizarov57857202017-03-02 23:17:25 +03002154Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002155
2156```kotlin
2157fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002158 val fizz = fizz(coroutineContext)
2159 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002160 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002161 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002162 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002163 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002164}
2165```
2166
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002167> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-01.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002168
2169The result of this code is:
2170
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002171```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002172fizz -> 'Fizz'
2173buzz -> 'Buzz!'
2174fizz -> 'Fizz'
2175fizz -> 'Fizz'
2176buzz -> 'Buzz!'
2177fizz -> 'Fizz'
2178buzz -> 'Buzz!'
2179```
2180
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002181<!--- TEST -->
2182
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002183### Selecting on close
2184
paolop1d6e4932018-07-02 08:46:34 +00002185The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
2186`select` to throw an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002187specific action when the channel is closed. The following example also shows that `select` is an expression that returns
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002188the result of its selected clause:
2189
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002190<!--- INCLUDE
2191import kotlin.coroutines.experimental.*
2192-->
2193
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002194```kotlin
2195suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2196 select<String> {
2197 a.onReceiveOrNull { value ->
2198 if (value == null)
2199 "Channel 'a' is closed"
2200 else
2201 "a -> '$value'"
2202 }
2203 b.onReceiveOrNull { value ->
2204 if (value == null)
2205 "Channel 'b' is closed"
2206 else
2207 "b -> '$value'"
2208 }
2209 }
2210```
2211
Roman Elizarova84730b2017-02-22 11:58:50 +03002212Let's use it with channel `a` that produces "Hello" string four times and
2213channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002214
2215```kotlin
2216fun main(args: Array<String>) = runBlocking<Unit> {
2217 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002218 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002219 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002220 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002221 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002222 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002223 }
2224 repeat(8) { // print first eight results
2225 println(selectAorB(a, b))
2226 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002227 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002228}
2229```
2230
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002231> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-02.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002232
Roman Elizarova84730b2017-02-22 11:58:50 +03002233The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002234
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002235```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002236a -> 'Hello 0'
2237a -> 'Hello 1'
2238b -> 'World 0'
2239a -> 'Hello 2'
2240a -> 'Hello 3'
2241b -> 'World 1'
2242Channel 'a' is closed
2243Channel 'a' is closed
2244```
2245
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002246<!--- TEST -->
2247
Roman Elizarova84730b2017-02-22 11:58:50 +03002248There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002249
2250First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2251the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002252being the first clause in select, wins. However, because we are using unbuffered channel, the `a` gets suspended from
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002253time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2254
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002255The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002256channel is already closed.
2257
2258### Selecting to send
2259
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002260Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002261with a biased nature of selection.
2262
Roman Elizarova84730b2017-02-22 11:58:50 +03002263Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002264the consumers on its primary channel cannot keep up with it:
2265
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002266<!--- INCLUDE
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002267import kotlin.coroutines.experimental.*
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002268-->
2269
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002270```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002271fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002272 for (num in 1..10) { // produce 10 numbers from 1 to 10
2273 delay(100) // every 100 ms
2274 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002275 onSend(num) {} // Send to the primary channel
2276 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002277 }
2278 }
2279}
2280```
2281
2282Consumer is going to be quite slow, taking 250 ms to process each number:
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002283
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002284```kotlin
2285fun main(args: Array<String>) = runBlocking<Unit> {
2286 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002287 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002288 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002289 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002290 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002291 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002292 delay(250) // let us digest the consumed number properly, do not hurry
2293 }
2294 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002295 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002296}
2297```
2298
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002299> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-03.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002300
2301So let us see what happens:
2302
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002303```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002304Consuming 1
2305Side channel has 2
2306Side channel has 3
2307Consuming 4
2308Side channel has 5
2309Side channel has 6
2310Consuming 7
2311Side channel has 8
2312Side channel has 9
2313Consuming 10
2314Done consuming
2315```
2316
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002317<!--- TEST -->
2318
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002319### Selecting deferred values
2320
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002321Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002322Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002323a random delay:
2324
2325<!--- INCLUDE .*/example-select-04.kt
2326import java.util.*
2327-->
2328
2329```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002330fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002331 delay(time.toLong())
2332 "Waited for $time ms"
2333}
2334```
2335
Roman Elizarova84730b2017-02-22 11:58:50 +03002336Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002337
2338```kotlin
2339fun asyncStringsList(): List<Deferred<String>> {
2340 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002341 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002342}
2343```
2344
Roman Elizarova84730b2017-02-22 11:58:50 +03002345Now the main function awaits for the first of them to complete and counts the number of deferred values
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002346that are still active. Note, that we've used here the fact that `select` expression is a Kotlin DSL,
Roman Elizarova84730b2017-02-22 11:58:50 +03002347so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2348of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002349
2350```kotlin
2351fun main(args: Array<String>) = runBlocking<Unit> {
2352 val list = asyncStringsList()
2353 val result = select<String> {
2354 list.withIndex().forEach { (index, deferred) ->
2355 deferred.onAwait { answer ->
2356 "Deferred $index produced answer '$answer'"
2357 }
2358 }
2359 }
2360 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002361 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002362 println("$countActive coroutines are still active")
2363}
2364```
2365
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002366> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-04.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002367
2368The output is:
2369
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002370```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002371Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300237211 coroutines are still active
2373```
2374
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002375<!--- TEST -->
2376
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002377### Switch over a channel of deferred values
2378
Roman Elizarova84730b2017-02-22 11:58:50 +03002379Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2380deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002381[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002382
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002383<!--- INCLUDE
2384import kotlin.coroutines.experimental.*
2385-->
2386
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002387```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002388fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002389 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002390 while (isActive) { // loop while not cancelled/closed
2391 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2392 input.onReceiveOrNull { update ->
2393 update // replaces next value to wait
2394 }
2395 current.onAwait { value ->
2396 send(value) // send value that current deferred has produced
2397 input.receiveOrNull() // and use the next deferred from the input channel
2398 }
2399 }
2400 if (next == null) {
2401 println("Channel was closed")
2402 break // out of loop
2403 } else {
2404 current = next
2405 }
2406 }
2407}
2408```
2409
2410To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2411
2412```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002413fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002414 delay(time)
2415 str
2416}
2417```
2418
2419The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2420data to it:
2421
2422```kotlin
2423fun main(args: Array<String>) = runBlocking<Unit> {
2424 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002425 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002426 for (s in switchMapDeferreds(chan))
2427 println(s) // print each received string
2428 }
2429 chan.send(asyncString("BEGIN", 100))
2430 delay(200) // enough time for "BEGIN" to be produced
2431 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002432 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002433 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002434 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002435 chan.send(asyncString("END", 500))
2436 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002437 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002438 delay(500) // and wait some time to let it finish
2439}
2440```
2441
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002442> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-05.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002443
2444The result of this code:
2445
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002446```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002447BEGIN
2448Replace
2449END
2450Channel was closed
2451```
2452
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002453<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002454
Roman Elizarov8db17332017-03-09 12:40:45 +03002455## Further reading
2456
2457* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002458* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002459* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2460* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2461
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002462<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002463<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002464[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2465[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2466[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002467[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002468[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002469[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2470[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03002471[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002472[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002473[CoroutineScope.isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/is-active.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002474[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002475[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002476[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2477[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002478[withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout-or-null.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002479[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2480[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002481[CoroutineStart.LAZY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-start/-l-a-z-y.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002482[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2483[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002484[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002485[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002486[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002487[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002488[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2489[ThreadPoolDispatcher.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-thread-pool-dispatcher/close.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002490[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002491[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002492[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Roman Elizarov3e387b82017-12-04 13:49:11 +03002493[kotlin.coroutines.experimental.CoroutineContext.cancelChildren]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/kotlin.coroutines.experimental.-coroutine-context/cancel-children.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002494[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002495[Deferred.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/on-await.html
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002496<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002497[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002498[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2499[Mutex.unlock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/unlock.html
Roman Elizarov88396732017-09-27 21:30:47 +03002500[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002501<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002502[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002503[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2504[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2505[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/close.html
Roman Elizarova5e653f2017-02-13 13:49:55 +03002506[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002507[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002508[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002509[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/ticker.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002510[ReceiveChannel.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/cancel.html
Roman Elizarov0c090ed2018-06-29 19:51:07 +03002511[TickerMode.FIXED_DELAY]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-ticker-mode/-f-i-x-e-d_-d-e-l-a-y.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002512[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarovb5328a72018-06-06 18:31:21 +03002513[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002514[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2515[SendChannel.onSend]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/on-send.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002516<!--- INDEX kotlinx.coroutines.experimental.selects -->
2517[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002518<!--- END -->