blob: bfdbe8c44d08024bdef92cb983c6c939c52cb138 [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)
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +030070* [Exception handling](#exception-handling)
71 * [Exception propagation](#exception-propagation)
72 * [CoroutineExceptionHandler](#coroutineexceptionhandler)
73 * [Cancellation and exceptions](#cancellation-and-exceptions)
74 * [Exceptions aggregation](#exceptions-aggregation)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030075* [Channels](#channels)
76 * [Channel basics](#channel-basics)
77 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
78 * [Building channel producers](#building-channel-producers)
79 * [Pipelines](#pipelines)
80 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
81 * [Fan-out](#fan-out)
82 * [Fan-in](#fan-in)
83 * [Buffered channels](#buffered-channels)
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +030084 * [Ticker channels](#ticker-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030085 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030086* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
87 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030088 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030089 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030090 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
91 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030092 * [Mutual exclusion](#mutual-exclusion)
93 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +030094* [Select expression](#select-expression)
95 * [Selecting from channels](#selecting-from-channels)
96 * [Selecting on close](#selecting-on-close)
97 * [Selecting to send](#selecting-to-send)
98 * [Selecting deferred values](#selecting-deferred-values)
99 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +0300100* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300101
Roman Elizarova5e653f2017-02-13 13:49:55 +0300102<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300103
104## Coroutine basics
105
106This section covers basic coroutine concepts.
107
108### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300109
110Run the following code:
111
112```kotlin
113fun main(args: Array<String>) {
Roman Elizarova4d45d22017-11-20 16:47:09 +0300114 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300115 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
116 println("World!") // print after delay
117 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300118 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300119 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
120}
121```
122
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300123> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300124
125Run this code:
126
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300127```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300128Hello,
129World!
130```
131
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300132<!--- TEST -->
133
Roman Elizarov419a6c82017-02-09 18:36:22 +0300134Essentially, coroutines are light-weight threads.
135They are launched with [launch] _coroutine builder_.
136You can achieve the same result replacing
Roman Elizarov66f018c2017-09-29 21:39:03 +0300137`launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300138
Roman Elizarov66f018c2017-09-29 21:39:03 +0300139If you start by replacing `launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300140
141```
142Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
143```
144
Roman Elizarov419a6c82017-02-09 18:36:22 +0300145That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300146coroutine and it can be only used from a coroutine.
147
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300148### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300149
Roman Elizarova4d45d22017-11-20 16:47:09 +0300150The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
151It is easy to get lost which one is blocking and which one is not.
152Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300153
154```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300155fun main(args: Array<String>) {
156 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300157 delay(1000L)
158 println("World!")
159 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300160 println("Hello,") // main thread continues here immediately
161 runBlocking { // but this expression blocks the main thread
162 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
163 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300164}
165```
166
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300167> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300168
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300169<!--- TEST
170Hello,
171World!
172-->
173
Roman Elizarov419a6c82017-02-09 18:36:22 +0300174The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100175The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300176
Roman Elizarova4d45d22017-11-20 16:47:09 +0300177This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
178the execution of the main function:
179
180```kotlin
181fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
182 launch { // launch new coroutine in background and continue
183 delay(1000L)
184 println("World!")
185 }
186 println("Hello,") // main coroutine continues here immediately
187 delay(2000L) // delaying for 2 seconds to keep JVM alive
188}
189```
190
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300191> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt)
Roman Elizarova4d45d22017-11-20 16:47:09 +0300192
193<!--- TEST
194Hello,
195World!
196-->
197
198Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
199We 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 +0300200
201This is also a way to write unit-tests for suspending functions:
202
203```kotlin
204class MyTest {
205 @Test
206 fun testMySuspendingFunction() = runBlocking<Unit> {
207 // here we can use suspending functions using any assertion style that we like
208 }
209}
210```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300211
212<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300213
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300214### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300215
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300216Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300217wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300218
219```kotlin
220fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300221 val job = launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300222 delay(1000L)
223 println("World!")
224 }
225 println("Hello,")
226 job.join() // wait until child coroutine completes
227}
228```
229
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300230> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300231
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300232<!--- TEST
233Hello,
234World!
235-->
236
Roman Elizarov7deefb82017-01-31 10:33:17 +0300237Now 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 +0300238the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300239
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300240### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300241
Roman Elizarov66f018c2017-09-29 21:39:03 +0300242Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300243perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
244That is your first _suspending function_. Suspending functions can be used inside coroutines
245just like regular functions, but their additional feature is that they can, in turn,
246use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
247
248```kotlin
249fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300250 val job = launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300251 println("Hello,")
252 job.join()
253}
254
255// this is your first suspending function
256suspend fun doWorld() {
257 delay(1000L)
258 println("World!")
259}
260```
261
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300262> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300263
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300264<!--- TEST
265Hello,
266World!
267-->
268
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300269### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300270
271Run the following code:
272
273```kotlin
274fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300275 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
276 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300277 delay(1000L)
278 print(".")
279 }
280 }
281 jobs.forEach { it.join() } // wait for all jobs to complete
282}
283```
284
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300285> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300286
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300287<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
288
Roman Elizarov66f018c2017-09-29 21:39:03 +0300289It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300290Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
291
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300292### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300293
294The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300295returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300296
297```kotlin
298fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300299 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300300 repeat(1000) { i ->
301 println("I'm sleeping $i ...")
302 delay(500L)
303 }
304 }
305 delay(1300L) // just quit after delay
306}
307```
308
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300309> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300310
311You can run and see that it prints three lines and terminates:
312
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300313```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300314I'm sleeping 0 ...
315I'm sleeping 1 ...
316I'm sleeping 2 ...
317```
318
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300319<!--- TEST -->
320
Roman Elizarov7deefb82017-01-31 10:33:17 +0300321Active coroutines do not keep the process alive. They are like daemon threads.
322
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300323## Cancellation and timeouts
324
325This section covers coroutine cancellation and timeouts.
326
327### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300328
Brad977ada12018-07-19 16:01:40 -0400329In a small application the return from "main" method might sound like a good idea to get all coroutines
330implicitly terminated but in a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300331The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300332
333```kotlin
334fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300335 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300336 repeat(1000) { i ->
337 println("I'm sleeping $i ...")
338 delay(500L)
339 }
340 }
341 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300342 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300343 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300344 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300345 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300346}
347```
348
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300349> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300350
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300351It produces the following output:
352
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300353```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300354I'm sleeping 0 ...
355I'm sleeping 1 ...
356I'm sleeping 2 ...
357main: I'm tired of waiting!
358main: Now I can quit.
359```
360
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300361<!--- TEST -->
362
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300363As 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 +0300364There is also a [Job] extension function [cancelAndJoin]
365that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300366
367### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300368
Tair Rzayevaf734622017-02-01 22:30:16 +0200369Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300370All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300371coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300372a computation and does not check for cancellation, then it cannot be cancelled, like the following
373example shows:
374
375```kotlin
376fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700377 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300378 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700379 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300380 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300381 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700382 // print a message twice a second
383 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300384 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300385 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300386 }
387 }
388 }
389 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300390 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300391 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300392 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300393}
394```
395
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300396> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300397
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300398Run it to see that it continues to print "I'm sleeping" even after cancellation
399until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300400
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300401<!--- TEST
402I'm sleeping 0 ...
403I'm sleeping 1 ...
404I'm sleeping 2 ...
405main: I'm tired of waiting!
406I'm sleeping 3 ...
407I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300408main: Now I can quit.
409-->
410
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300411### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300412
413There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300414invoke 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 +0300415The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300416
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300417Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300418
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300419```kotlin
420fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700421 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300422 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700423 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300424 var i = 0
425 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700426 // print a message twice a second
427 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300428 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700429 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300430 }
431 }
432 }
433 delay(1300L) // delay a bit
434 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300435 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300436 println("main: Now I can quit.")
437}
438```
439
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300440> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300441
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300442As 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 +0300443the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300444
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300445<!--- TEST
446I'm sleeping 0 ...
447I'm sleeping 1 ...
448I'm sleeping 2 ...
449main: I'm tired of waiting!
450main: Now I can quit.
451-->
452
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300453### Closing resources with finally
454
Roman Elizarov419a6c82017-02-09 18:36:22 +0300455Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Brad977ada12018-07-19 16:01:40 -0400456the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300457finalization actions normally when coroutine is cancelled:
458
459```kotlin
460fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300461 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300462 try {
463 repeat(1000) { i ->
464 println("I'm sleeping $i ...")
465 delay(500L)
466 }
467 } finally {
468 println("I'm running finally")
469 }
470 }
471 delay(1300L) // delay a bit
472 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300473 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300474 println("main: Now I can quit.")
475}
476```
477
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300478> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300479
Roman Elizarov88396732017-09-27 21:30:47 +0300480Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
481so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300482
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300483```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300484I'm sleeping 0 ...
485I'm sleeping 1 ...
486I'm sleeping 2 ...
487main: I'm tired of waiting!
488I'm running finally
489main: Now I can quit.
490```
491
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300492<!--- TEST -->
493
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300494### Run non-cancellable block
495
496Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300497[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300498problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
499communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
500rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300501`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300502
503```kotlin
504fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300505 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300506 try {
507 repeat(1000) { i ->
508 println("I'm sleeping $i ...")
509 delay(500L)
510 }
511 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300512 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300513 println("I'm running finally")
514 delay(1000L)
515 println("And I've just delayed for 1 sec because I'm non-cancellable")
516 }
517 }
518 }
519 delay(1300L) // delay a bit
520 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300521 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300522 println("main: Now I can quit.")
523}
524```
525
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300526> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300527
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300528<!--- TEST
529I'm sleeping 0 ...
530I'm sleeping 1 ...
531I'm sleeping 2 ...
532main: I'm tired of waiting!
533I'm running finally
534And I've just delayed for 1 sec because I'm non-cancellable
535main: Now I can quit.
536-->
537
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300538### Timeout
539
Brad977ada12018-07-19 16:01:40 -0400540The most obvious reason to cancel coroutine execution in practice
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300541is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300542While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
543the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300544Look at the following example:
545
546```kotlin
547fun main(args: Array<String>) = runBlocking<Unit> {
548 withTimeout(1300L) {
549 repeat(1000) { i ->
550 println("I'm sleeping $i ...")
551 delay(500L)
552 }
553 }
554}
555```
556
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300557> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300558
559It produces the following output:
560
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300561```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300562I'm sleeping 0 ...
563I'm sleeping 1 ...
564I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300565Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300566```
567
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300568<!--- TEST STARTS_WITH -->
569
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300570The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300571We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300572inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300573However, in this example we have used `withTimeout` right inside the `main` function.
574
575Because cancellation is just an exception, all the resources will be closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300576You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
577you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300578that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
579
580```kotlin
581fun main(args: Array<String>) = runBlocking<Unit> {
582 val result = withTimeoutOrNull(1300L) {
583 repeat(1000) { i ->
584 println("I'm sleeping $i ...")
585 delay(500L)
586 }
587 "Done" // will get cancelled before it produces this result
588 }
589 println("Result is $result")
590}
591```
592
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300593> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300594
595There is no longer an exception when running this code:
596
597```text
598I'm sleeping 0 ...
599I'm sleeping 1 ...
600I'm sleeping 2 ...
601Result is null
602```
603
604<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300605
606## Composing suspending functions
607
608This section covers various approaches to composition of suspending functions.
609
610### Sequential by default
611
612Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300613remote service call or computation. We just pretend they are useful, but actually each one just
614delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300615
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300616<!--- INCLUDE .*/example-compose-([0-9]+).kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300617import kotlin.system.*
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300618-->
619
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300620```kotlin
621suspend fun doSomethingUsefulOne(): Int {
622 delay(1000L) // pretend we are doing something useful here
623 return 13
624}
625
626suspend fun doSomethingUsefulTwo(): Int {
627 delay(1000L) // pretend we are doing something useful here, too
628 return 29
629}
630```
631
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300632<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
633
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300634What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
635`doSomethingUsefulTwo` and compute the sum of their results?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200636In 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 +0300637to invoke the second one or to decide on how to invoke it.
638
639We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300640code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300641time it takes to execute both suspending functions:
642
643```kotlin
644fun main(args: Array<String>) = runBlocking<Unit> {
645 val time = measureTimeMillis {
646 val one = doSomethingUsefulOne()
647 val two = doSomethingUsefulTwo()
648 println("The answer is ${one + two}")
649 }
650 println("Completed in $time ms")
651}
652```
653
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300654> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300655
656It produces something like this:
657
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300658```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300659The answer is 42
660Completed in 2017 ms
661```
662
Roman Elizarov35d2c342017-07-20 14:54:39 +0300663<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300664
Roman Elizarov32d95322017-02-09 15:57:31 +0300665### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300666
667What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300668we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300669
Roman Elizarov419a6c82017-02-09 18:36:22 +0300670Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
671that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
672does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300673that 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 +0300674but `Deferred` is also a `Job`, so you can cancel it if needed.
675
676```kotlin
677fun main(args: Array<String>) = runBlocking<Unit> {
678 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300679 val one = async { doSomethingUsefulOne() }
680 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300681 println("The answer is ${one.await() + two.await()}")
682 }
683 println("Completed in $time ms")
684}
685```
686
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300687> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300688
689It produces something like this:
690
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300691```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300692The answer is 42
693Completed in 1017 ms
694```
695
Roman Elizarov35d2c342017-07-20 14:54:39 +0300696<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300697
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300698This is twice as fast, because we have concurrent execution of two coroutines.
699Note, that concurrency with coroutines is always explicit.
700
Roman Elizarov32d95322017-02-09 15:57:31 +0300701### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300702
Roman Elizarov66f018c2017-09-29 21:39:03 +0300703There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300704It starts coroutine only when its result is needed by some
705[await][Deferred.await] or if a [start][Job.start] function
Sahil Lone52a0ec02018-07-19 18:55:35 +0200706is invoked. Run the following example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300707
708```kotlin
709fun main(args: Array<String>) = runBlocking<Unit> {
710 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300711 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
712 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Sahil Lone52a0ec02018-07-19 18:55:35 +0200713 // some computation
714 one.start() // start the first one
715 two.start() // start the second one
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300716 println("The answer is ${one.await() + two.await()}")
717 }
718 println("Completed in $time ms")
719}
720```
721
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300722> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300723
724It produces something like this:
725
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300726```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300727The answer is 42
Sahil Lone52a0ec02018-07-19 18:55:35 +0200728Completed in 1017 ms
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300729```
730
Roman Elizarov35d2c342017-07-20 14:54:39 +0300731<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300732
Sahil Lone52a0ec02018-07-19 18:55:35 +0200733So, here the two coroutines are defined but not executed as in the previous example, but the control is given to
734the programmer about when exactly to start the execution by calling [start][Job.start] on it. We first
735start `one`, then start `two`, and then await for the individual coroutines to finish.
736
737Note, that if we have called [await][Deferred.await] in `println` and omitted [start][Job.start] on individual
738coroutines, then we would have got the sequential behaviour as [await][Deferred.await] starts the coroutine
739execution and waits for the execution to finish, which is not the intended use-case for laziness.
740The use-case for `async(start = CoroutineStart.LAZY)` is a replacement for the
741standard `lazy` function in cases when computation of the value involves suspending functions.
Roman Elizarov32d95322017-02-09 15:57:31 +0300742
743### Async-style functions
744
745We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300746_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100747"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
748to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300749
750```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100751// The result type of somethingUsefulOneAsync is Deferred<Int>
752fun somethingUsefulOneAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300753 doSomethingUsefulOne()
754}
755
Marcin Moskała7e94e702018-01-29 18:39:02 +0100756// The result type of somethingUsefulTwoAsync is Deferred<Int>
757fun somethingUsefulTwoAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300758 doSomethingUsefulTwo()
759}
760```
761
Marcin Moskała7e94e702018-01-29 18:39:02 +0100762Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300763However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
764with the invoking code.
765
766The following example shows their use outside of coroutine:
767
768```kotlin
769// note, that we don't have `runBlocking` to the right of `main` in this example
770fun main(args: Array<String>) {
771 val time = measureTimeMillis {
772 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100773 val one = somethingUsefulOneAsync()
774 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300775 // but waiting for a result must involve either suspending or blocking.
776 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
777 runBlocking {
778 println("The answer is ${one.await() + two.await()}")
779 }
780 }
781 println("Completed in $time ms")
782}
783```
784
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300785> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300786
Roman Elizarov35d2c342017-07-20 14:54:39 +0300787<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300788The answer is 42
789Completed in 1085 ms
790-->
791
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300792## Coroutine context and dispatchers
793
Roman Elizarov66f018c2017-09-29 21:39:03 +0300794Coroutines always execute in some context which is represented by the value of
795[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
796type, defined in the Kotlin standard library.
797
798The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
799which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300800
801### Dispatchers and threads
802
Roman Elizarov66f018c2017-09-29 21:39:03 +0300803Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300804the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +0300805to a specific thread, dispatch it to a thread pool, or let it run unconfined.
806
807All coroutines builders like [launch] and [async] accept an optional
808[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
809parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
810
811Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300812
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300813<!--- INCLUDE
814import kotlin.coroutines.experimental.*
815-->
816
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300817```kotlin
818fun main(args: Array<String>) = runBlocking<Unit> {
819 val jobs = arrayListOf<Job>()
820 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300821 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300822 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300823 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
824 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300825 }
826 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300827 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300828 }
829 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300830 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300831 }
832 jobs.forEach { it.join() }
833}
834```
835
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300836> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300837
838It produces the following output (maybe in different order):
839
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300840```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300841 'Unconfined': I'm working in thread main
842 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
843 'newSTC': I'm working in thread MyOwnThread
844'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300845```
846
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300847<!--- TEST LINES_START_UNORDERED -->
848
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800849The default dispatcher that we've used in previous sections is representend by [DefaultDispatcher], which
Roman Elizarov66f018c2017-09-29 21:39:03 +0300850is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same
Charles Muchenefa13beb2018-01-08 16:56:54 +0300851as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300852
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300853The difference between parent
854[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html) and
Roman Elizarov43e3af72017-07-21 16:01:31 +0300855[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300856
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800857Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource.
858In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
859function, or stored in a top-level variable and reused throughout the application.
860
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300861### Unconfined vs confined dispatcher
862
Roman Elizarov419a6c82017-02-09 18:36:22 +0300863The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300864first suspension point. After suspension it resumes in the thread that is fully determined by the
865suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
866consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
867
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300868On the other side,
869[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
870property, that is available inside any coroutine, is a reference to a context of this particular coroutine.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300871This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
872is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300873this thread with a predictable FIFO scheduling.
874
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300875<!--- INCLUDE
876import kotlin.coroutines.experimental.*
877-->
878
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300879```kotlin
880fun main(args: Array<String>) = runBlocking<Unit> {
881 val jobs = arrayListOf<Job>()
882 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300883 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300884 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300885 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300886 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300887 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
888 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300889 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300890 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300891 }
892 jobs.forEach { it.join() }
893}
894```
895
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300896> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300897
898Produces the output:
899
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300900```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300901 'Unconfined': I'm working in thread main
902'coroutineContext': I'm working in thread main
903 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
904'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300905```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300906
907<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300908
Roman Elizarov43e3af72017-07-21 16:01:31 +0300909So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
910in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
911function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300912
913### Debugging coroutines and threads
914
Roman Elizarov419a6c82017-02-09 18:36:22 +0300915Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
Roman Elizarov66f018c2017-09-29 21:39:03 +0300916with a default multi-threaded dispatcher. Even with a single-threaded dispatcher it might be hard to
paolopb019b102018-06-09 16:42:24 +0000917figure out what coroutine was doing, where, and when. The common approach to debugging applications with
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300918threads is to print the thread name in the log file on each log statement. This feature is universally supported
919by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
920`kotlinx.coroutines` includes debugging facilities to make it easier.
921
922Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
923
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300924<!--- INCLUDE
925import kotlin.coroutines.experimental.*
926-->
927
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300928```kotlin
929fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
930
931fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300932 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300933 log("I'm computing a piece of the answer")
934 6
935 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300936 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300937 log("I'm computing another piece of the answer")
938 7
939 }
940 log("The answer is ${a.await() * b.await()}")
941}
942```
943
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300944> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300945
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300946There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300947and two coroutines computing deferred values `a` (#2) and `b` (#3).
948They are all executing in the context of `runBlocking` and are confined to the main thread.
949The output of this code is:
950
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300951```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300952[main @coroutine#2] I'm computing a piece of the answer
953[main @coroutine#3] I'm computing another piece of the answer
954[main @coroutine#1] The answer is 42
955```
956
Kirill Timofeeva5186962017-10-25 14:25:47 +0300957<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300958
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300959The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
960thread, but the identifier of the currently executing coroutine is appended to it. This identifier
961is consecutively assigned to all created coroutines when debugging mode is turned on.
962
Roman Elizarov419a6c82017-02-09 18:36:22 +0300963You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300964
965### Jumping between threads
966
967Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
968
969```kotlin
970fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
971
972fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800973 newSingleThreadContext("Ctx1").use { ctx1 ->
974 newSingleThreadContext("Ctx2").use { ctx2 ->
975 runBlocking(ctx1) {
976 log("Started in ctx1")
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300977 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800978 log("Working in ctx2")
979 }
980 log("Back to ctx1")
981 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300982 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300983 }
984}
985```
986
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300987> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300988
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800989It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300990the 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 +0300991same coroutine as you can see in the output below:
992
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300993```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300994[Ctx1 @coroutine#1] Started in ctx1
995[Ctx2 @coroutine#1] Working in ctx2
996[Ctx1 @coroutine#1] Back to ctx1
997```
998
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300999<!--- TEST -->
1000
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001001
Artsiom Chapialioue185ed62018-06-03 19:34:22 -04001002Note, that this example also uses `use` function from the Kotlin standard library to release threads that
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001003are created with [newSingleThreadContext] when they are no longer needed.
1004
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001005### Job in the context
1006
Roman Elizarov66f018c2017-09-29 21:39:03 +03001007The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001008using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001009
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001010<!--- INCLUDE
1011import kotlin.coroutines.experimental.*
1012-->
1013
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001014```kotlin
1015fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001016 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001017}
1018```
1019
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001020> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001021
Roman Elizarov66f018c2017-09-29 21:39:03 +03001022It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001023
1024```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001025My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001026```
1027
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001028<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001029
Roman Elizarov43e3af72017-07-21 16:01:31 +03001030So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001031`coroutineContext[Job]?.isActive == true`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001032
1033### Children of a coroutine
1034
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001035When
1036[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
1037of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +03001038the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001039a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1040are recursively cancelled, too.
1041
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001042<!--- INCLUDE
1043import kotlin.coroutines.experimental.*
1044-->
1045
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001046```kotlin
1047fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001048 // launch a coroutine to process some kind of incoming request
1049 val request = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001050 // it spawns two other jobs, one with its separate context
Roman Elizarov66f018c2017-09-29 21:39:03 +03001051 val job1 = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001052 println("job1: I have my own context and execute independently!")
1053 delay(1000)
1054 println("job1: I am not affected by cancellation of the request")
1055 }
1056 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001057 val job2 = launch(coroutineContext) {
Roman Elizarov74619c12017-11-09 10:32:15 +03001058 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001059 println("job2: I am a child of the request coroutine")
1060 delay(1000)
1061 println("job2: I will not execute this line if my parent request is cancelled")
1062 }
1063 // request completes when both its sub-jobs complete:
1064 job1.join()
1065 job2.join()
1066 }
1067 delay(500)
1068 request.cancel() // cancel processing of the request
1069 delay(1000) // delay a second to see what happens
1070 println("main: Who has survived request cancellation?")
1071}
1072```
1073
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001074> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001075
1076The output of this code is:
1077
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001078```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001079job1: I have my own context and execute independently!
1080job2: I am a child of the request coroutine
1081job1: I am not affected by cancellation of the request
1082main: Who has survived request cancellation?
1083```
1084
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001085<!--- TEST -->
1086
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001087### Combining contexts
1088
Roman Elizarov66f018c2017-09-29 21:39:03 +03001089Coroutine contexts can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +03001090of 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 +03001091its dispatcher replaced:
1092
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001093<!--- INCLUDE
1094import kotlin.coroutines.experimental.*
1095-->
1096
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001097```kotlin
1098fun main(args: Array<String>) = runBlocking<Unit> {
1099 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +03001100 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001101 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +03001102 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001103 println("job: I am a child of the request coroutine, but with a different dispatcher")
1104 delay(1000)
1105 println("job: I will not execute this line if my parent request is cancelled")
1106 }
1107 job.join() // request completes when its sub-job completes
1108 }
1109 delay(500)
1110 request.cancel() // cancel processing of the request
1111 delay(1000) // delay a second to see what happens
1112 println("main: Who has survived request cancellation?")
1113}
1114```
1115
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001116> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001117
1118The expected outcome of this code is:
1119
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001120```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001121job: I am a child of the request coroutine, but with a different dispatcher
1122main: Who has survived request cancellation?
1123```
1124
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001125<!--- TEST -->
1126
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001127### Parental responsibilities
1128
1129A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001130all 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 +03001131
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001132<!--- INCLUDE
1133import kotlin.coroutines.experimental.*
1134-->
1135
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001136```kotlin
1137fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001138 // launch a coroutine to process some kind of incoming request
1139 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001140 repeat(3) { i -> // launch a few children jobs
1141 launch(coroutineContext) {
1142 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1143 println("Coroutine $i is done")
1144 }
1145 }
1146 println("request: I'm done and I don't explicitly join my children that are still active")
1147 }
1148 request.join() // wait for completion of the request, including all its children
1149 println("Now processing of the request is complete")
1150}
1151```
1152
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001153> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-08.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001154
1155The result is going to be:
1156
1157```text
1158request: I'm done and I don't explicitly join my children that are still active
1159Coroutine 0 is done
1160Coroutine 1 is done
1161Coroutine 2 is done
1162Now processing of the request is complete
1163```
1164
1165<!--- TEST -->
1166
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001167### Naming coroutines for debugging
1168
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001169Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001170coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1171or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001172[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1173is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001174
1175The following example demonstrates this concept:
1176
1177```kotlin
1178fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1179
1180fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1181 log("Started main coroutine")
1182 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001183 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001184 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001185 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001186 252
1187 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001188 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001189 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001190 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001191 6
1192 }
1193 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1194}
1195```
1196
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001197> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-09.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001198
1199The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1200
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001201```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001202[main @main#1] Started main coroutine
1203[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1204[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1205[main @main#1] The answer for v1 / v2 = 42
1206```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001207
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001208<!--- TEST FLEXIBLE_THREAD -->
1209
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001210### Cancellation via explicit job
1211
1212Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1213an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1214and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1215and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1216to avoid memory leaks.
1217
1218We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
Roman Elizarov88396732017-09-27 21:30:47 +03001219the lifecycle of our activity. A job instance is created using [Job()] factory function
Roman Elizarove8f694e2017-11-28 10:12:00 +03001220as the following example shows. For convenience, rather than using `launch(coroutineContext + job)` expression,
1221we can write `launch(coroutineContext, parent = job)` to make explicit the fact that the parent job is being used.
1222
1223Now, a single invocation of [Job.cancel] cancels all the children we've launched.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001224Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1225this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001226
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001227<!--- INCLUDE
1228import kotlin.coroutines.experimental.*
1229-->
1230
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001231```kotlin
1232fun main(args: Array<String>) = runBlocking<Unit> {
1233 val job = Job() // create a job object to manage our lifecycle
1234 // now launch ten coroutines for a demo, each working for a different time
1235 val coroutines = List(10) { i ->
1236 // they are all children of our job object
Roman Elizarove8f694e2017-11-28 10:12:00 +03001237 launch(coroutineContext, parent = job) { // we use the context of main runBlocking thread, but with our parent job
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001238 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001239 println("Coroutine $i is done")
1240 }
1241 }
1242 println("Launched ${coroutines.size} coroutines")
1243 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001244 println("Cancelling the job!")
1245 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001246}
1247```
1248
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001249> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-10.kt)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001250
1251The output of this example is:
1252
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001253```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001254Launched 10 coroutines
1255Coroutine 0 is done
1256Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001257Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001258```
1259
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001260<!--- TEST -->
1261
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001262As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001263by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001264application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001265and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1266since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1267resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001268
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001269## Exception handling
1270
1271<!--- INCLUDE .*/example-exceptions-([0-9]+).kt
1272-->
1273
1274This section covers exception handling and cancellation on exceptions.
1275We already know that cancelled coroutine throws [CancellationException] in suspension points and that it
1276is ignored by coroutines machinery. But what happens if an exception is thrown during cancellation or multiple children of the same
1277coroutine throw an exception?
1278
1279### Exception propagation
Roman Elizarov563da402018-08-10 19:18:56 +03001280
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001281Coroutine builders come in two flavors: propagating exceptions automatically ([launch] and [actor]) or exposing them to users ([async] and [produce]).
Roman Elizarov563da402018-08-10 19:18:56 +03001282The former treat exceptions as unhandled, similar to Java's `Thread.uncaughExceptionHandler`, while the latter are relying on the user to consume the final
1283exception, for example via [await][Deferred.await] or [receive][ReceiveChannel.receive]
1284([produce] and [receive][ReceiveChannel.receive] are covered later in [Channels](#channels) section).
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001285
1286It can be demonstrated by a simple example:
1287
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001288```kotlin
1289fun main(args: Array<String>) = runBlocking {
1290 val job = launch {
1291 println("Throwing exception from launch")
1292 throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
1293 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001294 job.join()
1295 println("Joined failed job")
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001296 val deferred = async {
1297 println("Throwing exception from async")
1298 throw ArithmeticException() // Nothing is printed, relying on user to call await
1299 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001300 try {
1301 deferred.await()
1302 println("Unreached")
1303 } catch (e: ArithmeticException) {
1304 println("Caught ArithmeticException")
1305 }
1306}
1307```
1308
1309> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-01.kt)
1310
1311The output of this code is:
1312
1313```text
1314Throwing exception from launch
1315Exception in thread "ForkJoinPool.commonPool-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
1316Joined failed job
1317Throwing exception from async
1318Caught ArithmeticException
1319```
1320
1321<!--- TEST EXCEPTION-->
1322
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001323### CoroutineExceptionHandler
1324
1325But what if one does not want to print all exceptions to the console?
1326[CoroutineExceptionHandler] context element is used as generic `catch` block of coroutine where custom logging or exception handling may take place.
Roman Elizarov563da402018-08-10 19:18:56 +03001327It is similar to using [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
1328
1329On JVM it's possible to redefine global exception handler for all coroutines by registering [CoroutineExceptionHandler] via
1330[`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
1331Global exception handler is similar to
1332[`Thread.defaultUncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler))
1333which is used when no more specific handlers are registered.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001334On Android, `uncaughtExceptionPreHandler` is installed as a global coroutine exception handler.
1335
Roman Elizarov563da402018-08-10 19:18:56 +03001336[CoroutineExceptionHandler] is invoked only on exceptions which are not expected to be handled by the user,
1337so registering it in [async] builder and the like of it has no effect.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001338
1339```kotlin
1340fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001341 val handler = CoroutineExceptionHandler { _, exception ->
1342 println("Caught $exception")
1343 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001344 val job = launch(handler) {
1345 throw AssertionError()
1346 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001347 val deferred = async(handler) {
1348 throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
1349 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001350 joinAll(job, deferred)
1351}
1352```
1353
1354> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-02.kt)
1355
1356The output of this code is:
1357
1358```text
1359Caught java.lang.AssertionError
1360```
1361
1362<!--- TEST-->
1363
1364### Cancellation and exceptions
Roman Elizarov563da402018-08-10 19:18:56 +03001365
1366Cancellation is tightly bound with exceptions. Coroutines internally use `CancellationException` for cancellation, these
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001367exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can
1368be obtained by `catch` block.
Roman Elizarov563da402018-08-10 19:18:56 +03001369When a coroutine is cancelled using [Job.cancel] without a cause, it terminates, but it does not cancel its parent.
1370Cancelling without cause is a mechanism for parent to cancel its children without cancelling itself.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001371
1372<!--- INCLUDE
1373import kotlin.coroutines.experimental.*
1374-->
1375
1376```kotlin
1377fun main(args: Array<String>) = runBlocking {
1378 val job = launch(coroutineContext, parent = Job()) {
1379 val child = launch(coroutineContext) {
1380 try {
1381 delay(Long.MAX_VALUE)
1382 } finally {
1383 println("Child is cancelled")
1384 }
1385 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001386 yield()
1387 println("Cancelling child")
1388 child.cancel()
1389 child.join()
1390 yield()
1391 println("Parent is not cancelled")
1392 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001393 job.join()
1394}
1395```
1396
1397> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-03.kt)
1398
1399The output of this code is:
1400
1401```text
1402Cancelling child
1403Child is cancelled
1404Parent is not cancelled
1405```
1406
1407<!--- TEST-->
1408
Roman Elizarov563da402018-08-10 19:18:56 +03001409If a coroutine encounters exception other than `CancellationException`, it cancels its parent with that exception.
1410This behaviour cannot be overridden and is used to provide stable coroutines hierarchies which do not depend on [CoroutineExceptionHandler] implementation.
1411The original exception is handled by the parent when all its children terminate.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001412
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001413<!--- INCLUDE
1414import kotlin.coroutines.experimental.*
1415-->
1416
1417```kotlin
1418fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001419 val handler = CoroutineExceptionHandler { _, exception ->
1420 println("Caught $exception")
1421 }
1422 val job = launch(handler) {
1423 val child1 = launch(coroutineContext, start = CoroutineStart.ATOMIC) {
1424 try {
1425 delay(Long.MAX_VALUE)
1426 } finally {
1427 withContext(NonCancellable) {
1428 println("Children are cancelled, but exception is not handled until all children terminate")
1429 delay(100)
1430 println("Last child finished its non cancellable block")
1431 }
1432 }
1433 }
1434 val child2 = launch(coroutineContext, start = CoroutineStart.ATOMIC) {
1435 delay(10)
1436 println("Second child throws an exception")
1437 throw ArithmeticException()
1438 }
1439 }
1440 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001441}
1442```
1443
1444> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-04.kt)
1445
1446The output of this code is:
1447
1448```text
Roman Elizarov563da402018-08-10 19:18:56 +03001449Second child throws an exception
1450Children are cancelled, but exception is not handled until all children terminate
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001451Last child finished its non cancellable block
1452Caught java.lang.ArithmeticException
1453```
1454<!--- TEST-->
1455
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001456### Exceptions aggregation
Roman Elizarov563da402018-08-10 19:18:56 +03001457
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001458What happens if multiple children of a coroutine throw an exception?
Roman Elizarov563da402018-08-10 19:18:56 +03001459The general rule is "the first exception wins", so the first thrown exception is exposed to the handler.
1460But that may cause lost exceptions, for example if coroutine throws an exception in its `finally` block.
1461
1462One of the solutions would have been to report each exception separately,
1463but then [Deferred.await] should have had the same mechanism to avoid behavioural inconsistency and this
1464would cause implementation details of a coroutines (whether it had delegate parts of its work to its children or not)
1465to leak to its exception handler.
1466
1467To avoid that, additional exceptions are suppressed.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001468
1469<!--- INCLUDE
1470import kotlinx.coroutines.experimental.exceptions.*
1471import kotlin.coroutines.experimental.*
1472import java.io.*
1473-->
1474
1475```kotlin
1476fun main(args: Array<String>) = runBlocking {
1477 val handler = CoroutineExceptionHandler { _, exception ->
Roman Elizarov563da402018-08-10 19:18:56 +03001478 println("Caught $exception with suppressed ${exception.suppressed().contentToString()}")
1479 }
1480 val job = launch(handler + coroutineContext, parent = Job()) {
1481 launch(coroutineContext, start = CoroutineStart.ATOMIC) {
1482 try {
1483 delay(Long.MAX_VALUE)
1484 } finally {
1485 throw ArithmeticException()
1486 }
1487 }
1488 launch(coroutineContext) {
1489 throw IOException()
1490 }
1491 delay(Long.MAX_VALUE)
1492 }
1493 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001494}
1495```
1496
1497> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-05.kt)
1498
1499The output of this code is:
1500
1501```text
1502Caught java.io.IOException with suppressed [java.lang.ArithmeticException]
1503```
1504<!--- TEST-->
1505
Roman Elizarov563da402018-08-10 19:18:56 +03001506Note that this mechanism currently works only on Java version 1.7+.
1507Limitation on JS and Native is temporary and will be fixed in the future.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001508
1509Cancellation exceptions are transparent and unwrapped by default:
1510
1511<!--- INCLUDE
1512import kotlin.coroutines.experimental.*
1513import java.io.*
1514-->
1515
1516```kotlin
1517fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001518 val handler = CoroutineExceptionHandler { _, exception ->
1519 println("Caught original $exception")
1520 }
1521 val job = launch(handler) {
1522 val inner = launch(coroutineContext) {
1523 launch(coroutineContext) {
1524 launch(coroutineContext) {
1525 throw IOException()
1526 }
1527 }
1528 }
1529 try {
1530 inner.join()
1531 } catch (e: JobCancellationException) {
1532 println("Rethrowing JobCancellationException with original cause")
1533 throw e
1534 }
1535 }
1536 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001537}
1538```
1539
1540> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt)
1541
1542The output of this code is:
1543
1544```text
1545Rethrowing JobCancellationException with original cause
1546Caught original java.io.IOException
1547```
1548<!--- TEST-->
1549
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001550## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001551
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001552Deferred values provide a convenient way to transfer a single value between coroutines.
1553Channels provide a way to transfer a stream of values.
1554
1555<!--- INCLUDE .*/example-channel-([0-9]+).kt
1556import kotlinx.coroutines.experimental.channels.*
1557-->
1558
1559### Channel basics
1560
Roman Elizarov419a6c82017-02-09 18:36:22 +03001561A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1562instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1563a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001564
1565```kotlin
1566fun main(args: Array<String>) = runBlocking<Unit> {
1567 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001568 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001569 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1570 for (x in 1..5) channel.send(x * x)
1571 }
1572 // here we print five received integers:
1573 repeat(5) { println(channel.receive()) }
1574 println("Done!")
1575}
1576```
1577
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001578> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-01.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001579
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001580The output of this code is:
1581
1582```text
15831
15844
15859
158616
158725
1588Done!
1589```
1590
1591<!--- TEST -->
1592
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001593### Closing and iteration over channels
1594
1595Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1596On the receiver side it is convenient to use a regular `for` loop to receive elements
1597from the channel.
1598
Roman Elizarov419a6c82017-02-09 18:36:22 +03001599Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001600The iteration stops as soon as this close token is received, so there is a guarantee
1601that all previously sent elements before the close are received:
1602
1603```kotlin
1604fun main(args: Array<String>) = runBlocking<Unit> {
1605 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001606 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001607 for (x in 1..5) channel.send(x * x)
1608 channel.close() // we're done sending
1609 }
1610 // here we print received values using `for` loop (until the channel is closed)
1611 for (y in channel) println(y)
1612 println("Done!")
1613}
1614```
1615
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001616> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001617
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001618<!--- TEST
16191
16204
16219
162216
162325
1624Done!
1625-->
1626
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001627### Building channel producers
1628
Roman Elizarova5e653f2017-02-13 13:49:55 +03001629The pattern where a coroutine is producing a sequence of elements is quite common.
1630This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001631You 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 +03001632to common sense that results must be returned from functions.
1633
Roman Elizarov86349be2017-03-17 16:47:37 +03001634There 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 +03001635and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001636
1637```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001638fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001639 for (x in 1..5) send(x * x)
1640}
1641
1642fun main(args: Array<String>) = runBlocking<Unit> {
1643 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001644 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001645 println("Done!")
1646}
1647```
1648
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001649> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-03.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001650
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001651<!--- TEST
16521
16534
16549
165516
165625
1657Done!
1658-->
1659
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001660### Pipelines
1661
Roman Elizarov66f018c2017-09-29 21:39:03 +03001662A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001663
1664```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001665fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001666 var x = 1
1667 while (true) send(x++) // infinite stream of integers starting from 1
1668}
1669```
1670
Roman Elizarova5e653f2017-02-13 13:49:55 +03001671And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001672In the below example the numbers are just squared:
1673
1674```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001675fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001676 for (x in numbers) send(x * x)
1677}
1678```
1679
Roman Elizarova5e653f2017-02-13 13:49:55 +03001680The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001681
1682```kotlin
1683fun main(args: Array<String>) = runBlocking<Unit> {
1684 val numbers = produceNumbers() // produces integers from 1 and on
1685 val squares = square(numbers) // squares integers
1686 for (i in 1..5) println(squares.receive()) // print first five
1687 println("Done!") // we are done
1688 squares.cancel() // need to cancel these coroutines in a larger app
1689 numbers.cancel()
1690}
1691```
1692
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001693> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-04.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001694
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001695<!--- TEST
16961
16974
16989
169916
170025
1701Done!
1702-->
1703
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001704We don't have to cancel these coroutines in this example app, because
1705[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1706but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1707Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001708[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001709
1710### Prime numbers with pipeline
1711
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001712Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001713of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001714explicit `context` parameter and pass it to [produce] builder,
1715so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001716
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001717<!--- INCLUDE
1718import kotlin.coroutines.experimental.*
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001719-->
1720
1721```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001722fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001723 var x = start
1724 while (true) send(x++) // infinite stream of integers from start
1725}
1726```
1727
1728The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1729that are divisible by the given prime number:
1730
1731```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001732fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001733 for (x in numbers) if (x % prime != 0) send(x)
1734}
1735```
1736
1737Now 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 +03001738and launching new pipeline stage for each prime number found:
1739
1740```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001741numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001742```
1743
1744The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001745running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001746children of the main [runBlocking] coroutine in its
1747[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html),
1748we don't have to keep an explicit list of all the coroutines we have started.
Roman Elizarov3e387b82017-12-04 13:49:11 +03001749We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
1750extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001751
1752```kotlin
1753fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001754 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001755 for (i in 1..10) {
1756 val prime = cur.receive()
1757 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001758 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001759 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001760 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001761}
1762```
1763
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001764> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-05.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001765
1766The output of this code is:
1767
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001768```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030017692
17703
17715
17727
177311
177413
177517
177619
177723
177829
1779```
1780
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001781<!--- TEST -->
1782
Roman Elizarov66f018c2017-09-29 21:39:03 +03001783Note, that you can build the same pipeline using
1784[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1785coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001786Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001787`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1788However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1789multiple CPU cores if you run it in [CommonPool] context.
1790
Roman Elizarova5e653f2017-02-13 13:49:55 +03001791Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001792other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1793built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001794`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001795
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001796### Fan-out
1797
1798Multiple coroutines may receive from the same channel, distributing work between themselves.
1799Let us start with a producer coroutine that is periodically producing integers
1800(ten numbers per second):
1801
1802```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001803fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001804 var x = 1 // start from 1
1805 while (true) {
1806 send(x++) // produce next
1807 delay(100) // wait 0.1s
1808 }
1809}
1810```
1811
1812Then we can have several processor coroutines. In this example, they just print their id and
1813received number:
1814
1815```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001816fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
bill58c61c72018-06-21 17:24:08 -05001817 for (msg in channel) {
1818 println("Processor #$id received $msg")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001819 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001820}
1821```
1822
Roman Elizarov35d2c342017-07-20 14:54:39 +03001823Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001824
1825```kotlin
1826fun main(args: Array<String>) = runBlocking<Unit> {
1827 val producer = produceNumbers()
1828 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001829 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001830 producer.cancel() // cancel producer coroutine and thus kill them all
1831}
1832```
1833
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001834> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-06.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001835
1836The output will be similar to the the following one, albeit the processor ids that receive
1837each specific integer may be different:
1838
1839```
1840Processor #2 received 1
1841Processor #4 received 2
1842Processor #0 received 3
1843Processor #1 received 4
1844Processor #3 received 5
1845Processor #2 received 6
1846Processor #4 received 7
1847Processor #0 received 8
1848Processor #1 received 9
1849Processor #3 received 10
1850```
1851
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001852<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1853
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001854Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1855over the channel that processor coroutines are doing.
1856
Roman Elizarov1ce6c0b2018-06-28 10:37:20 +03001857Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
1858Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
1859coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
1860always consumes (cancels) the underlying channel on its normal or abnormal termination.
1861
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001862### Fan-in
1863
1864Multiple coroutines may send to the same channel.
1865For example, let us have a channel of strings, and a suspending function that
1866repeatedly sends a specified string to this channel with a specified delay:
1867
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001868<!--- INCLUDE
1869import kotlin.coroutines.experimental.*
1870-->
1871
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001872```kotlin
1873suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1874 while (true) {
1875 delay(time)
1876 channel.send(s)
1877 }
1878}
1879```
1880
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001881Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001882(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 +03001883
1884```kotlin
1885fun main(args: Array<String>) = runBlocking<Unit> {
1886 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001887 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1888 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001889 repeat(6) { // receive first six
1890 println(channel.receive())
1891 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001892 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001893}
1894```
1895
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001896> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-07.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001897
1898The output is:
1899
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001900```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001901foo
1902foo
1903BAR!
1904foo
1905foo
1906BAR!
1907```
1908
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001909<!--- TEST -->
1910
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001911### Buffered channels
1912
1913The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1914meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1915if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001916
Roman Elizarov88396732017-09-27 21:30:47 +03001917Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001918specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1919similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1920
1921Take a look at the behavior of the following code:
1922
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001923<!--- INCLUDE
1924import kotlin.coroutines.experimental.*
1925-->
1926
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001927```kotlin
1928fun main(args: Array<String>) = runBlocking<Unit> {
1929 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001930 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001931 repeat(10) {
1932 println("Sending $it") // print before sending each element
1933 channel.send(it) // will suspend when buffer is full
1934 }
1935 }
1936 // don't receive anything... just wait....
1937 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001938 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001939}
1940```
1941
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001942> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001943
1944It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1945
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001946```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001947Sending 0
1948Sending 1
1949Sending 2
1950Sending 3
1951Sending 4
1952```
1953
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001954<!--- TEST -->
1955
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001956The 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 +03001957
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001958### Ticker channels
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001959
Roman Elizarovb5328a72018-06-06 18:31:21 +03001960Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
1961Though 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 +03001962pipelines and operators that do windowing and other time-dependent processing.
Roman Elizarovb5328a72018-06-06 18:31:21 +03001963Ticker channel can be used in [select] to perform "on tick" action.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001964
Roman Elizarovb5328a72018-06-06 18:31:21 +03001965To create such channel use a factory method [ticker].
1966To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001967
1968Now let's see how it works in practice:
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001969
1970```kotlin
1971fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovb5328a72018-06-06 18:31:21 +03001972 val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001973 var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
paolop1d6e4932018-07-02 08:46:34 +00001974 println("Initial element is available immediately: $nextElement") // initial delay hasn't passed yet
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001975
paolop1d6e4932018-07-02 08:46:34 +00001976 nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements has 100ms delay
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001977 println("Next element is not ready in 50 ms: $nextElement")
1978
Roman Elizarovb5328a72018-06-06 18:31:21 +03001979 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001980 println("Next element is ready in 100 ms: $nextElement")
1981
1982 // Emulate large consumption delays
Roman Elizarovb5328a72018-06-06 18:31:21 +03001983 println("Consumer pauses for 150ms")
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001984 delay(150)
1985 // Next element is available immediately
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001986 nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001987 println("Next element is available immediately after large consumer delay: $nextElement")
1988 // Note that the pause between `receive` calls is taken into account and next element arrives faster
Roman Elizarovb5328a72018-06-06 18:31:21 +03001989 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001990 println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
1991
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001992 tickerChannel.cancel() // indicate that no more elements are needed
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001993}
1994```
1995
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001996> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-10.kt)
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001997
1998It prints following lines:
1999
2000```text
2001Initial element is available immediately: kotlin.Unit
2002Next element is not ready in 50 ms: null
2003Next element is ready in 100 ms: kotlin.Unit
Roman Elizarovb5328a72018-06-06 18:31:21 +03002004Consumer pauses for 150ms
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002005Next element is available immediately after large consumer delay: kotlin.Unit
2006Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
2007```
2008
2009<!--- TEST -->
2010
Roman Elizarovb5328a72018-06-06 18:31:21 +03002011Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
2012delay if a pause occurs, trying to maintain a fixed rate of produced elements.
2013
Roman Elizarov0c090ed2018-06-29 19:51:07 +03002014Optionally, a `mode` parameter equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
Roman Elizarovb5328a72018-06-06 18:31:21 +03002015delay between elements.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002016
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002017### Channels are fair
2018
2019Send and receive operations to channels are _fair_ with respect to the order of their invocation from
2020multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
2021gets the element. In the following example two coroutines "ping" and "pong" are
2022receiving the "ball" object from the shared "table" channel.
2023
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002024<!--- INCLUDE
2025import kotlin.coroutines.experimental.*
2026-->
2027
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002028```kotlin
2029data class Ball(var hits: Int)
2030
2031fun main(args: Array<String>) = runBlocking<Unit> {
2032 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03002033 launch(coroutineContext) { player("ping", table) }
2034 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002035 table.send(Ball(0)) // serve the ball
2036 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002037 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002038}
2039
2040suspend fun player(name: String, table: Channel<Ball>) {
2041 for (ball in table) { // receive the ball in a loop
2042 ball.hits++
2043 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03002044 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002045 table.send(ball) // send the ball back
2046 }
2047}
2048```
2049
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002050> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-09.kt)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002051
2052The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
2053coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
2054received by the "pong" coroutine, because it was already waiting for it:
2055
2056```text
2057ping Ball(hits=1)
2058pong Ball(hits=2)
2059ping Ball(hits=3)
2060pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002061```
2062
2063<!--- TEST -->
2064
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002065Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
2066that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
2067
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002068## Shared mutable state and concurrency
2069
Roman Elizarov66f018c2017-09-29 21:39:03 +03002070Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002071all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
2072Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
2073but others are unique.
2074
2075### The problem
2076
Roman Elizarov1e459602017-02-27 11:05:17 +03002077Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
2078We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002079
Roman Elizarov1e459602017-02-27 11:05:17 +03002080<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002081import java.util.concurrent.atomic.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002082-->
2083
Roman Elizarov1e459602017-02-27 11:05:17 +03002084<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002085import kotlinx.coroutines.experimental.sync.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002086-->
2087
Roman Elizarov1e459602017-02-27 11:05:17 +03002088<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002089import kotlinx.coroutines.experimental.channels.*
2090-->
2091
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002092<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
2093import kotlin.system.*
2094import kotlin.coroutines.experimental.*
2095-->
2096
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002097```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03002098suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
2099 val n = 1000 // number of coroutines to launch
2100 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002101 val time = measureTimeMillis {
2102 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03002103 launch(context) {
2104 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002105 }
2106 }
2107 jobs.forEach { it.join() }
2108 }
Roman Elizarov1e459602017-02-27 11:05:17 +03002109 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002110}
2111```
2112
Roman Elizarov43e90112017-05-10 11:25:20 +03002113<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002114
Roman Elizarov1e459602017-02-27 11:05:17 +03002115We start with a very simple action that increments a shared mutable variable using
2116multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002117
2118```kotlin
2119var counter = 0
2120
2121fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002122 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002123 counter++
2124 }
2125 println("Counter = $counter")
2126}
2127```
2128
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002129> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002130
Roman Elizarov1e459602017-02-27 11:05:17 +03002131<!--- TEST LINES_START
2132Completed 1000000 actions in
2133Counter =
2134-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002135
Roman Elizarov1e459602017-02-27 11:05:17 +03002136What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
2137increment the `counter` concurrently from multiple threads without any synchronization.
2138
Roman Elizarov43e90112017-05-10 11:25:20 +03002139> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
2140`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
2141following change:
2142
2143```kotlin
2144val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
2145var counter = 0
2146
2147fun main(args: Array<String>) = runBlocking<Unit> {
2148 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
2149 counter++
2150 }
2151 println("Counter = $counter")
2152}
2153```
2154
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002155> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt)
Roman Elizarov43e90112017-05-10 11:25:20 +03002156
2157<!--- TEST LINES_START
2158Completed 1000000 actions in
2159Counter =
2160-->
2161
Roman Elizarov1e459602017-02-27 11:05:17 +03002162### Volatiles are of no help
2163
2164There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
2165
2166```kotlin
2167@Volatile // in Kotlin `volatile` is an annotation
2168var counter = 0
2169
2170fun main(args: Array<String>) = runBlocking<Unit> {
2171 massiveRun(CommonPool) {
2172 counter++
2173 }
2174 println("Counter = $counter")
2175}
2176```
2177
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002178> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03002179
2180<!--- TEST LINES_START
2181Completed 1000000 actions in
2182Counter =
2183-->
2184
2185This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
2186linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
2187do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002188
2189### Thread-safe data structures
2190
2191The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
2192linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
2193operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03002194In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002195
2196```kotlin
2197var counter = AtomicInteger()
2198
2199fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002200 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002201 counter.incrementAndGet()
2202 }
2203 println("Counter = ${counter.get()}")
2204}
2205```
2206
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002207> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002208
Roman Elizarov1e459602017-02-27 11:05:17 +03002209<!--- TEST ARBITRARY_TIME
2210Completed 1000000 actions in xxx ms
2211Counter = 1000000
2212-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002213
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002214This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
2215standard data structures and basic operations on them. However, it does not easily scale to complex
2216state or to complex operations that do not have ready-to-use thread-safe implementations.
2217
Roman Elizarov1e459602017-02-27 11:05:17 +03002218### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002219
Roman Elizarov1e459602017-02-27 11:05:17 +03002220_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 +03002221state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
2222the single event-dispatch/application thread. It is easy to apply with coroutines by using a
2223single-threaded context:
2224
2225```kotlin
2226val counterContext = newSingleThreadContext("CounterContext")
2227var counter = 0
2228
2229fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002230 massiveRun(CommonPool) { // run each coroutine in CommonPool
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002231 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002232 counter++
2233 }
2234 }
2235 println("Counter = $counter")
2236}
2237```
2238
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002239> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002240
Roman Elizarov1e459602017-02-27 11:05:17 +03002241<!--- TEST ARBITRARY_TIME
2242Completed 1000000 actions in xxx ms
2243Counter = 1000000
2244-->
2245
2246This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002247from multi-threaded `CommonPool` context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03002248
2249### Thread confinement coarse-grained
2250
2251In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
2252are confined to the single thread. The following example does it like that, running each coroutine in
2253the single-threaded context to start with.
2254
2255```kotlin
2256val counterContext = newSingleThreadContext("CounterContext")
2257var counter = 0
2258
2259fun main(args: Array<String>) = runBlocking<Unit> {
2260 massiveRun(counterContext) { // run each coroutine in the single-threaded context
2261 counter++
2262 }
2263 println("Counter = $counter")
2264}
2265```
2266
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002267> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-05.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03002268
2269<!--- TEST ARBITRARY_TIME
2270Completed 1000000 actions in xxx ms
2271Counter = 1000000
2272-->
2273
2274This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002275
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002276### Mutual exclusion
2277
2278Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
2279that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
2280Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
paolop1d6e4932018-07-02 08:46:34 +00002281delimit 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 +03002282
Roman Elizarov88396732017-09-27 21:30:47 +03002283There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002284`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
2285
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002286```kotlin
2287val mutex = Mutex()
2288var counter = 0
2289
2290fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002291 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002292 mutex.withLock {
2293 counter++
2294 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002295 }
2296 println("Counter = $counter")
2297}
2298```
2299
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002300> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002301
Roman Elizarov1e459602017-02-27 11:05:17 +03002302<!--- TEST ARBITRARY_TIME
2303Completed 1000000 actions in xxx ms
2304Counter = 1000000
2305-->
2306
2307The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
2308where you absolutely must modify some shared state periodically, but there is no natural thread that this state
2309is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002310
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002311### Actors
2312
paolop1d6e4932018-07-02 08:46:34 +00002313An [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 +03002314and a channel to communicate with other coroutines. A simple actor can be written as a function,
2315but an actor with a complex state is better suited for a class.
2316
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002317There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
2318scope to receive messages from and combines the send channel into the resulting job object, so that a
2319single reference to the actor can be carried around as its handle.
2320
Roman Elizarov256812a2017-07-22 01:00:30 +03002321The first step of using an actor is to define a class of messages that an actor is going to process.
2322Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
2323We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
2324to get its value. The later needs to send a response. A [CompletableDeferred] communication
2325primitive, that represents a single value that will be known (communicated) in the future,
2326is used here for that purpose.
2327
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002328```kotlin
2329// Message types for counterActor
2330sealed class CounterMsg
2331object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03002332class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
2333```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002334
Roman Elizarov256812a2017-07-22 01:00:30 +03002335Then we define a function that launches an actor using an [actor] coroutine builder:
2336
2337```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002338// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03002339fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002340 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002341 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002342 when (msg) {
2343 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03002344 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002345 }
2346 }
2347}
Roman Elizarov256812a2017-07-22 01:00:30 +03002348```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002349
Roman Elizarov256812a2017-07-22 01:00:30 +03002350The main code is straightforward:
2351
2352```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002353fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002354 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03002355 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002356 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002357 }
Roman Elizarov256812a2017-07-22 01:00:30 +03002358 // send a message to get a counter value from an actor
2359 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002360 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03002361 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002362 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002363}
2364```
2365
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002366> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002367
Roman Elizarov1e459602017-02-27 11:05:17 +03002368<!--- TEST ARBITRARY_TIME
2369Completed 1000000 actions in xxx ms
2370Counter = 1000000
2371-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002372
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002373It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002374a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
paolop1d6e4932018-07-02 08:46:34 +00002375works 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 +03002376
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002377Actor is more efficient than locking under load, because in this case it always has work to do and it does not
2378have to switch to a different context at all.
2379
2380> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
2381 with the channel that it receives messages from, while a producer is associated with the channel that it
2382 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03002383
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002384## Select expression
2385
Roman Elizarova84730b2017-02-22 11:58:50 +03002386Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002387the first one that becomes available.
2388
2389<!--- INCLUDE .*/example-select-([0-9]+).kt
2390import kotlinx.coroutines.experimental.channels.*
2391import kotlinx.coroutines.experimental.selects.*
2392-->
2393
2394### Selecting from channels
2395
Roman Elizarov57857202017-03-02 23:17:25 +03002396Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2397
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002398<!--- INCLUDE
2399import kotlinx.coroutines.experimental.*
2400import kotlin.coroutines.experimental.*
Roman Elizarov57857202017-03-02 23:17:25 +03002401-->
2402
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002403```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002404fun fizz(context: CoroutineContext) = produce<String>(context) {
2405 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002406 delay(300)
2407 send("Fizz")
2408 }
2409}
2410```
2411
Roman Elizarov57857202017-03-02 23:17:25 +03002412And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002413
2414```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002415fun buzz(context: CoroutineContext) = produce<String>(context) {
2416 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002417 delay(500)
2418 send("Buzz!")
2419 }
2420}
2421```
2422
2423Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2424other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002425[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002426
2427```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002428suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002429 select<Unit> { // <Unit> means that this select expression does not produce any result
2430 fizz.onReceive { value -> // this is the first select clause
2431 println("fizz -> '$value'")
2432 }
2433 buzz.onReceive { value -> // this is the second select clause
2434 println("buzz -> '$value'")
2435 }
2436 }
2437}
2438```
2439
Roman Elizarov57857202017-03-02 23:17:25 +03002440Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002441
2442```kotlin
2443fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002444 val fizz = fizz(coroutineContext)
2445 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002446 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002447 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002448 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002449 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002450}
2451```
2452
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002453> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-01.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002454
2455The result of this code is:
2456
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002457```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002458fizz -> 'Fizz'
2459buzz -> 'Buzz!'
2460fizz -> 'Fizz'
2461fizz -> 'Fizz'
2462buzz -> 'Buzz!'
2463fizz -> 'Fizz'
2464buzz -> 'Buzz!'
2465```
2466
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002467<!--- TEST -->
2468
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002469### Selecting on close
2470
paolop1d6e4932018-07-02 08:46:34 +00002471The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
2472`select` to throw an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002473specific 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 +03002474the result of its selected clause:
2475
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002476<!--- INCLUDE
2477import kotlin.coroutines.experimental.*
2478-->
2479
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002480```kotlin
2481suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2482 select<String> {
2483 a.onReceiveOrNull { value ->
2484 if (value == null)
2485 "Channel 'a' is closed"
2486 else
2487 "a -> '$value'"
2488 }
2489 b.onReceiveOrNull { value ->
2490 if (value == null)
2491 "Channel 'b' is closed"
2492 else
2493 "b -> '$value'"
2494 }
2495 }
2496```
2497
Roman Elizarova84730b2017-02-22 11:58:50 +03002498Let's use it with channel `a` that produces "Hello" string four times and
2499channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002500
2501```kotlin
2502fun main(args: Array<String>) = runBlocking<Unit> {
2503 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002504 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002505 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002506 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002507 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002508 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002509 }
2510 repeat(8) { // print first eight results
2511 println(selectAorB(a, b))
2512 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002513 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002514}
2515```
2516
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002517> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-02.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002518
Roman Elizarova84730b2017-02-22 11:58:50 +03002519The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002520
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002521```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002522a -> 'Hello 0'
2523a -> 'Hello 1'
2524b -> 'World 0'
2525a -> 'Hello 2'
2526a -> 'Hello 3'
2527b -> 'World 1'
2528Channel 'a' is closed
2529Channel 'a' is closed
2530```
2531
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002532<!--- TEST -->
2533
Roman Elizarova84730b2017-02-22 11:58:50 +03002534There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002535
2536First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2537the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002538being 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 +03002539time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2540
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002541The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002542channel is already closed.
2543
2544### Selecting to send
2545
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002546Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002547with a biased nature of selection.
2548
Roman Elizarova84730b2017-02-22 11:58:50 +03002549Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002550the consumers on its primary channel cannot keep up with it:
2551
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002552<!--- INCLUDE
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002553import kotlin.coroutines.experimental.*
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002554-->
2555
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002556```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002557fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002558 for (num in 1..10) { // produce 10 numbers from 1 to 10
2559 delay(100) // every 100 ms
2560 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002561 onSend(num) {} // Send to the primary channel
2562 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002563 }
2564 }
2565}
2566```
2567
2568Consumer is going to be quite slow, taking 250 ms to process each number:
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002569
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002570```kotlin
2571fun main(args: Array<String>) = runBlocking<Unit> {
2572 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002573 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002574 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002575 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002576 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002577 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002578 delay(250) // let us digest the consumed number properly, do not hurry
2579 }
2580 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002581 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002582}
2583```
2584
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002585> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-03.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002586
2587So let us see what happens:
2588
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002589```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002590Consuming 1
2591Side channel has 2
2592Side channel has 3
2593Consuming 4
2594Side channel has 5
2595Side channel has 6
2596Consuming 7
2597Side channel has 8
2598Side channel has 9
2599Consuming 10
2600Done consuming
2601```
2602
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002603<!--- TEST -->
2604
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002605### Selecting deferred values
2606
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002607Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002608Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002609a random delay:
2610
2611<!--- INCLUDE .*/example-select-04.kt
2612import java.util.*
2613-->
2614
2615```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002616fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002617 delay(time.toLong())
2618 "Waited for $time ms"
2619}
2620```
2621
Roman Elizarova84730b2017-02-22 11:58:50 +03002622Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002623
2624```kotlin
2625fun asyncStringsList(): List<Deferred<String>> {
2626 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002627 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002628}
2629```
2630
Roman Elizarova84730b2017-02-22 11:58:50 +03002631Now 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 +03002632that 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 +03002633so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2634of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002635
2636```kotlin
2637fun main(args: Array<String>) = runBlocking<Unit> {
2638 val list = asyncStringsList()
2639 val result = select<String> {
2640 list.withIndex().forEach { (index, deferred) ->
2641 deferred.onAwait { answer ->
2642 "Deferred $index produced answer '$answer'"
2643 }
2644 }
2645 }
2646 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002647 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002648 println("$countActive coroutines are still active")
2649}
2650```
2651
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002652> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-04.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002653
2654The output is:
2655
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002656```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002657Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300265811 coroutines are still active
2659```
2660
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002661<!--- TEST -->
2662
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002663### Switch over a channel of deferred values
2664
Roman Elizarova84730b2017-02-22 11:58:50 +03002665Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2666deferred 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 +03002667[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002668
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002669<!--- INCLUDE
2670import kotlin.coroutines.experimental.*
2671-->
2672
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002673```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002674fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002675 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002676 while (isActive) { // loop while not cancelled/closed
2677 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2678 input.onReceiveOrNull { update ->
2679 update // replaces next value to wait
2680 }
2681 current.onAwait { value ->
2682 send(value) // send value that current deferred has produced
2683 input.receiveOrNull() // and use the next deferred from the input channel
2684 }
2685 }
2686 if (next == null) {
2687 println("Channel was closed")
2688 break // out of loop
2689 } else {
2690 current = next
2691 }
2692 }
2693}
2694```
2695
2696To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2697
2698```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002699fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002700 delay(time)
2701 str
2702}
2703```
2704
2705The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2706data to it:
2707
2708```kotlin
2709fun main(args: Array<String>) = runBlocking<Unit> {
2710 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002711 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002712 for (s in switchMapDeferreds(chan))
2713 println(s) // print each received string
2714 }
2715 chan.send(asyncString("BEGIN", 100))
2716 delay(200) // enough time for "BEGIN" to be produced
2717 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002718 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002719 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002720 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002721 chan.send(asyncString("END", 500))
2722 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002723 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002724 delay(500) // and wait some time to let it finish
2725}
2726```
2727
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002728> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-05.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002729
2730The result of this code:
2731
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002732```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002733BEGIN
2734Replace
2735END
2736Channel was closed
2737```
2738
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002739<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002740
Roman Elizarov8db17332017-03-09 12:40:45 +03002741## Further reading
2742
2743* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002744* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002745* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2746* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2747
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002748<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002749<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002750[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2751[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2752[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002753[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002754[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002755[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2756[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03002757[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002758[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002759[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 +03002760[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002761[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002762[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2763[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002764[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 +03002765[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2766[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002767[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 +03002768[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2769[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002770[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002771[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002772[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002773[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002774[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2775[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 +03002776[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002777[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002778[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03002779[CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-exception-handler/index.html
Roman Elizarov3e387b82017-12-04 13:49:11 +03002780[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 +03002781[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002782[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 +03002783<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002784[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002785[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2786[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 +03002787[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002788<!--- INDEX kotlinx.coroutines.experimental.channels -->
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03002789[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
2790[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
2791[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002792[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002793[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002794[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/close.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002795[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002796[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002797[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/ticker.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002798[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 +03002799[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
Roman Elizarovb5328a72018-06-06 18:31:21 +03002800[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 +03002801[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2802[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 +03002803<!--- INDEX kotlinx.coroutines.experimental.selects -->
2804[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002805<!--- END -->