blob: c1d8679ad39a4971b929b10d835af79549059662 [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 Tolstopyatove3425972018-08-22 19:41:57 +030070 * [Thread-local data](#thread-local-data)
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +030071* [Exception handling](#exception-handling)
72 * [Exception propagation](#exception-propagation)
73 * [CoroutineExceptionHandler](#coroutineexceptionhandler)
74 * [Cancellation and exceptions](#cancellation-and-exceptions)
75 * [Exceptions aggregation](#exceptions-aggregation)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030076* [Channels](#channels)
77 * [Channel basics](#channel-basics)
78 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
79 * [Building channel producers](#building-channel-producers)
80 * [Pipelines](#pipelines)
81 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
82 * [Fan-out](#fan-out)
83 * [Fan-in](#fan-in)
84 * [Buffered channels](#buffered-channels)
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +030085 * [Ticker channels](#ticker-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030086 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030087* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
88 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030089 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030090 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030091 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
92 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030093 * [Mutual exclusion](#mutual-exclusion)
94 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +030095* [Select expression](#select-expression)
96 * [Selecting from channels](#selecting-from-channels)
97 * [Selecting on close](#selecting-on-close)
98 * [Selecting to send](#selecting-to-send)
99 * [Selecting deferred values](#selecting-deferred-values)
100 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +0300101* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300102
Roman Elizarova5e653f2017-02-13 13:49:55 +0300103<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300104
105## Coroutine basics
106
107This section covers basic coroutine concepts.
108
109### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300110
111Run the following code:
112
113```kotlin
114fun main(args: Array<String>) {
Roman Elizarova4d45d22017-11-20 16:47:09 +0300115 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300116 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
117 println("World!") // print after delay
118 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300119 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300120 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
121}
122```
123
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300124> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300125
126Run this code:
127
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300128```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300129Hello,
130World!
131```
132
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300133<!--- TEST -->
134
Roman Elizarov419a6c82017-02-09 18:36:22 +0300135Essentially, coroutines are light-weight threads.
136They are launched with [launch] _coroutine builder_.
137You can achieve the same result replacing
Roman Elizarov66f018c2017-09-29 21:39:03 +0300138`launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300139
Roman Elizarov66f018c2017-09-29 21:39:03 +0300140If you start by replacing `launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300141
142```
143Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
144```
145
Roman Elizarov419a6c82017-02-09 18:36:22 +0300146That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300147coroutine and it can be only used from a coroutine.
148
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300149### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300150
Roman Elizarova4d45d22017-11-20 16:47:09 +0300151The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
152It is easy to get lost which one is blocking and which one is not.
153Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300154
155```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300156fun main(args: Array<String>) {
157 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300158 delay(1000L)
159 println("World!")
160 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300161 println("Hello,") // main thread continues here immediately
162 runBlocking { // but this expression blocks the main thread
163 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
164 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300165}
166```
167
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300168> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300169
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300170<!--- TEST
171Hello,
172World!
173-->
174
Roman Elizarov419a6c82017-02-09 18:36:22 +0300175The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100176The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300177
Roman Elizarova4d45d22017-11-20 16:47:09 +0300178This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
179the execution of the main function:
180
181```kotlin
182fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
183 launch { // launch new coroutine in background and continue
184 delay(1000L)
185 println("World!")
186 }
187 println("Hello,") // main coroutine continues here immediately
188 delay(2000L) // delaying for 2 seconds to keep JVM alive
189}
190```
191
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300192> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt)
Roman Elizarova4d45d22017-11-20 16:47:09 +0300193
194<!--- TEST
195Hello,
196World!
197-->
198
199Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
200We 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 +0300201
202This is also a way to write unit-tests for suspending functions:
203
204```kotlin
205class MyTest {
206 @Test
207 fun testMySuspendingFunction() = runBlocking<Unit> {
208 // here we can use suspending functions using any assertion style that we like
209 }
210}
211```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300212
213<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300214
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300215### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300216
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300217Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300218wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300219
220```kotlin
221fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300222 val job = launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300223 delay(1000L)
224 println("World!")
225 }
226 println("Hello,")
227 job.join() // wait until child coroutine completes
228}
229```
230
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300231> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300232
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300233<!--- TEST
234Hello,
235World!
236-->
237
Roman Elizarov7deefb82017-01-31 10:33:17 +0300238Now 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 +0300239the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300240
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300241### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300242
Roman Elizarov66f018c2017-09-29 21:39:03 +0300243Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300244perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
245That is your first _suspending function_. Suspending functions can be used inside coroutines
246just like regular functions, but their additional feature is that they can, in turn,
247use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
248
249```kotlin
250fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300251 val job = launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300252 println("Hello,")
253 job.join()
254}
255
256// this is your first suspending function
257suspend fun doWorld() {
258 delay(1000L)
259 println("World!")
260}
261```
262
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300263> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300264
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300265<!--- TEST
266Hello,
267World!
268-->
269
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300270### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300271
272Run the following code:
273
274```kotlin
275fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300276 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
277 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300278 delay(1000L)
279 print(".")
280 }
281 }
282 jobs.forEach { it.join() } // wait for all jobs to complete
283}
284```
285
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300286> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300287
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300288<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
289
Roman Elizarov66f018c2017-09-29 21:39:03 +0300290It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300291Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
292
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300293### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300294
295The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300296returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300297
298```kotlin
299fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300300 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300301 repeat(1000) { i ->
302 println("I'm sleeping $i ...")
303 delay(500L)
304 }
305 }
306 delay(1300L) // just quit after delay
307}
308```
309
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300310> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300311
312You can run and see that it prints three lines and terminates:
313
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300314```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300315I'm sleeping 0 ...
316I'm sleeping 1 ...
317I'm sleeping 2 ...
318```
319
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300320<!--- TEST -->
321
Roman Elizarov7deefb82017-01-31 10:33:17 +0300322Active coroutines do not keep the process alive. They are like daemon threads.
323
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300324## Cancellation and timeouts
325
326This section covers coroutine cancellation and timeouts.
327
328### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300329
Brad977ada12018-07-19 16:01:40 -0400330In a small application the return from "main" method might sound like a good idea to get all coroutines
331implicitly terminated but in a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300332The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300333
334```kotlin
335fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300336 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300337 repeat(1000) { i ->
338 println("I'm sleeping $i ...")
339 delay(500L)
340 }
341 }
342 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300343 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300344 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300345 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300346 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300347}
348```
349
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300350> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300351
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300352It produces the following output:
353
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300354```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300355I'm sleeping 0 ...
356I'm sleeping 1 ...
357I'm sleeping 2 ...
358main: I'm tired of waiting!
359main: Now I can quit.
360```
361
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300362<!--- TEST -->
363
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300364As 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 +0300365There is also a [Job] extension function [cancelAndJoin]
366that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300367
368### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300369
Tair Rzayevaf734622017-02-01 22:30:16 +0200370Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300371All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300372coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300373a computation and does not check for cancellation, then it cannot be cancelled, like the following
374example shows:
375
376```kotlin
377fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700378 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300379 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700380 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300381 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300382 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700383 // print a message twice a second
384 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300385 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300386 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300387 }
388 }
389 }
390 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300391 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300392 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300393 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300394}
395```
396
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300397> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300398
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300399Run it to see that it continues to print "I'm sleeping" even after cancellation
400until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300401
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300402<!--- TEST
403I'm sleeping 0 ...
404I'm sleeping 1 ...
405I'm sleeping 2 ...
406main: I'm tired of waiting!
407I'm sleeping 3 ...
408I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300409main: Now I can quit.
410-->
411
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300412### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300413
414There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300415invoke 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 +0300416The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300417
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300418Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300419
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300420```kotlin
421fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700422 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300423 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700424 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300425 var i = 0
426 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700427 // print a message twice a second
428 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300429 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700430 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300431 }
432 }
433 }
434 delay(1300L) // delay a bit
435 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300436 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300437 println("main: Now I can quit.")
438}
439```
440
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300441> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300442
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300443As 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 +0300444the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300445
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300446<!--- TEST
447I'm sleeping 0 ...
448I'm sleeping 1 ...
449I'm sleeping 2 ...
450main: I'm tired of waiting!
451main: Now I can quit.
452-->
453
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300454### Closing resources with finally
455
Roman Elizarov419a6c82017-02-09 18:36:22 +0300456Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Brad977ada12018-07-19 16:01:40 -0400457the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300458finalization actions normally when coroutine is cancelled:
459
460```kotlin
461fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300462 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300463 try {
464 repeat(1000) { i ->
465 println("I'm sleeping $i ...")
466 delay(500L)
467 }
468 } finally {
469 println("I'm running finally")
470 }
471 }
472 delay(1300L) // delay a bit
473 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300474 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300475 println("main: Now I can quit.")
476}
477```
478
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300479> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300480
Roman Elizarov88396732017-09-27 21:30:47 +0300481Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
482so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300483
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300484```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300485I'm sleeping 0 ...
486I'm sleeping 1 ...
487I'm sleeping 2 ...
488main: I'm tired of waiting!
489I'm running finally
490main: Now I can quit.
491```
492
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300493<!--- TEST -->
494
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300495### Run non-cancellable block
496
497Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300498[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300499problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
500communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
501rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300502`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300503
504```kotlin
505fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300506 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300507 try {
508 repeat(1000) { i ->
509 println("I'm sleeping $i ...")
510 delay(500L)
511 }
512 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300513 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300514 println("I'm running finally")
515 delay(1000L)
516 println("And I've just delayed for 1 sec because I'm non-cancellable")
517 }
518 }
519 }
520 delay(1300L) // delay a bit
521 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300522 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300523 println("main: Now I can quit.")
524}
525```
526
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300527> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300528
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300529<!--- TEST
530I'm sleeping 0 ...
531I'm sleeping 1 ...
532I'm sleeping 2 ...
533main: I'm tired of waiting!
534I'm running finally
535And I've just delayed for 1 sec because I'm non-cancellable
536main: Now I can quit.
537-->
538
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300539### Timeout
540
Brad977ada12018-07-19 16:01:40 -0400541The most obvious reason to cancel coroutine execution in practice
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300542is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300543While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
544the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300545Look at the following example:
546
547```kotlin
548fun main(args: Array<String>) = runBlocking<Unit> {
549 withTimeout(1300L) {
550 repeat(1000) { i ->
551 println("I'm sleeping $i ...")
552 delay(500L)
553 }
554 }
555}
556```
557
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300558> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300559
560It produces the following output:
561
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300562```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300563I'm sleeping 0 ...
564I'm sleeping 1 ...
565I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300566Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300567```
568
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300569<!--- TEST STARTS_WITH -->
570
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300571The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300572We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300573inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300574However, in this example we have used `withTimeout` right inside the `main` function.
575
576Because cancellation is just an exception, all the resources will be closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300577You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
578you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300579that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
580
581```kotlin
582fun main(args: Array<String>) = runBlocking<Unit> {
583 val result = withTimeoutOrNull(1300L) {
584 repeat(1000) { i ->
585 println("I'm sleeping $i ...")
586 delay(500L)
587 }
588 "Done" // will get cancelled before it produces this result
589 }
590 println("Result is $result")
591}
592```
593
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300594> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300595
596There is no longer an exception when running this code:
597
598```text
599I'm sleeping 0 ...
600I'm sleeping 1 ...
601I'm sleeping 2 ...
602Result is null
603```
604
605<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300606
607## Composing suspending functions
608
609This section covers various approaches to composition of suspending functions.
610
611### Sequential by default
612
613Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300614remote service call or computation. We just pretend they are useful, but actually each one just
615delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300616
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300617<!--- INCLUDE .*/example-compose-([0-9]+).kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300618import kotlin.system.*
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300619-->
620
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300621```kotlin
622suspend fun doSomethingUsefulOne(): Int {
623 delay(1000L) // pretend we are doing something useful here
624 return 13
625}
626
627suspend fun doSomethingUsefulTwo(): Int {
628 delay(1000L) // pretend we are doing something useful here, too
629 return 29
630}
631```
632
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300633<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
634
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300635What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
636`doSomethingUsefulTwo` and compute the sum of their results?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200637In 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 +0300638to invoke the second one or to decide on how to invoke it.
639
640We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300641code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300642time it takes to execute both suspending functions:
643
644```kotlin
645fun main(args: Array<String>) = runBlocking<Unit> {
646 val time = measureTimeMillis {
647 val one = doSomethingUsefulOne()
648 val two = doSomethingUsefulTwo()
649 println("The answer is ${one + two}")
650 }
651 println("Completed in $time ms")
652}
653```
654
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300655> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300656
657It produces something like this:
658
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300659```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300660The answer is 42
661Completed in 2017 ms
662```
663
Roman Elizarov35d2c342017-07-20 14:54:39 +0300664<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300665
Roman Elizarov32d95322017-02-09 15:57:31 +0300666### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300667
668What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300669we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300670
Roman Elizarov419a6c82017-02-09 18:36:22 +0300671Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
672that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
673does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300674that 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 +0300675but `Deferred` is also a `Job`, so you can cancel it if needed.
676
677```kotlin
678fun main(args: Array<String>) = runBlocking<Unit> {
679 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300680 val one = async { doSomethingUsefulOne() }
681 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300682 println("The answer is ${one.await() + two.await()}")
683 }
684 println("Completed in $time ms")
685}
686```
687
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300688> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300689
690It produces something like this:
691
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300692```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300693The answer is 42
694Completed in 1017 ms
695```
696
Roman Elizarov35d2c342017-07-20 14:54:39 +0300697<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300698
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300699This is twice as fast, because we have concurrent execution of two coroutines.
700Note, that concurrency with coroutines is always explicit.
701
Roman Elizarov32d95322017-02-09 15:57:31 +0300702### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300703
Roman Elizarov66f018c2017-09-29 21:39:03 +0300704There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300705It starts coroutine only when its result is needed by some
706[await][Deferred.await] or if a [start][Job.start] function
Sahil Lone52a0ec02018-07-19 18:55:35 +0200707is invoked. Run the following example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300708
709```kotlin
710fun main(args: Array<String>) = runBlocking<Unit> {
711 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300712 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
713 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Sahil Lone52a0ec02018-07-19 18:55:35 +0200714 // some computation
715 one.start() // start the first one
716 two.start() // start the second one
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300717 println("The answer is ${one.await() + two.await()}")
718 }
719 println("Completed in $time ms")
720}
721```
722
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300723> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300724
725It produces something like this:
726
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300727```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300728The answer is 42
Sahil Lone52a0ec02018-07-19 18:55:35 +0200729Completed in 1017 ms
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300730```
731
Roman Elizarov35d2c342017-07-20 14:54:39 +0300732<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300733
Sahil Lone52a0ec02018-07-19 18:55:35 +0200734So, here the two coroutines are defined but not executed as in the previous example, but the control is given to
735the programmer about when exactly to start the execution by calling [start][Job.start] on it. We first
736start `one`, then start `two`, and then await for the individual coroutines to finish.
737
738Note, that if we have called [await][Deferred.await] in `println` and omitted [start][Job.start] on individual
739coroutines, then we would have got the sequential behaviour as [await][Deferred.await] starts the coroutine
740execution and waits for the execution to finish, which is not the intended use-case for laziness.
741The use-case for `async(start = CoroutineStart.LAZY)` is a replacement for the
742standard `lazy` function in cases when computation of the value involves suspending functions.
Roman Elizarov32d95322017-02-09 15:57:31 +0300743
744### Async-style functions
745
746We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300747_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100748"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
749to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300750
751```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100752// The result type of somethingUsefulOneAsync is Deferred<Int>
753fun somethingUsefulOneAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300754 doSomethingUsefulOne()
755}
756
Marcin Moskała7e94e702018-01-29 18:39:02 +0100757// The result type of somethingUsefulTwoAsync is Deferred<Int>
758fun somethingUsefulTwoAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300759 doSomethingUsefulTwo()
760}
761```
762
Marcin Moskała7e94e702018-01-29 18:39:02 +0100763Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300764However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
765with the invoking code.
766
767The following example shows their use outside of coroutine:
768
769```kotlin
770// note, that we don't have `runBlocking` to the right of `main` in this example
771fun main(args: Array<String>) {
772 val time = measureTimeMillis {
773 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100774 val one = somethingUsefulOneAsync()
775 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300776 // but waiting for a result must involve either suspending or blocking.
777 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
778 runBlocking {
779 println("The answer is ${one.await() + two.await()}")
780 }
781 }
782 println("Completed in $time ms")
783}
784```
785
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300786> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300787
Roman Elizarov35d2c342017-07-20 14:54:39 +0300788<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300789The answer is 42
790Completed in 1085 ms
791-->
792
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300793## Coroutine context and dispatchers
794
Roman Elizarov66f018c2017-09-29 21:39:03 +0300795Coroutines always execute in some context which is represented by the value of
796[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
797type, defined in the Kotlin standard library.
798
799The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
800which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300801
802### Dispatchers and threads
803
Roman Elizarov66f018c2017-09-29 21:39:03 +0300804Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300805the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +0300806to a specific thread, dispatch it to a thread pool, or let it run unconfined.
807
808All coroutines builders like [launch] and [async] accept an optional
809[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
810parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
811
812Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300813
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300814<!--- INCLUDE
815import kotlin.coroutines.experimental.*
816-->
817
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300818```kotlin
819fun main(args: Array<String>) = runBlocking<Unit> {
820 val jobs = arrayListOf<Job>()
821 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300822 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300823 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300824 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
825 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300826 }
827 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300828 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300829 }
830 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300831 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300832 }
833 jobs.forEach { it.join() }
834}
835```
836
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300837> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300838
839It produces the following output (maybe in different order):
840
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300841```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300842 'Unconfined': I'm working in thread main
843 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
844 'newSTC': I'm working in thread MyOwnThread
845'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300846```
847
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300848<!--- TEST LINES_START_UNORDERED -->
849
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800850The default dispatcher that we've used in previous sections is representend by [DefaultDispatcher], which
Roman Elizarov66f018c2017-09-29 21:39:03 +0300851is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same
Charles Muchenefa13beb2018-01-08 16:56:54 +0300852as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300853
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300854The difference between parent
855[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html) and
Roman Elizarov43e3af72017-07-21 16:01:31 +0300856[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300857
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800858Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource.
859In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
860function, or stored in a top-level variable and reused throughout the application.
861
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300862### Unconfined vs confined dispatcher
863
Roman Elizarov419a6c82017-02-09 18:36:22 +0300864The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300865first suspension point. After suspension it resumes in the thread that is fully determined by the
866suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
867consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
868
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300869On the other side,
870[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
871property, that is available inside any coroutine, is a reference to a context of this particular coroutine.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300872This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
873is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300874this thread with a predictable FIFO scheduling.
875
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300876<!--- INCLUDE
877import kotlin.coroutines.experimental.*
878-->
879
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300880```kotlin
881fun main(args: Array<String>) = runBlocking<Unit> {
882 val jobs = arrayListOf<Job>()
883 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300884 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300885 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300886 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300887 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300888 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
889 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300890 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300891 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300892 }
893 jobs.forEach { it.join() }
894}
895```
896
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300897> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300898
899Produces the output:
900
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300901```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300902 'Unconfined': I'm working in thread main
903'coroutineContext': I'm working in thread main
904 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
905'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300906```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300907
908<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300909
Roman Elizarov43e3af72017-07-21 16:01:31 +0300910So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
911in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
912function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300913
914### Debugging coroutines and threads
915
Roman Elizarov419a6c82017-02-09 18:36:22 +0300916Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
Roman Elizarov66f018c2017-09-29 21:39:03 +0300917with a default multi-threaded dispatcher. Even with a single-threaded dispatcher it might be hard to
paolopb019b102018-06-09 16:42:24 +0000918figure out what coroutine was doing, where, and when. The common approach to debugging applications with
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300919threads is to print the thread name in the log file on each log statement. This feature is universally supported
920by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
921`kotlinx.coroutines` includes debugging facilities to make it easier.
922
923Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
924
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300925<!--- INCLUDE
926import kotlin.coroutines.experimental.*
927-->
928
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300929```kotlin
930fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
931
932fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300933 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300934 log("I'm computing a piece of the answer")
935 6
936 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300937 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300938 log("I'm computing another piece of the answer")
939 7
940 }
941 log("The answer is ${a.await() * b.await()}")
942}
943```
944
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300945> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300946
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300947There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300948and two coroutines computing deferred values `a` (#2) and `b` (#3).
949They are all executing in the context of `runBlocking` and are confined to the main thread.
950The output of this code is:
951
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300952```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300953[main @coroutine#2] I'm computing a piece of the answer
954[main @coroutine#3] I'm computing another piece of the answer
955[main @coroutine#1] The answer is 42
956```
957
Kirill Timofeeva5186962017-10-25 14:25:47 +0300958<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300959
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300960The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
961thread, but the identifier of the currently executing coroutine is appended to it. This identifier
962is consecutively assigned to all created coroutines when debugging mode is turned on.
963
Roman Elizarov419a6c82017-02-09 18:36:22 +0300964You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300965
966### Jumping between threads
967
968Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
969
970```kotlin
971fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
972
973fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800974 newSingleThreadContext("Ctx1").use { ctx1 ->
975 newSingleThreadContext("Ctx2").use { ctx2 ->
976 runBlocking(ctx1) {
977 log("Started in ctx1")
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300978 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800979 log("Working in ctx2")
980 }
981 log("Back to ctx1")
982 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300983 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300984 }
985}
986```
987
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300988> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300989
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800990It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300991the 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 +0300992same coroutine as you can see in the output below:
993
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300994```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300995[Ctx1 @coroutine#1] Started in ctx1
996[Ctx2 @coroutine#1] Working in ctx2
997[Ctx1 @coroutine#1] Back to ctx1
998```
999
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001000<!--- TEST -->
1001
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001002
Artsiom Chapialioue185ed62018-06-03 19:34:22 -04001003Note, that this example also uses `use` function from the Kotlin standard library to release threads that
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001004are created with [newSingleThreadContext] when they are no longer needed.
1005
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001006### Job in the context
1007
Roman Elizarov66f018c2017-09-29 21:39:03 +03001008The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001009using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001010
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001011<!--- INCLUDE
1012import kotlin.coroutines.experimental.*
1013-->
1014
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001015```kotlin
1016fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001017 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001018}
1019```
1020
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001021> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001022
Roman Elizarov66f018c2017-09-29 21:39:03 +03001023It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001024
1025```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001026My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001027```
1028
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001029<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001030
Roman Elizarov43e3af72017-07-21 16:01:31 +03001031So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001032`coroutineContext[Job]?.isActive == true`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001033
1034### Children of a coroutine
1035
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001036When
1037[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
1038of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +03001039the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001040a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1041are recursively cancelled, too.
1042
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001043<!--- INCLUDE
1044import kotlin.coroutines.experimental.*
1045-->
1046
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001047```kotlin
1048fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001049 // launch a coroutine to process some kind of incoming request
1050 val request = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001051 // it spawns two other jobs, one with its separate context
Roman Elizarov66f018c2017-09-29 21:39:03 +03001052 val job1 = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001053 println("job1: I have my own context and execute independently!")
1054 delay(1000)
1055 println("job1: I am not affected by cancellation of the request")
1056 }
1057 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001058 val job2 = launch(coroutineContext) {
Roman Elizarov74619c12017-11-09 10:32:15 +03001059 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001060 println("job2: I am a child of the request coroutine")
1061 delay(1000)
1062 println("job2: I will not execute this line if my parent request is cancelled")
1063 }
1064 // request completes when both its sub-jobs complete:
1065 job1.join()
1066 job2.join()
1067 }
1068 delay(500)
1069 request.cancel() // cancel processing of the request
1070 delay(1000) // delay a second to see what happens
1071 println("main: Who has survived request cancellation?")
1072}
1073```
1074
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001075> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001076
1077The output of this code is:
1078
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001079```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001080job1: I have my own context and execute independently!
1081job2: I am a child of the request coroutine
1082job1: I am not affected by cancellation of the request
1083main: Who has survived request cancellation?
1084```
1085
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001086<!--- TEST -->
1087
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001088### Combining contexts
1089
Roman Elizarov66f018c2017-09-29 21:39:03 +03001090Coroutine contexts can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +03001091of 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 +03001092its dispatcher replaced:
1093
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001094<!--- INCLUDE
1095import kotlin.coroutines.experimental.*
1096-->
1097
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001098```kotlin
1099fun main(args: Array<String>) = runBlocking<Unit> {
1100 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +03001101 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001102 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +03001103 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001104 println("job: I am a child of the request coroutine, but with a different dispatcher")
1105 delay(1000)
1106 println("job: I will not execute this line if my parent request is cancelled")
1107 }
1108 job.join() // request completes when its sub-job completes
1109 }
1110 delay(500)
1111 request.cancel() // cancel processing of the request
1112 delay(1000) // delay a second to see what happens
1113 println("main: Who has survived request cancellation?")
1114}
1115```
1116
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001117> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001118
1119The expected outcome of this code is:
1120
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001121```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001122job: I am a child of the request coroutine, but with a different dispatcher
1123main: Who has survived request cancellation?
1124```
1125
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001126<!--- TEST -->
1127
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001128### Parental responsibilities
1129
1130A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001131all 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 +03001132
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001133<!--- INCLUDE
1134import kotlin.coroutines.experimental.*
1135-->
1136
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001137```kotlin
1138fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001139 // launch a coroutine to process some kind of incoming request
1140 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001141 repeat(3) { i -> // launch a few children jobs
1142 launch(coroutineContext) {
1143 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1144 println("Coroutine $i is done")
1145 }
1146 }
1147 println("request: I'm done and I don't explicitly join my children that are still active")
1148 }
1149 request.join() // wait for completion of the request, including all its children
1150 println("Now processing of the request is complete")
1151}
1152```
1153
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001154> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-08.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001155
1156The result is going to be:
1157
1158```text
1159request: I'm done and I don't explicitly join my children that are still active
1160Coroutine 0 is done
1161Coroutine 1 is done
1162Coroutine 2 is done
1163Now processing of the request is complete
1164```
1165
1166<!--- TEST -->
1167
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001168### Naming coroutines for debugging
1169
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001170Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001171coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1172or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001173[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1174is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001175
1176The following example demonstrates this concept:
1177
1178```kotlin
1179fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1180
1181fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1182 log("Started main coroutine")
1183 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001184 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001185 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001186 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001187 252
1188 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001189 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001190 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001191 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001192 6
1193 }
1194 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1195}
1196```
1197
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001198> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-09.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001199
1200The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1201
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001202```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001203[main @main#1] Started main coroutine
1204[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1205[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1206[main @main#1] The answer for v1 / v2 = 42
1207```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001208
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001209<!--- TEST FLEXIBLE_THREAD -->
1210
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001211### Cancellation via explicit job
1212
1213Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1214an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1215and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1216and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1217to avoid memory leaks.
1218
1219We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
Roman Elizarov88396732017-09-27 21:30:47 +03001220the lifecycle of our activity. A job instance is created using [Job()] factory function
Roman Elizarove8f694e2017-11-28 10:12:00 +03001221as the following example shows. For convenience, rather than using `launch(coroutineContext + job)` expression,
1222we can write `launch(coroutineContext, parent = job)` to make explicit the fact that the parent job is being used.
1223
1224Now, a single invocation of [Job.cancel] cancels all the children we've launched.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001225Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1226this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001227
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001228<!--- INCLUDE
1229import kotlin.coroutines.experimental.*
1230-->
1231
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001232```kotlin
1233fun main(args: Array<String>) = runBlocking<Unit> {
1234 val job = Job() // create a job object to manage our lifecycle
1235 // now launch ten coroutines for a demo, each working for a different time
1236 val coroutines = List(10) { i ->
1237 // they are all children of our job object
Roman Elizarove8f694e2017-11-28 10:12:00 +03001238 launch(coroutineContext, parent = job) { // we use the context of main runBlocking thread, but with our parent job
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001239 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001240 println("Coroutine $i is done")
1241 }
1242 }
1243 println("Launched ${coroutines.size} coroutines")
1244 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001245 println("Cancelling the job!")
1246 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001247}
1248```
1249
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001250> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-10.kt)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001251
1252The output of this example is:
1253
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001254```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001255Launched 10 coroutines
1256Coroutine 0 is done
1257Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001258Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001259```
1260
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001261<!--- TEST -->
1262
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001263As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001264by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001265application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001266and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1267since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1268resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001269
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001270### Thread-local data
1271
1272Sometimes it is very convenient to have an ability to pass some thread-local data, but, for coroutines, which
1273are not bound to any particular thread, it is hard to achieve it manually without writing a lot of boilerplate.
1274
1275For [`ThreadLocal`](https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html),
1276[asContextElement] is here for the rescue. It creates an additional context element,
1277which keep the value of the given `ThreadLocal` and restores it every time the coroutine switches its context.
1278
1279It is easy to demonstrate it in action:
1280
1281<!--- INCLUDE
1282import kotlin.coroutines.experimental.*
1283-->
1284
1285```kotlin
1286val threadLocal = ThreadLocal<String?>() // declare thread-local variable
1287
1288fun main(args: Array<String>) = runBlocking<Unit> {
1289 threadLocal.set("main")
1290 println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
1291 val job = launch(CommonPool + threadLocal.asContextElement(value = "launch"), start = CoroutineStart.UNDISPATCHED) {
1292 println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
1293 yield()
1294 println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
1295 }
1296 job.join()
1297 println("Post-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
1298}
1299```
1300
1301> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-11.kt)
1302
1303The output of this example is:
1304
1305```text
1306Pre-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
1307Launch start, current thread: Thread[main @coroutine#2,5,main], thread local value: 'launch'
1308After yield, current thread: Thread[ForkJoinPool.commonPool-worker-1 @coroutine#2,5,main], thread local value: 'launch'
1309Post-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
1310```
1311
1312<!--- TEST FLEXIBLE_THREAD -->
1313
1314Note how thread-local value is restored properly, no matter on what thread the coroutine is executed.
1315`ThreadLocal` has first-class support and can be used with any primitive `kotlinx.corotuines` provides.
1316It has one key limitation: when thread-local is mutated, a new value is not propagated to the coroutine caller
1317(as context element cannot track all `ThreadLocal` object accesses) and updated value is lost on the next suspension.
1318Use [withContext] to update the value of the thread-local in a coroutine, see [asContextElement] for more details.
1319
1320Alternatively, a value can be stored in a mutable box like `class Counter(var i: Int)`, which is, in turn,
1321is stored in a thread-local variable. However, in this case you are fully responsible to synchronize
1322potentially concurrent modifications to the variable in this box.
1323
1324For advanced usage, for example for integration with logging MDC, transactional contexts or any other libraries
1325which internally use thread-locals for passing data, see documentation for [ThreadContextElement] interface
1326that should be implemented.
1327
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001328## Exception handling
1329
1330<!--- INCLUDE .*/example-exceptions-([0-9]+).kt
1331-->
1332
1333This section covers exception handling and cancellation on exceptions.
1334We already know that cancelled coroutine throws [CancellationException] in suspension points and that it
1335is ignored by coroutines machinery. But what happens if an exception is thrown during cancellation or multiple children of the same
1336coroutine throw an exception?
1337
1338### Exception propagation
Roman Elizarov563da402018-08-10 19:18:56 +03001339
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001340Coroutine 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 +03001341The former treat exceptions as unhandled, similar to Java's `Thread.uncaughExceptionHandler`, while the latter are relying on the user to consume the final
1342exception, for example via [await][Deferred.await] or [receive][ReceiveChannel.receive]
1343([produce] and [receive][ReceiveChannel.receive] are covered later in [Channels](#channels) section).
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001344
1345It can be demonstrated by a simple example:
1346
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001347```kotlin
1348fun main(args: Array<String>) = runBlocking {
1349 val job = launch {
1350 println("Throwing exception from launch")
1351 throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
1352 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001353 job.join()
1354 println("Joined failed job")
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001355 val deferred = async {
1356 println("Throwing exception from async")
1357 throw ArithmeticException() // Nothing is printed, relying on user to call await
1358 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001359 try {
1360 deferred.await()
1361 println("Unreached")
1362 } catch (e: ArithmeticException) {
1363 println("Caught ArithmeticException")
1364 }
1365}
1366```
1367
1368> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-01.kt)
1369
1370The output of this code is:
1371
1372```text
1373Throwing exception from launch
1374Exception in thread "ForkJoinPool.commonPool-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
1375Joined failed job
1376Throwing exception from async
1377Caught ArithmeticException
1378```
1379
1380<!--- TEST EXCEPTION-->
1381
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001382### CoroutineExceptionHandler
1383
1384But what if one does not want to print all exceptions to the console?
1385[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 +03001386It is similar to using [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
1387
1388On JVM it's possible to redefine global exception handler for all coroutines by registering [CoroutineExceptionHandler] via
1389[`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
1390Global exception handler is similar to
1391[`Thread.defaultUncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler))
1392which is used when no more specific handlers are registered.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001393On Android, `uncaughtExceptionPreHandler` is installed as a global coroutine exception handler.
1394
Roman Elizarov563da402018-08-10 19:18:56 +03001395[CoroutineExceptionHandler] is invoked only on exceptions which are not expected to be handled by the user,
1396so registering it in [async] builder and the like of it has no effect.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001397
1398```kotlin
1399fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001400 val handler = CoroutineExceptionHandler { _, exception ->
1401 println("Caught $exception")
1402 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001403 val job = launch(handler) {
1404 throw AssertionError()
1405 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001406 val deferred = async(handler) {
1407 throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
1408 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001409 joinAll(job, deferred)
1410}
1411```
1412
1413> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-02.kt)
1414
1415The output of this code is:
1416
1417```text
1418Caught java.lang.AssertionError
1419```
1420
1421<!--- TEST-->
1422
1423### Cancellation and exceptions
Roman Elizarov563da402018-08-10 19:18:56 +03001424
1425Cancellation is tightly bound with exceptions. Coroutines internally use `CancellationException` for cancellation, these
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001426exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can
1427be obtained by `catch` block.
Roman Elizarov563da402018-08-10 19:18:56 +03001428When a coroutine is cancelled using [Job.cancel] without a cause, it terminates, but it does not cancel its parent.
1429Cancelling without cause is a mechanism for parent to cancel its children without cancelling itself.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001430
1431<!--- INCLUDE
1432import kotlin.coroutines.experimental.*
1433-->
1434
1435```kotlin
1436fun main(args: Array<String>) = runBlocking {
1437 val job = launch(coroutineContext, parent = Job()) {
1438 val child = launch(coroutineContext) {
1439 try {
1440 delay(Long.MAX_VALUE)
1441 } finally {
1442 println("Child is cancelled")
1443 }
1444 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001445 yield()
1446 println("Cancelling child")
1447 child.cancel()
1448 child.join()
1449 yield()
1450 println("Parent is not cancelled")
1451 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001452 job.join()
1453}
1454```
1455
1456> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-03.kt)
1457
1458The output of this code is:
1459
1460```text
1461Cancelling child
1462Child is cancelled
1463Parent is not cancelled
1464```
1465
1466<!--- TEST-->
1467
Roman Elizarov563da402018-08-10 19:18:56 +03001468If a coroutine encounters exception other than `CancellationException`, it cancels its parent with that exception.
1469This behaviour cannot be overridden and is used to provide stable coroutines hierarchies which do not depend on [CoroutineExceptionHandler] implementation.
1470The original exception is handled by the parent when all its children terminate.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001471
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001472<!--- INCLUDE
1473import kotlin.coroutines.experimental.*
1474-->
1475
1476```kotlin
1477fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001478 val handler = CoroutineExceptionHandler { _, exception ->
1479 println("Caught $exception")
1480 }
1481 val job = launch(handler) {
1482 val child1 = launch(coroutineContext, start = CoroutineStart.ATOMIC) {
1483 try {
1484 delay(Long.MAX_VALUE)
1485 } finally {
1486 withContext(NonCancellable) {
1487 println("Children are cancelled, but exception is not handled until all children terminate")
1488 delay(100)
1489 println("Last child finished its non cancellable block")
1490 }
1491 }
1492 }
1493 val child2 = launch(coroutineContext, start = CoroutineStart.ATOMIC) {
1494 delay(10)
1495 println("Second child throws an exception")
1496 throw ArithmeticException()
1497 }
1498 }
1499 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001500}
1501```
1502
1503> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-04.kt)
1504
1505The output of this code is:
1506
1507```text
Roman Elizarov563da402018-08-10 19:18:56 +03001508Second child throws an exception
1509Children are cancelled, but exception is not handled until all children terminate
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001510Last child finished its non cancellable block
1511Caught java.lang.ArithmeticException
1512```
1513<!--- TEST-->
1514
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001515### Exceptions aggregation
Roman Elizarov563da402018-08-10 19:18:56 +03001516
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001517What happens if multiple children of a coroutine throw an exception?
Roman Elizarov563da402018-08-10 19:18:56 +03001518The general rule is "the first exception wins", so the first thrown exception is exposed to the handler.
1519But that may cause lost exceptions, for example if coroutine throws an exception in its `finally` block.
1520
1521One of the solutions would have been to report each exception separately,
1522but then [Deferred.await] should have had the same mechanism to avoid behavioural inconsistency and this
1523would cause implementation details of a coroutines (whether it had delegate parts of its work to its children or not)
1524to leak to its exception handler.
1525
1526To avoid that, additional exceptions are suppressed.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001527
1528<!--- INCLUDE
1529import kotlinx.coroutines.experimental.exceptions.*
1530import kotlin.coroutines.experimental.*
1531import java.io.*
1532-->
1533
1534```kotlin
1535fun main(args: Array<String>) = runBlocking {
1536 val handler = CoroutineExceptionHandler { _, exception ->
Roman Elizarov563da402018-08-10 19:18:56 +03001537 println("Caught $exception with suppressed ${exception.suppressed().contentToString()}")
1538 }
1539 val job = launch(handler + coroutineContext, parent = Job()) {
1540 launch(coroutineContext, start = CoroutineStart.ATOMIC) {
1541 try {
1542 delay(Long.MAX_VALUE)
1543 } finally {
1544 throw ArithmeticException()
1545 }
1546 }
1547 launch(coroutineContext) {
1548 throw IOException()
1549 }
1550 delay(Long.MAX_VALUE)
1551 }
1552 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001553}
1554```
1555
1556> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-05.kt)
1557
1558The output of this code is:
1559
1560```text
1561Caught java.io.IOException with suppressed [java.lang.ArithmeticException]
1562```
1563<!--- TEST-->
1564
Roman Elizarov563da402018-08-10 19:18:56 +03001565Note that this mechanism currently works only on Java version 1.7+.
1566Limitation on JS and Native is temporary and will be fixed in the future.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001567
1568Cancellation exceptions are transparent and unwrapped by default:
1569
1570<!--- INCLUDE
1571import kotlin.coroutines.experimental.*
1572import java.io.*
1573-->
1574
1575```kotlin
1576fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001577 val handler = CoroutineExceptionHandler { _, exception ->
1578 println("Caught original $exception")
1579 }
1580 val job = launch(handler) {
1581 val inner = launch(coroutineContext) {
1582 launch(coroutineContext) {
1583 launch(coroutineContext) {
1584 throw IOException()
1585 }
1586 }
1587 }
1588 try {
1589 inner.join()
1590 } catch (e: JobCancellationException) {
1591 println("Rethrowing JobCancellationException with original cause")
1592 throw e
1593 }
1594 }
1595 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001596}
1597```
1598
1599> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt)
1600
1601The output of this code is:
1602
1603```text
1604Rethrowing JobCancellationException with original cause
1605Caught original java.io.IOException
1606```
1607<!--- TEST-->
1608
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001609## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001610
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001611Deferred values provide a convenient way to transfer a single value between coroutines.
1612Channels provide a way to transfer a stream of values.
1613
1614<!--- INCLUDE .*/example-channel-([0-9]+).kt
1615import kotlinx.coroutines.experimental.channels.*
1616-->
1617
1618### Channel basics
1619
Roman Elizarov419a6c82017-02-09 18:36:22 +03001620A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1621instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1622a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001623
1624```kotlin
1625fun main(args: Array<String>) = runBlocking<Unit> {
1626 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001627 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001628 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1629 for (x in 1..5) channel.send(x * x)
1630 }
1631 // here we print five received integers:
1632 repeat(5) { println(channel.receive()) }
1633 println("Done!")
1634}
1635```
1636
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001637> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-01.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001638
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001639The output of this code is:
1640
1641```text
16421
16434
16449
164516
164625
1647Done!
1648```
1649
1650<!--- TEST -->
1651
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001652### Closing and iteration over channels
1653
1654Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1655On the receiver side it is convenient to use a regular `for` loop to receive elements
1656from the channel.
1657
Roman Elizarov419a6c82017-02-09 18:36:22 +03001658Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001659The iteration stops as soon as this close token is received, so there is a guarantee
1660that all previously sent elements before the close are received:
1661
1662```kotlin
1663fun main(args: Array<String>) = runBlocking<Unit> {
1664 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001665 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001666 for (x in 1..5) channel.send(x * x)
1667 channel.close() // we're done sending
1668 }
1669 // here we print received values using `for` loop (until the channel is closed)
1670 for (y in channel) println(y)
1671 println("Done!")
1672}
1673```
1674
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001675> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001676
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001677<!--- TEST
16781
16794
16809
168116
168225
1683Done!
1684-->
1685
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001686### Building channel producers
1687
Roman Elizarova5e653f2017-02-13 13:49:55 +03001688The pattern where a coroutine is producing a sequence of elements is quite common.
1689This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001690You 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 +03001691to common sense that results must be returned from functions.
1692
Roman Elizarov86349be2017-03-17 16:47:37 +03001693There 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 +03001694and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001695
1696```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001697fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001698 for (x in 1..5) send(x * x)
1699}
1700
1701fun main(args: Array<String>) = runBlocking<Unit> {
1702 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001703 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001704 println("Done!")
1705}
1706```
1707
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001708> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-03.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001709
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001710<!--- TEST
17111
17124
17139
171416
171525
1716Done!
1717-->
1718
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001719### Pipelines
1720
Roman Elizarov66f018c2017-09-29 21:39:03 +03001721A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001722
1723```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001724fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001725 var x = 1
1726 while (true) send(x++) // infinite stream of integers starting from 1
1727}
1728```
1729
Roman Elizarova5e653f2017-02-13 13:49:55 +03001730And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001731In the below example the numbers are just squared:
1732
1733```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001734fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001735 for (x in numbers) send(x * x)
1736}
1737```
1738
Roman Elizarova5e653f2017-02-13 13:49:55 +03001739The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001740
1741```kotlin
1742fun main(args: Array<String>) = runBlocking<Unit> {
1743 val numbers = produceNumbers() // produces integers from 1 and on
1744 val squares = square(numbers) // squares integers
1745 for (i in 1..5) println(squares.receive()) // print first five
1746 println("Done!") // we are done
1747 squares.cancel() // need to cancel these coroutines in a larger app
1748 numbers.cancel()
1749}
1750```
1751
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001752> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-04.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001753
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001754<!--- TEST
17551
17564
17579
175816
175925
1760Done!
1761-->
1762
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001763We don't have to cancel these coroutines in this example app, because
1764[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1765but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1766Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001767[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001768
1769### Prime numbers with pipeline
1770
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001771Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001772of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001773explicit `context` parameter and pass it to [produce] builder,
1774so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001775
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001776<!--- INCLUDE
1777import kotlin.coroutines.experimental.*
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001778-->
1779
1780```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001781fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001782 var x = start
1783 while (true) send(x++) // infinite stream of integers from start
1784}
1785```
1786
1787The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1788that are divisible by the given prime number:
1789
1790```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001791fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001792 for (x in numbers) if (x % prime != 0) send(x)
1793}
1794```
1795
1796Now 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 +03001797and launching new pipeline stage for each prime number found:
1798
1799```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001800numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001801```
1802
1803The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001804running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001805children of the main [runBlocking] coroutine in its
1806[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html),
1807we don't have to keep an explicit list of all the coroutines we have started.
Roman Elizarov3e387b82017-12-04 13:49:11 +03001808We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
1809extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001810
1811```kotlin
1812fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001813 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001814 for (i in 1..10) {
1815 val prime = cur.receive()
1816 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001817 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001818 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001819 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001820}
1821```
1822
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001823> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-05.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001824
1825The output of this code is:
1826
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001827```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030018282
18293
18305
18317
183211
183313
183417
183519
183623
183729
1838```
1839
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001840<!--- TEST -->
1841
Roman Elizarov66f018c2017-09-29 21:39:03 +03001842Note, that you can build the same pipeline using
1843[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1844coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001845Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001846`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1847However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1848multiple CPU cores if you run it in [CommonPool] context.
1849
Roman Elizarova5e653f2017-02-13 13:49:55 +03001850Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001851other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1852built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001853`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001854
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001855### Fan-out
1856
1857Multiple coroutines may receive from the same channel, distributing work between themselves.
1858Let us start with a producer coroutine that is periodically producing integers
1859(ten numbers per second):
1860
1861```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001862fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001863 var x = 1 // start from 1
1864 while (true) {
1865 send(x++) // produce next
1866 delay(100) // wait 0.1s
1867 }
1868}
1869```
1870
1871Then we can have several processor coroutines. In this example, they just print their id and
1872received number:
1873
1874```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001875fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
bill58c61c72018-06-21 17:24:08 -05001876 for (msg in channel) {
1877 println("Processor #$id received $msg")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001878 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001879}
1880```
1881
Roman Elizarov35d2c342017-07-20 14:54:39 +03001882Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001883
1884```kotlin
1885fun main(args: Array<String>) = runBlocking<Unit> {
1886 val producer = produceNumbers()
1887 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001888 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001889 producer.cancel() // cancel producer coroutine and thus kill them all
1890}
1891```
1892
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001893> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-06.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001894
1895The output will be similar to the the following one, albeit the processor ids that receive
1896each specific integer may be different:
1897
1898```
1899Processor #2 received 1
1900Processor #4 received 2
1901Processor #0 received 3
1902Processor #1 received 4
1903Processor #3 received 5
1904Processor #2 received 6
1905Processor #4 received 7
1906Processor #0 received 8
1907Processor #1 received 9
1908Processor #3 received 10
1909```
1910
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001911<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1912
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001913Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1914over the channel that processor coroutines are doing.
1915
Roman Elizarov1ce6c0b2018-06-28 10:37:20 +03001916Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
1917Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
1918coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
1919always consumes (cancels) the underlying channel on its normal or abnormal termination.
1920
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001921### Fan-in
1922
1923Multiple coroutines may send to the same channel.
1924For example, let us have a channel of strings, and a suspending function that
1925repeatedly sends a specified string to this channel with a specified delay:
1926
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001927<!--- INCLUDE
1928import kotlin.coroutines.experimental.*
1929-->
1930
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001931```kotlin
1932suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1933 while (true) {
1934 delay(time)
1935 channel.send(s)
1936 }
1937}
1938```
1939
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001940Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001941(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 +03001942
1943```kotlin
1944fun main(args: Array<String>) = runBlocking<Unit> {
1945 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001946 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1947 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001948 repeat(6) { // receive first six
1949 println(channel.receive())
1950 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001951 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001952}
1953```
1954
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001955> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-07.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001956
1957The output is:
1958
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001959```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001960foo
1961foo
1962BAR!
1963foo
1964foo
1965BAR!
1966```
1967
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001968<!--- TEST -->
1969
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001970### Buffered channels
1971
1972The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1973meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1974if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001975
Roman Elizarov88396732017-09-27 21:30:47 +03001976Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001977specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1978similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1979
1980Take a look at the behavior of the following code:
1981
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001982<!--- INCLUDE
1983import kotlin.coroutines.experimental.*
1984-->
1985
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001986```kotlin
1987fun main(args: Array<String>) = runBlocking<Unit> {
1988 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001989 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001990 repeat(10) {
1991 println("Sending $it") // print before sending each element
1992 channel.send(it) // will suspend when buffer is full
1993 }
1994 }
1995 // don't receive anything... just wait....
1996 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001997 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001998}
1999```
2000
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002001> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002002
2003It prints "sending" _five_ times using a buffered channel with capacity of _four_:
2004
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002005```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002006Sending 0
2007Sending 1
2008Sending 2
2009Sending 3
2010Sending 4
2011```
2012
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002013<!--- TEST -->
2014
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002015The 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 +03002016
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002017### Ticker channels
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002018
Roman Elizarovb5328a72018-06-06 18:31:21 +03002019Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
2020Though 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 +03002021pipelines and operators that do windowing and other time-dependent processing.
Roman Elizarovb5328a72018-06-06 18:31:21 +03002022Ticker channel can be used in [select] to perform "on tick" action.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002023
Roman Elizarovb5328a72018-06-06 18:31:21 +03002024To create such channel use a factory method [ticker].
2025To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002026
2027Now let's see how it works in practice:
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002028
2029```kotlin
2030fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovb5328a72018-06-06 18:31:21 +03002031 val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002032 var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
paolop1d6e4932018-07-02 08:46:34 +00002033 println("Initial element is available immediately: $nextElement") // initial delay hasn't passed yet
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002034
paolop1d6e4932018-07-02 08:46:34 +00002035 nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements has 100ms delay
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002036 println("Next element is not ready in 50 ms: $nextElement")
2037
Roman Elizarovb5328a72018-06-06 18:31:21 +03002038 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002039 println("Next element is ready in 100 ms: $nextElement")
2040
2041 // Emulate large consumption delays
Roman Elizarovb5328a72018-06-06 18:31:21 +03002042 println("Consumer pauses for 150ms")
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002043 delay(150)
2044 // Next element is available immediately
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002045 nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002046 println("Next element is available immediately after large consumer delay: $nextElement")
2047 // Note that the pause between `receive` calls is taken into account and next element arrives faster
Roman Elizarovb5328a72018-06-06 18:31:21 +03002048 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002049 println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
2050
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002051 tickerChannel.cancel() // indicate that no more elements are needed
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002052}
2053```
2054
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002055> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-10.kt)
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002056
2057It prints following lines:
2058
2059```text
2060Initial element is available immediately: kotlin.Unit
2061Next element is not ready in 50 ms: null
2062Next element is ready in 100 ms: kotlin.Unit
Roman Elizarovb5328a72018-06-06 18:31:21 +03002063Consumer pauses for 150ms
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002064Next element is available immediately after large consumer delay: kotlin.Unit
2065Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
2066```
2067
2068<!--- TEST -->
2069
Roman Elizarovb5328a72018-06-06 18:31:21 +03002070Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
2071delay if a pause occurs, trying to maintain a fixed rate of produced elements.
2072
Roman Elizarov0c090ed2018-06-29 19:51:07 +03002073Optionally, a `mode` parameter equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
Roman Elizarovb5328a72018-06-06 18:31:21 +03002074delay between elements.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002075
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002076### Channels are fair
2077
2078Send and receive operations to channels are _fair_ with respect to the order of their invocation from
2079multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
2080gets the element. In the following example two coroutines "ping" and "pong" are
2081receiving the "ball" object from the shared "table" channel.
2082
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002083<!--- INCLUDE
2084import kotlin.coroutines.experimental.*
2085-->
2086
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002087```kotlin
2088data class Ball(var hits: Int)
2089
2090fun main(args: Array<String>) = runBlocking<Unit> {
2091 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03002092 launch(coroutineContext) { player("ping", table) }
2093 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002094 table.send(Ball(0)) // serve the ball
2095 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002096 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002097}
2098
2099suspend fun player(name: String, table: Channel<Ball>) {
2100 for (ball in table) { // receive the ball in a loop
2101 ball.hits++
2102 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03002103 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002104 table.send(ball) // send the ball back
2105 }
2106}
2107```
2108
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002109> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-09.kt)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002110
2111The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
2112coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
2113received by the "pong" coroutine, because it was already waiting for it:
2114
2115```text
2116ping Ball(hits=1)
2117pong Ball(hits=2)
2118ping Ball(hits=3)
2119pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03002120```
2121
2122<!--- TEST -->
2123
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002124Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
2125that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
2126
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002127## Shared mutable state and concurrency
2128
Roman Elizarov66f018c2017-09-29 21:39:03 +03002129Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002130all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
2131Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
2132but others are unique.
2133
2134### The problem
2135
Roman Elizarov1e459602017-02-27 11:05:17 +03002136Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
2137We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002138
Roman Elizarov1e459602017-02-27 11:05:17 +03002139<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002140import java.util.concurrent.atomic.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002141-->
2142
Roman Elizarov1e459602017-02-27 11:05:17 +03002143<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002144import kotlinx.coroutines.experimental.sync.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002145-->
2146
Roman Elizarov1e459602017-02-27 11:05:17 +03002147<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002148import kotlinx.coroutines.experimental.channels.*
2149-->
2150
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002151<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
2152import kotlin.system.*
2153import kotlin.coroutines.experimental.*
2154-->
2155
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002156```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03002157suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
2158 val n = 1000 // number of coroutines to launch
2159 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002160 val time = measureTimeMillis {
2161 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03002162 launch(context) {
2163 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002164 }
2165 }
2166 jobs.forEach { it.join() }
2167 }
Roman Elizarov1e459602017-02-27 11:05:17 +03002168 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002169}
2170```
2171
Roman Elizarov43e90112017-05-10 11:25:20 +03002172<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002173
Roman Elizarov1e459602017-02-27 11:05:17 +03002174We start with a very simple action that increments a shared mutable variable using
2175multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002176
2177```kotlin
2178var counter = 0
2179
2180fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002181 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002182 counter++
2183 }
2184 println("Counter = $counter")
2185}
2186```
2187
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002188> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002189
Roman Elizarov1e459602017-02-27 11:05:17 +03002190<!--- TEST LINES_START
2191Completed 1000000 actions in
2192Counter =
2193-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002194
Roman Elizarov1e459602017-02-27 11:05:17 +03002195What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
2196increment the `counter` concurrently from multiple threads without any synchronization.
2197
Roman Elizarov43e90112017-05-10 11:25:20 +03002198> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
2199`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
2200following change:
2201
2202```kotlin
2203val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
2204var counter = 0
2205
2206fun main(args: Array<String>) = runBlocking<Unit> {
2207 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
2208 counter++
2209 }
2210 println("Counter = $counter")
2211}
2212```
2213
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002214> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt)
Roman Elizarov43e90112017-05-10 11:25:20 +03002215
2216<!--- TEST LINES_START
2217Completed 1000000 actions in
2218Counter =
2219-->
2220
Roman Elizarov1e459602017-02-27 11:05:17 +03002221### Volatiles are of no help
2222
2223There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
2224
2225```kotlin
2226@Volatile // in Kotlin `volatile` is an annotation
2227var counter = 0
2228
2229fun main(args: Array<String>) = runBlocking<Unit> {
2230 massiveRun(CommonPool) {
2231 counter++
2232 }
2233 println("Counter = $counter")
2234}
2235```
2236
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002237> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03002238
2239<!--- TEST LINES_START
2240Completed 1000000 actions in
2241Counter =
2242-->
2243
2244This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
2245linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
2246do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002247
2248### Thread-safe data structures
2249
2250The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
2251linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
2252operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03002253In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002254
2255```kotlin
2256var counter = AtomicInteger()
2257
2258fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002259 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002260 counter.incrementAndGet()
2261 }
2262 println("Counter = ${counter.get()}")
2263}
2264```
2265
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002266> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002267
Roman Elizarov1e459602017-02-27 11:05:17 +03002268<!--- TEST ARBITRARY_TIME
2269Completed 1000000 actions in xxx ms
2270Counter = 1000000
2271-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002272
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002273This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
2274standard data structures and basic operations on them. However, it does not easily scale to complex
2275state or to complex operations that do not have ready-to-use thread-safe implementations.
2276
Roman Elizarov1e459602017-02-27 11:05:17 +03002277### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002278
Roman Elizarov1e459602017-02-27 11:05:17 +03002279_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 +03002280state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
2281the single event-dispatch/application thread. It is easy to apply with coroutines by using a
2282single-threaded context:
2283
2284```kotlin
2285val counterContext = newSingleThreadContext("CounterContext")
2286var counter = 0
2287
2288fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002289 massiveRun(CommonPool) { // run each coroutine in CommonPool
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002290 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002291 counter++
2292 }
2293 }
2294 println("Counter = $counter")
2295}
2296```
2297
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002298> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002299
Roman Elizarov1e459602017-02-27 11:05:17 +03002300<!--- TEST ARBITRARY_TIME
2301Completed 1000000 actions in xxx ms
2302Counter = 1000000
2303-->
2304
2305This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002306from multi-threaded `CommonPool` context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03002307
2308### Thread confinement coarse-grained
2309
2310In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
2311are confined to the single thread. The following example does it like that, running each coroutine in
2312the single-threaded context to start with.
2313
2314```kotlin
2315val counterContext = newSingleThreadContext("CounterContext")
2316var counter = 0
2317
2318fun main(args: Array<String>) = runBlocking<Unit> {
2319 massiveRun(counterContext) { // run each coroutine in the single-threaded context
2320 counter++
2321 }
2322 println("Counter = $counter")
2323}
2324```
2325
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002326> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-05.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03002327
2328<!--- TEST ARBITRARY_TIME
2329Completed 1000000 actions in xxx ms
2330Counter = 1000000
2331-->
2332
2333This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002334
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002335### Mutual exclusion
2336
2337Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
2338that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
2339Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
paolop1d6e4932018-07-02 08:46:34 +00002340delimit 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 +03002341
Roman Elizarov88396732017-09-27 21:30:47 +03002342There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002343`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
2344
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002345```kotlin
2346val mutex = Mutex()
2347var counter = 0
2348
2349fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03002350 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002351 mutex.withLock {
2352 counter++
2353 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002354 }
2355 println("Counter = $counter")
2356}
2357```
2358
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002359> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002360
Roman Elizarov1e459602017-02-27 11:05:17 +03002361<!--- TEST ARBITRARY_TIME
2362Completed 1000000 actions in xxx ms
2363Counter = 1000000
2364-->
2365
2366The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
2367where you absolutely must modify some shared state periodically, but there is no natural thread that this state
2368is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002369
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002370### Actors
2371
paolop1d6e4932018-07-02 08:46:34 +00002372An [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 +03002373and a channel to communicate with other coroutines. A simple actor can be written as a function,
2374but an actor with a complex state is better suited for a class.
2375
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002376There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
2377scope to receive messages from and combines the send channel into the resulting job object, so that a
2378single reference to the actor can be carried around as its handle.
2379
Roman Elizarov256812a2017-07-22 01:00:30 +03002380The first step of using an actor is to define a class of messages that an actor is going to process.
2381Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
2382We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
2383to get its value. The later needs to send a response. A [CompletableDeferred] communication
2384primitive, that represents a single value that will be known (communicated) in the future,
2385is used here for that purpose.
2386
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002387```kotlin
2388// Message types for counterActor
2389sealed class CounterMsg
2390object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03002391class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
2392```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002393
Roman Elizarov256812a2017-07-22 01:00:30 +03002394Then we define a function that launches an actor using an [actor] coroutine builder:
2395
2396```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002397// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03002398fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002399 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002400 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002401 when (msg) {
2402 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03002403 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002404 }
2405 }
2406}
Roman Elizarov256812a2017-07-22 01:00:30 +03002407```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002408
Roman Elizarov256812a2017-07-22 01:00:30 +03002409The main code is straightforward:
2410
2411```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002412fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002413 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03002414 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002415 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002416 }
Roman Elizarov256812a2017-07-22 01:00:30 +03002417 // send a message to get a counter value from an actor
2418 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002419 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03002420 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002421 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002422}
2423```
2424
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002425> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002426
Roman Elizarov1e459602017-02-27 11:05:17 +03002427<!--- TEST ARBITRARY_TIME
2428Completed 1000000 actions in xxx ms
2429Counter = 1000000
2430-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002431
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002432It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002433a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
paolop1d6e4932018-07-02 08:46:34 +00002434works 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 +03002435
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002436Actor is more efficient than locking under load, because in this case it always has work to do and it does not
2437have to switch to a different context at all.
2438
2439> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
2440 with the channel that it receives messages from, while a producer is associated with the channel that it
2441 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03002442
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002443## Select expression
2444
Roman Elizarova84730b2017-02-22 11:58:50 +03002445Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002446the first one that becomes available.
2447
2448<!--- INCLUDE .*/example-select-([0-9]+).kt
2449import kotlinx.coroutines.experimental.channels.*
2450import kotlinx.coroutines.experimental.selects.*
2451-->
2452
2453### Selecting from channels
2454
Roman Elizarov57857202017-03-02 23:17:25 +03002455Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2456
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002457<!--- INCLUDE
2458import kotlinx.coroutines.experimental.*
2459import kotlin.coroutines.experimental.*
Roman Elizarov57857202017-03-02 23:17:25 +03002460-->
2461
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002462```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002463fun fizz(context: CoroutineContext) = produce<String>(context) {
2464 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002465 delay(300)
2466 send("Fizz")
2467 }
2468}
2469```
2470
Roman Elizarov57857202017-03-02 23:17:25 +03002471And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002472
2473```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002474fun buzz(context: CoroutineContext) = produce<String>(context) {
2475 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002476 delay(500)
2477 send("Buzz!")
2478 }
2479}
2480```
2481
2482Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2483other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002484[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002485
2486```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002487suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002488 select<Unit> { // <Unit> means that this select expression does not produce any result
2489 fizz.onReceive { value -> // this is the first select clause
2490 println("fizz -> '$value'")
2491 }
2492 buzz.onReceive { value -> // this is the second select clause
2493 println("buzz -> '$value'")
2494 }
2495 }
2496}
2497```
2498
Roman Elizarov57857202017-03-02 23:17:25 +03002499Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002500
2501```kotlin
2502fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002503 val fizz = fizz(coroutineContext)
2504 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002505 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002506 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002507 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002508 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002509}
2510```
2511
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002512> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-01.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002513
2514The result of this code is:
2515
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002516```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002517fizz -> 'Fizz'
2518buzz -> 'Buzz!'
2519fizz -> 'Fizz'
2520fizz -> 'Fizz'
2521buzz -> 'Buzz!'
2522fizz -> 'Fizz'
2523buzz -> 'Buzz!'
2524```
2525
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002526<!--- TEST -->
2527
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002528### Selecting on close
2529
paolop1d6e4932018-07-02 08:46:34 +00002530The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
2531`select` to throw an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002532specific 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 +03002533the result of its selected clause:
2534
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002535<!--- INCLUDE
2536import kotlin.coroutines.experimental.*
2537-->
2538
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002539```kotlin
2540suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2541 select<String> {
2542 a.onReceiveOrNull { value ->
2543 if (value == null)
2544 "Channel 'a' is closed"
2545 else
2546 "a -> '$value'"
2547 }
2548 b.onReceiveOrNull { value ->
2549 if (value == null)
2550 "Channel 'b' is closed"
2551 else
2552 "b -> '$value'"
2553 }
2554 }
2555```
2556
Roman Elizarova84730b2017-02-22 11:58:50 +03002557Let's use it with channel `a` that produces "Hello" string four times and
2558channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002559
2560```kotlin
2561fun main(args: Array<String>) = runBlocking<Unit> {
2562 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002563 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002564 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002565 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002566 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002567 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002568 }
2569 repeat(8) { // print first eight results
2570 println(selectAorB(a, b))
2571 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002572 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002573}
2574```
2575
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002576> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-02.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002577
Roman Elizarova84730b2017-02-22 11:58:50 +03002578The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002579
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002580```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002581a -> 'Hello 0'
2582a -> 'Hello 1'
2583b -> 'World 0'
2584a -> 'Hello 2'
2585a -> 'Hello 3'
2586b -> 'World 1'
2587Channel 'a' is closed
2588Channel 'a' is closed
2589```
2590
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002591<!--- TEST -->
2592
Roman Elizarova84730b2017-02-22 11:58:50 +03002593There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002594
2595First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2596the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002597being 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 +03002598time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2599
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002600The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002601channel is already closed.
2602
2603### Selecting to send
2604
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002605Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002606with a biased nature of selection.
2607
Roman Elizarova84730b2017-02-22 11:58:50 +03002608Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002609the consumers on its primary channel cannot keep up with it:
2610
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002611<!--- INCLUDE
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002612import kotlin.coroutines.experimental.*
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002613-->
2614
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002615```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002616fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002617 for (num in 1..10) { // produce 10 numbers from 1 to 10
2618 delay(100) // every 100 ms
2619 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002620 onSend(num) {} // Send to the primary channel
2621 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002622 }
2623 }
2624}
2625```
2626
2627Consumer is going to be quite slow, taking 250 ms to process each number:
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002628
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002629```kotlin
2630fun main(args: Array<String>) = runBlocking<Unit> {
2631 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002632 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002633 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002634 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002635 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002636 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002637 delay(250) // let us digest the consumed number properly, do not hurry
2638 }
2639 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002640 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002641}
2642```
2643
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002644> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-03.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002645
2646So let us see what happens:
2647
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002648```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002649Consuming 1
2650Side channel has 2
2651Side channel has 3
2652Consuming 4
2653Side channel has 5
2654Side channel has 6
2655Consuming 7
2656Side channel has 8
2657Side channel has 9
2658Consuming 10
2659Done consuming
2660```
2661
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002662<!--- TEST -->
2663
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002664### Selecting deferred values
2665
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002666Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002667Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002668a random delay:
2669
2670<!--- INCLUDE .*/example-select-04.kt
2671import java.util.*
2672-->
2673
2674```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002675fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002676 delay(time.toLong())
2677 "Waited for $time ms"
2678}
2679```
2680
Roman Elizarova84730b2017-02-22 11:58:50 +03002681Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002682
2683```kotlin
2684fun asyncStringsList(): List<Deferred<String>> {
2685 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002686 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002687}
2688```
2689
Roman Elizarova84730b2017-02-22 11:58:50 +03002690Now 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 +03002691that 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 +03002692so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2693of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002694
2695```kotlin
2696fun main(args: Array<String>) = runBlocking<Unit> {
2697 val list = asyncStringsList()
2698 val result = select<String> {
2699 list.withIndex().forEach { (index, deferred) ->
2700 deferred.onAwait { answer ->
2701 "Deferred $index produced answer '$answer'"
2702 }
2703 }
2704 }
2705 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002706 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002707 println("$countActive coroutines are still active")
2708}
2709```
2710
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002711> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-04.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002712
2713The output is:
2714
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002715```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002716Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300271711 coroutines are still active
2718```
2719
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002720<!--- TEST -->
2721
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002722### Switch over a channel of deferred values
2723
Roman Elizarova84730b2017-02-22 11:58:50 +03002724Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2725deferred 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 +03002726[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002727
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002728<!--- INCLUDE
2729import kotlin.coroutines.experimental.*
2730-->
2731
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002732```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002733fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002734 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002735 while (isActive) { // loop while not cancelled/closed
2736 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2737 input.onReceiveOrNull { update ->
2738 update // replaces next value to wait
2739 }
2740 current.onAwait { value ->
2741 send(value) // send value that current deferred has produced
2742 input.receiveOrNull() // and use the next deferred from the input channel
2743 }
2744 }
2745 if (next == null) {
2746 println("Channel was closed")
2747 break // out of loop
2748 } else {
2749 current = next
2750 }
2751 }
2752}
2753```
2754
2755To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2756
2757```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002758fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002759 delay(time)
2760 str
2761}
2762```
2763
2764The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2765data to it:
2766
2767```kotlin
2768fun main(args: Array<String>) = runBlocking<Unit> {
2769 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002770 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002771 for (s in switchMapDeferreds(chan))
2772 println(s) // print each received string
2773 }
2774 chan.send(asyncString("BEGIN", 100))
2775 delay(200) // enough time for "BEGIN" to be produced
2776 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002777 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002778 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002779 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002780 chan.send(asyncString("END", 500))
2781 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002782 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002783 delay(500) // and wait some time to let it finish
2784}
2785```
2786
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002787> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-05.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002788
2789The result of this code:
2790
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002791```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002792BEGIN
2793Replace
2794END
2795Channel was closed
2796```
2797
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002798<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002799
Roman Elizarov8db17332017-03-09 12:40:45 +03002800## Further reading
2801
2802* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002803* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002804* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2805* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2806
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002807<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002808<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002809[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2810[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2811[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002812[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002813[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002814[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2815[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03002816[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002817[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002818[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 +03002819[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002820[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002821[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2822[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002823[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 +03002824[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2825[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002826[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 +03002827[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2828[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002829[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002830[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002831[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002832[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002833[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2834[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 +03002835[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002836[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002837[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03002838[asContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/java.lang.-thread-local/as-context-element.html
2839[ThreadContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-thread-context-element/index.html
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03002840[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 +03002841[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 +03002842[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002843[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 +03002844<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002845[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002846[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2847[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 +03002848[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002849<!--- INDEX kotlinx.coroutines.experimental.channels -->
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03002850[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
2851[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
2852[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 +03002853[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002854[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 +03002855[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 +03002856[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002857[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002858[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/ticker.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002859[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 +03002860[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 +03002861[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 +03002862[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2863[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 +03002864<!--- INDEX kotlinx.coroutines.experimental.selects -->
2865[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002866<!--- END -->