blob: 21d562cc76b5a0cd92a62cd8263e2118129a65d8 [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`
Roman Elizarovc32579e2018-09-09 19:21:43 +030029are not keywords in Kotlin and are not even part of its standard library. Moreover, Kotlin's concept
30of _suspending function_ provides a safer and less error-prone abstraction for for asynchronous
31operations than futures and promises.
Roman Elizarov2a638922017-03-04 10:22:43 +030032
Roman Elizarovc32579e2018-09-09 19:21:43 +030033`kotlinx.coroutines` is a rich library for coroutines developed by JetBrains. It contains a number of high-level
Roman Elizarova4d45d22017-11-20 16:47:09 +030034coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
Roman Elizarov2a638922017-03-04 10:22:43 +030035You need to add a dependency on `kotlinx-coroutines-core` module as explained
36[here](README.md#using-in-your-projects) to use primitives from this guide in your projects.
37
Roman Elizarov1293ccd2017-02-01 18:49:54 +030038## Table of contents
39
Roman Elizarovfa7723e2017-02-06 11:17:51 +030040<!--- TOC -->
41
Roman Elizarov1293ccd2017-02-01 18:49:54 +030042* [Coroutine basics](#coroutine-basics)
43 * [Your first coroutine](#your-first-coroutine)
44 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
45 * [Waiting for a job](#waiting-for-a-job)
Roman Elizarovc32579e2018-09-09 19:21:43 +030046 * [Structured concurrency](#structured-concurrency)
47 * [Scope builder](#scope-builder)
Roman Elizarov1293ccd2017-02-01 18:49:54 +030048 * [Extract function refactoring](#extract-function-refactoring)
49 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
Roman Elizarovc32579e2018-09-09 19:21:43 +030050 * [Global coroutines are like daemon threads](#global-coroutines-are-like-daemon-threads)
Roman Elizarov1293ccd2017-02-01 18:49:54 +030051* [Cancellation and timeouts](#cancellation-and-timeouts)
52 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
53 * [Cancellation is cooperative](#cancellation-is-cooperative)
54 * [Making computation code cancellable](#making-computation-code-cancellable)
55 * [Closing resources with finally](#closing-resources-with-finally)
56 * [Run non-cancellable block](#run-non-cancellable-block)
57 * [Timeout](#timeout)
58* [Composing suspending functions](#composing-suspending-functions)
59 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030060 * [Concurrent using async](#concurrent-using-async)
61 * [Lazily started async](#lazily-started-async)
62 * [Async-style functions](#async-style-functions)
Roman Elizarovc32579e2018-09-09 19:21:43 +030063 * [Structured concurrency with async](#structured-concurrency-with-async)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030064* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030065 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030066 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
67 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
68 * [Jumping between threads](#jumping-between-threads)
69 * [Job in the context](#job-in-the-context)
70 * [Children of a coroutine](#children-of-a-coroutine)
Roman Elizarov8b38fa22017-09-27 17:44:31 +030071 * [Parental responsibilities](#parental-responsibilities)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030072 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarovc32579e2018-09-09 19:21:43 +030073 * [Combining context elements](#combining-context-elements)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030074 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +030075 * [Thread-local data](#thread-local-data)
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +030076* [Exception handling](#exception-handling)
77 * [Exception propagation](#exception-propagation)
78 * [CoroutineExceptionHandler](#coroutineexceptionhandler)
79 * [Cancellation and exceptions](#cancellation-and-exceptions)
80 * [Exceptions aggregation](#exceptions-aggregation)
Roman Elizarovc32579e2018-09-09 19:21:43 +030081* [Channels (experimental)](#channels-(experimental))
Roman Elizarovb7721cf2017-02-03 19:23:08 +030082 * [Channel basics](#channel-basics)
83 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
84 * [Building channel producers](#building-channel-producers)
85 * [Pipelines](#pipelines)
86 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
87 * [Fan-out](#fan-out)
88 * [Fan-in](#fan-in)
89 * [Buffered channels](#buffered-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030090 * [Channels are fair](#channels-are-fair)
Roman Elizarovc32579e2018-09-09 19:21:43 +030091 * [Ticker channels](#ticker-channels)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030092* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
93 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030094 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030095 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030096 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
97 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030098 * [Mutual exclusion](#mutual-exclusion)
99 * [Actors](#actors)
Roman Elizarovc32579e2018-09-09 19:21:43 +0300100* [Select expression (experimental)](#select-expression-(experimental))
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300101 * [Selecting from channels](#selecting-from-channels)
102 * [Selecting on close](#selecting-on-close)
103 * [Selecting to send](#selecting-to-send)
104 * [Selecting deferred values](#selecting-deferred-values)
105 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +0300106* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300107
Roman Elizarova5e653f2017-02-13 13:49:55 +0300108<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300109
110## Coroutine basics
111
112This section covers basic coroutine concepts.
113
114### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300115
116Run the following code:
117
118```kotlin
119fun main(args: Array<String>) {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300120 GlobalScope.launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300121 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
122 println("World!") // print after delay
123 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300124 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300125 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
126}
127```
128
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300129> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300130
131Run this code:
132
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300133```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300134Hello,
135World!
136```
137
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300138<!--- TEST -->
139
Roman Elizarov419a6c82017-02-09 18:36:22 +0300140Essentially, coroutines are light-weight threads.
Roman Elizarovc32579e2018-09-09 19:21:43 +0300141They are launched with [launch] _coroutine builder_ in a context of some [CoroutineScope].
142Here we are launching a new coroutine in the [GlobalScope], meaning that the lifetime of the new
143coroutine is limited only by the lifetime of the whole application.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300144
Roman Elizarovc32579e2018-09-09 19:21:43 +0300145You can achieve the same result replacing
146`GlobalScope.launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
147
148If you start by replacing `GlobalScope.launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300149
150```
151Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
152```
153
Roman Elizarov419a6c82017-02-09 18:36:22 +0300154That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300155coroutine and it can be only used from a coroutine.
156
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300157### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300158
Roman Elizarova4d45d22017-11-20 16:47:09 +0300159The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
160It is easy to get lost which one is blocking and which one is not.
161Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300162
163```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300164fun main(args: Array<String>) {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300165 GlobalScope.launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300166 delay(1000L)
167 println("World!")
168 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300169 println("Hello,") // main thread continues here immediately
170 runBlocking { // but this expression blocks the main thread
171 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
172 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300173}
174```
175
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300176> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300177
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300178<!--- TEST
179Hello,
180World!
181-->
182
Roman Elizarov419a6c82017-02-09 18:36:22 +0300183The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100184The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300185
Roman Elizarova4d45d22017-11-20 16:47:09 +0300186This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
187the execution of the main function:
188
189```kotlin
190fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
Roman Elizarovc32579e2018-09-09 19:21:43 +0300191 GlobalScope.launch { // launch new coroutine in background and continue
Roman Elizarova4d45d22017-11-20 16:47:09 +0300192 delay(1000L)
193 println("World!")
194 }
195 println("Hello,") // main coroutine continues here immediately
196 delay(2000L) // delaying for 2 seconds to keep JVM alive
197}
198```
199
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300200> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt)
Roman Elizarova4d45d22017-11-20 16:47:09 +0300201
202<!--- TEST
203Hello,
204World!
205-->
206
207Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
208We 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 +0300209
210This is also a way to write unit-tests for suspending functions:
211
212```kotlin
213class MyTest {
214 @Test
215 fun testMySuspendingFunction() = runBlocking<Unit> {
216 // here we can use suspending functions using any assertion style that we like
217 }
218}
219```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300220
221<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300222
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300223### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300224
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300225Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300226wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300227
228```kotlin
229fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300230 val job = GlobalScope.launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300231 delay(1000L)
232 println("World!")
233 }
234 println("Hello,")
235 job.join() // wait until child coroutine completes
236}
237```
238
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300239> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300240
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300241<!--- TEST
242Hello,
243World!
244-->
245
Roman Elizarov7deefb82017-01-31 10:33:17 +0300246Now 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 +0300247the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300248
Roman Elizarovc32579e2018-09-09 19:21:43 +0300249### Structured concurrency
250
251There is still something to be desired for practical usage of coroutines.
252When we use `GlobalScope.launch` we create a top-level coroutine. Even though it is light-weight, it still
253consumes some memory resources while it runs. If we forget to keep a reference to the newly launched
254coroutine it still runs. What if the code in the coroutine hangs (for example, we erroneously
255delay for too long), what if we launched too many coroutines and ran out of memory?
256Having to manually keep a reference to all the launched coroutines and [join][Job.join] them is error-prone.
257
258There is a better solution. We can use structured concurrency in our code.
259Instead of launching coroutines in the [GlobalScope], just like we usually do with threads (threads are always global),
260we can launch coroutines in the specific scope of the operation we are performing.
261
262In our example, we have `main` function that is turned into a coroutine using [runBlocking] coroutine builder.
263Every coroutine builder, including `runBlocking`, adds an instance of [CoroutineScope] to the scope its code block.
264We can launch coroutines in this scope without having to `join` them explicitly, because
265an outer coroutine (`runBlocking` in our example) does not complete until all the coroutines launched
266in its scope complete. Thus, we can make our example simpler:
267
268```kotlin
269fun main(args: Array<String>) = runBlocking<Unit> { // this: CoroutineScope
270 launch { // launch new coroutine in the scope of runBlocking
271 delay(1000L)
272 println("World!")
273 }
274 println("Hello,")
275}
276```
277
278> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt)
279
280<!--- TEST
281Hello,
282World!
283-->
284
285### Scope builder
286In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using
287[coroutineScope] builder. It creates new coroutine scope and does not complete until all launched children
288complete. The main difference between [runBlocking] and [coroutineScope] is that the latter does not block the current thread
289while waiting for all children to complete.
290
291```kotlin
292fun main(args: Array<String>) = runBlocking<Unit> { // this: CoroutineScope
293 launch {
294 delay(200L)
295 println("Task from runBlocking")
296 }
297
298 coroutineScope { // Creates a new coroutine scope
299 launch {
300 delay(500L)
301 println("Task from nested launch")
302 }
303
304 delay(100L)
305 println("Task from coroutine scope") // This line will be printed before nested launch
306 }
307
308 println("Coroutine scope is over") // This line is not printed until nested launch completes
309}
310```
311
312> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-04.kt)
313
314<!--- TEST
315Task from coroutine scope
316Task from runBlocking
317Task from nested launch
318Coroutine scope is over
319-->
320
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300321### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300322
Roman Elizarov66f018c2017-09-29 21:39:03 +0300323Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300324perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
325That is your first _suspending function_. Suspending functions can be used inside coroutines
326just like regular functions, but their additional feature is that they can, in turn,
327use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
328
329```kotlin
330fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300331 launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300332 println("Hello,")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300333}
334
335// this is your first suspending function
336suspend fun doWorld() {
337 delay(1000L)
338 println("World!")
339}
340```
341
Roman Elizarovc32579e2018-09-09 19:21:43 +0300342> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-05.kt)
343
344<!--- TEST
345Hello,
346World!
347-->
348
349
350But what if the extracted function contains a coroutine builder which is invoked on the current scope?
351In this case `suspend` modifier on the extracted function is not enough. Making `doWorld` extension
352method on `CoroutineScope` is one of the solutions, but it may not always be applicable as it does not make API clearer.
353[currentScope] builder comes to help: it inherits current [CoroutineScope] from the coroutine context it is invoked.
354
355```kotlin
356fun main(args: Array<String>) = runBlocking<Unit> {
357 launchDoWorld()
358 println("Hello,")
359}
360
361// this is your first suspending function
362suspend fun launchDoWorld() = currentScope {
Roman Elizarovbca98f42018-09-19 14:49:42 +0300363 launch {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300364 println("World!")
365 }
366}
367```
368
369> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300370
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300371<!--- TEST
372Hello,
373World!
374-->
375
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300376### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300377
378Run the following code:
379
380```kotlin
381fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300382 repeat(100_000) { // launch a lot of coroutines
Roman Elizarov66f018c2017-09-29 21:39:03 +0300383 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300384 delay(1000L)
385 print(".")
386 }
387 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300388}
389```
390
Roman Elizarovc32579e2018-09-09 19:21:43 +0300391> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300392
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300393<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
394
Roman Elizarov66f018c2017-09-29 21:39:03 +0300395It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300396Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
397
Roman Elizarovc32579e2018-09-09 19:21:43 +0300398### Global coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300399
Roman Elizarovc32579e2018-09-09 19:21:43 +0300400The following code launches a long-running coroutine in [GlobalScope] that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300401returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300402
403```kotlin
404fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +0300405 GlobalScope.launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300406 repeat(1000) { i ->
407 println("I'm sleeping $i ...")
408 delay(500L)
409 }
410 }
411 delay(1300L) // just quit after delay
412}
413```
414
Roman Elizarovc32579e2018-09-09 19:21:43 +0300415> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-07.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300416
417You can run and see that it prints three lines and terminates:
418
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300419```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300420I'm sleeping 0 ...
421I'm sleeping 1 ...
422I'm sleeping 2 ...
423```
424
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300425<!--- TEST -->
426
Roman Elizarovc32579e2018-09-09 19:21:43 +0300427Active coroutines that were launched in [GlobalScope] do not keep the process alive. They are like daemon threads.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300428
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300429## Cancellation and timeouts
430
431This section covers coroutine cancellation and timeouts.
432
433### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300434
Roman Elizarovc32579e2018-09-09 19:21:43 +0300435In a long-running application you might need fine-grained control on your background coroutines.
436For example, a user might have closed the page that launched a coroutine and now its result
437is no longer needed and its operation can be cancelled.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300438The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300439
440```kotlin
441fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300442 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300443 repeat(1000) { i ->
444 println("I'm sleeping $i ...")
445 delay(500L)
446 }
447 }
448 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300449 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300450 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300451 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300452 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300453}
454```
455
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300456> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300457
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300458It produces the following output:
459
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300460```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300461I'm sleeping 0 ...
462I'm sleeping 1 ...
463I'm sleeping 2 ...
464main: I'm tired of waiting!
465main: Now I can quit.
466```
467
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300468<!--- TEST -->
469
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300470As 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 +0300471There is also a [Job] extension function [cancelAndJoin]
472that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300473
474### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300475
Tair Rzayevaf734622017-02-01 22:30:16 +0200476Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300477All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300478coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300479a computation and does not check for cancellation, then it cannot be cancelled, like the following
480example shows:
481
482```kotlin
483fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700484 val startTime = System.currentTimeMillis()
Roman Elizarovdc29b072018-09-11 18:42:03 +0300485 val job = launch(Dispatchers.Default) {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700486 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300487 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300488 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700489 // print a message twice a second
490 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300491 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300492 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300493 }
494 }
495 }
496 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300497 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300498 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300499 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300500}
501```
502
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300503> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300504
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300505Run it to see that it continues to print "I'm sleeping" even after cancellation
506until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300507
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300508<!--- TEST
509I'm sleeping 0 ...
510I'm sleeping 1 ...
511I'm sleeping 2 ...
512main: I'm tired of waiting!
513I'm sleeping 3 ...
514I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300515main: Now I can quit.
516-->
517
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300518### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300519
520There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300521invoke 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 +0300522The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300523
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300524Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300525
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300526```kotlin
527fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700528 val startTime = System.currentTimeMillis()
Roman Elizarovdc29b072018-09-11 18:42:03 +0300529 val job = launch(Dispatchers.Default) {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700530 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300531 var i = 0
532 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700533 // print a message twice a second
534 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300535 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700536 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300537 }
538 }
539 }
540 delay(1300L) // delay a bit
541 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300542 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300543 println("main: Now I can quit.")
544}
545```
546
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300547> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300548
Roman Elizarovc32579e2018-09-09 19:21:43 +0300549As you can see, now this loop is cancelled. [isActive] is an extension property that is
550available inside the code of coroutine via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300551
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300552<!--- TEST
553I'm sleeping 0 ...
554I'm sleeping 1 ...
555I'm sleeping 2 ...
556main: I'm tired of waiting!
557main: Now I can quit.
558-->
559
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300560### Closing resources with finally
561
Roman Elizarov419a6c82017-02-09 18:36:22 +0300562Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarovc32579e2018-09-09 19:21:43 +0300563a usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300564finalization actions normally when coroutine is cancelled:
565
566```kotlin
567fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300568 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300569 try {
570 repeat(1000) { i ->
571 println("I'm sleeping $i ...")
572 delay(500L)
573 }
574 } finally {
575 println("I'm running finally")
576 }
577 }
578 delay(1300L) // delay a bit
579 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300580 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300581 println("main: Now I can quit.")
582}
583```
584
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300585> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300586
Roman Elizarov88396732017-09-27 21:30:47 +0300587Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
588so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300589
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300590```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300591I'm sleeping 0 ...
592I'm sleeping 1 ...
593I'm sleeping 2 ...
594main: I'm tired of waiting!
595I'm running finally
596main: Now I can quit.
597```
598
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300599<!--- TEST -->
600
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300601### Run non-cancellable block
602
Roman Elizarovc32579e2018-09-09 19:21:43 +0300603Any attempt to use a suspending function in the `finally` block of the previous example causes
Roman Elizarov419a6c82017-02-09 18:36:22 +0300604[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300605problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
606communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
607rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300608`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300609
610```kotlin
611fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300612 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300613 try {
614 repeat(1000) { i ->
615 println("I'm sleeping $i ...")
616 delay(500L)
617 }
618 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300619 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300620 println("I'm running finally")
621 delay(1000L)
622 println("And I've just delayed for 1 sec because I'm non-cancellable")
623 }
624 }
625 }
626 delay(1300L) // delay a bit
627 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300628 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300629 println("main: Now I can quit.")
630}
631```
632
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300633> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300634
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300635<!--- TEST
636I'm sleeping 0 ...
637I'm sleeping 1 ...
638I'm sleeping 2 ...
639main: I'm tired of waiting!
640I'm running finally
641And I've just delayed for 1 sec because I'm non-cancellable
642main: Now I can quit.
643-->
644
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300645### Timeout
646
Brad977ada12018-07-19 16:01:40 -0400647The most obvious reason to cancel coroutine execution in practice
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300648is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300649While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
650the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300651Look at the following example:
652
653```kotlin
654fun main(args: Array<String>) = runBlocking<Unit> {
655 withTimeout(1300L) {
656 repeat(1000) { i ->
657 println("I'm sleeping $i ...")
658 delay(500L)
659 }
660 }
661}
662```
663
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300664> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300665
666It produces the following output:
667
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300668```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300669I'm sleeping 0 ...
670I'm sleeping 1 ...
671I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300672Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300673```
674
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300675<!--- TEST STARTS_WITH -->
676
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300677The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300678We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300679inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300680However, in this example we have used `withTimeout` right inside the `main` function.
681
Roman Elizarovc32579e2018-09-09 19:21:43 +0300682Because cancellation is just an exception, all the resources are closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300683You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
684you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300685that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
686
687```kotlin
688fun main(args: Array<String>) = runBlocking<Unit> {
689 val result = withTimeoutOrNull(1300L) {
690 repeat(1000) { i ->
691 println("I'm sleeping $i ...")
692 delay(500L)
693 }
694 "Done" // will get cancelled before it produces this result
695 }
696 println("Result is $result")
697}
698```
699
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300700> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300701
702There is no longer an exception when running this code:
703
704```text
705I'm sleeping 0 ...
706I'm sleeping 1 ...
707I'm sleeping 2 ...
708Result is null
709```
710
711<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300712
713## Composing suspending functions
714
715This section covers various approaches to composition of suspending functions.
716
717### Sequential by default
718
719Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300720remote service call or computation. We just pretend they are useful, but actually each one just
721delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300722
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300723<!--- INCLUDE .*/example-compose-([0-9]+).kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300724import kotlin.system.*
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300725-->
726
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300727```kotlin
728suspend fun doSomethingUsefulOne(): Int {
729 delay(1000L) // pretend we are doing something useful here
730 return 13
731}
732
733suspend fun doSomethingUsefulTwo(): Int {
734 delay(1000L) // pretend we are doing something useful here, too
735 return 29
736}
737```
738
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300739<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
740
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300741What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
742`doSomethingUsefulTwo` and compute the sum of their results?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200743In 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 +0300744to invoke the second one or to decide on how to invoke it.
745
Roman Elizarovc32579e2018-09-09 19:21:43 +0300746We use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300747code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300748time it takes to execute both suspending functions:
749
750```kotlin
751fun main(args: Array<String>) = runBlocking<Unit> {
752 val time = measureTimeMillis {
753 val one = doSomethingUsefulOne()
754 val two = doSomethingUsefulTwo()
755 println("The answer is ${one + two}")
756 }
757 println("Completed in $time ms")
758}
759```
760
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300761> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300762
763It produces something like this:
764
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300765```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300766The answer is 42
767Completed in 2017 ms
768```
769
Roman Elizarov35d2c342017-07-20 14:54:39 +0300770<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300771
Roman Elizarov32d95322017-02-09 15:57:31 +0300772### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300773
774What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300775we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300776
Roman Elizarov419a6c82017-02-09 18:36:22 +0300777Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
778that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
779does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300780that 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 +0300781but `Deferred` is also a `Job`, so you can cancel it if needed.
782
783```kotlin
784fun main(args: Array<String>) = runBlocking<Unit> {
785 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300786 val one = async { doSomethingUsefulOne() }
787 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300788 println("The answer is ${one.await() + two.await()}")
789 }
790 println("Completed in $time ms")
791}
792```
793
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300794> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300795
796It produces something like this:
797
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300798```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300799The answer is 42
800Completed in 1017 ms
801```
802
Roman Elizarov35d2c342017-07-20 14:54:39 +0300803<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300804
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300805This is twice as fast, because we have concurrent execution of two coroutines.
806Note, that concurrency with coroutines is always explicit.
807
Roman Elizarov32d95322017-02-09 15:57:31 +0300808### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300809
Roman Elizarov66f018c2017-09-29 21:39:03 +0300810There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300811It starts coroutine only when its result is needed by some
812[await][Deferred.await] or if a [start][Job.start] function
Sahil Lone52a0ec02018-07-19 18:55:35 +0200813is invoked. Run the following example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300814
815```kotlin
816fun main(args: Array<String>) = runBlocking<Unit> {
817 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300818 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
819 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Sahil Lone52a0ec02018-07-19 18:55:35 +0200820 // some computation
821 one.start() // start the first one
822 two.start() // start the second one
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300823 println("The answer is ${one.await() + two.await()}")
824 }
825 println("Completed in $time ms")
826}
827```
828
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300829> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300830
831It produces something like this:
832
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300833```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300834The answer is 42
Sahil Lone52a0ec02018-07-19 18:55:35 +0200835Completed in 1017 ms
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300836```
837
Roman Elizarov35d2c342017-07-20 14:54:39 +0300838<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300839
Sahil Lone52a0ec02018-07-19 18:55:35 +0200840So, here the two coroutines are defined but not executed as in the previous example, but the control is given to
Roman Elizarovc32579e2018-09-09 19:21:43 +0300841the programmer on when exactly to start the execution by calling [start][Job.start]. We first
Sahil Lone52a0ec02018-07-19 18:55:35 +0200842start `one`, then start `two`, and then await for the individual coroutines to finish.
843
844Note, that if we have called [await][Deferred.await] in `println` and omitted [start][Job.start] on individual
845coroutines, then we would have got the sequential behaviour as [await][Deferred.await] starts the coroutine
846execution and waits for the execution to finish, which is not the intended use-case for laziness.
847The use-case for `async(start = CoroutineStart.LAZY)` is a replacement for the
848standard `lazy` function in cases when computation of the value involves suspending functions.
Roman Elizarov32d95322017-02-09 15:57:31 +0300849
850### Async-style functions
851
852We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarovc32579e2018-09-09 19:21:43 +0300853_asynchronously_ using [async] coroutine builder with an explicit [GlobalScope] reference.
854We name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100855"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
856to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300857
858```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100859// The result type of somethingUsefulOneAsync is Deferred<Int>
Roman Elizarovc32579e2018-09-09 19:21:43 +0300860fun somethingUsefulOneAsync() = GlobalScope.async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300861 doSomethingUsefulOne()
862}
863
Marcin Moskała7e94e702018-01-29 18:39:02 +0100864// The result type of somethingUsefulTwoAsync is Deferred<Int>
Roman Elizarovc32579e2018-09-09 19:21:43 +0300865fun somethingUsefulTwoAsync() = GlobalScope.async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300866 doSomethingUsefulTwo()
867}
868```
869
Marcin Moskała7e94e702018-01-29 18:39:02 +0100870Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300871However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
872with the invoking code.
873
874The following example shows their use outside of coroutine:
875
876```kotlin
877// note, that we don't have `runBlocking` to the right of `main` in this example
878fun main(args: Array<String>) {
879 val time = measureTimeMillis {
880 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100881 val one = somethingUsefulOneAsync()
882 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300883 // but waiting for a result must involve either suspending or blocking.
884 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
885 runBlocking {
886 println("The answer is ${one.await() + two.await()}")
887 }
888 }
889 println("Completed in $time ms")
890}
891```
892
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300893> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300894
Roman Elizarov35d2c342017-07-20 14:54:39 +0300895<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300896The answer is 42
897Completed in 1085 ms
898-->
899
Roman Elizarovc32579e2018-09-09 19:21:43 +0300900> This programming style with async functions is provided here only for illustration, because it is a popular style
901in other programming languages. Using this style with Kotlin coroutines is **strongly discouraged** for the
902reasons that are explained below.
903
904Consider what happens if between `val one = somethingUsefulOneAsync()` line and `one.await()` expression there is some logic
905error in the code and the program throws an exception and the operation that was being performed by the program aborts.
906Normally, a global error-handler could catch this exception, log and report the error for developers, but the program
907could otherwise continue doing other operations. But here we have `somethingUsefulOneAsync` still running in background,
908despite the fact, that operation that had initiated it aborts. This problem does not happen with structured
909concurrency, as shown in the section below.
910
911### Structured concurrency with async
912
913Let us take [Concurrent using async](#concurrent-using-async) example and extract a function that
Stephan Oudmaijer9f72ff42018-09-12 16:21:27 +0200914concurrently performs `doSomethingUsefulOne` and `doSomethingUsefulTwo` and returns the sum of their results.
Roman Elizarovc32579e2018-09-09 19:21:43 +0300915Because [async] coroutines builder is defined as extension on [CoroutineScope] we need to have it in the
916scope and that is what [coroutineScope] function provides:
917
918```kotlin
919suspend fun concurrentSum(): Int = coroutineScope {
920 val one = async { doSomethingUsefulOne() }
921 val two = async { doSomethingUsefulTwo() }
922 awaitAll(one, two)
923 one.await() + two.await()
924}
925```
926
927This way, if something goes wrong inside the code of `concurrentSum` function and it throws an exception,
928all the coroutines that were launched in its scope are cancelled.
929
930```kotlin
931fun main(args: Array<String>) = runBlocking<Unit> {
932 val time = measureTimeMillis {
933 println("The answer is ${concurrentSum()}")
934 }
935 println("Completed in $time ms")
936}
937```
938
939> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-05.kt)
940
941We still have concurrent execution of both operations as evident from the output of the above main function:
942
943```text
944The answer is 42
945Completed in 1017 ms
946```
947
948<!--- TEST ARBITRARY_TIME -->
949
950Cancellation is always propagated through coroutines hierarchy:
951
952```kotlin
953fun main(args: Array<String>) = runBlocking<Unit> {
954 try {
955 failedConcurrentSum()
956 } catch(e: ArithmeticException) {
957 println("Computation failed with ArithmeticException")
958 }
959}
960
961suspend fun failedConcurrentSum(): Int = coroutineScope {
962 val one = async<Int> {
963 try {
964 delay(Long.MAX_VALUE) // Emulates very long computation
965 42
966 } finally {
967 println("First child was cancelled")
968 }
969 }
970 val two = async<Int> {
971 println("Second child throws an exception")
972 throw ArithmeticException()
973 }
974
975 awaitAll(one, two)
976 one.await() + two.await()
977}
978```
979
980> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-06.kt)
981
982Note, how both first `async` and awaiting parent are cancelled on the one child failure:
983```text
984Second child throws an exception
985First child was cancelled
986Computation failed with ArithmeticException
987```
988
989<!--- TEST -->
990
991
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300992## Coroutine context and dispatchers
993
Roman Elizarov66f018c2017-09-29 21:39:03 +0300994Coroutines always execute in some context which is represented by the value of
995[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
996type, defined in the Kotlin standard library.
997
998The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
999which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001000
1001### Dispatchers and threads
1002
Roman Elizarov66f018c2017-09-29 21:39:03 +03001003Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001004the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +03001005to a specific thread, dispatch it to a thread pool, or let it run unconfined.
1006
1007All coroutines builders like [launch] and [async] accept an optional
1008[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
1009parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
1010
1011Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001012
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001013<!--- INCLUDE
1014import kotlin.coroutines.experimental.*
1015-->
1016
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001017```kotlin
1018fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001019 launch { // context of the parent, main runBlocking coroutine
1020 println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001021 }
Roman Elizarovdc29b072018-09-11 18:42:03 +03001022 launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
Roman Elizarovc32579e2018-09-09 19:21:43 +03001023 println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001024 }
Roman Elizarovdc29b072018-09-11 18:42:03 +03001025 launch(Dispatchers.Default) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
1026 println("Default : I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001027 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001028 launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
1029 println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001030 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001031}
1032```
1033
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001034> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001035
1036It produces the following output (maybe in different order):
1037
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001038```text
Roman Elizarovc32579e2018-09-09 19:21:43 +03001039Unconfined : I'm working in thread main
Roman Elizarovdc29b072018-09-11 18:42:03 +03001040Default : I'm working in thread CommonPool-worker-1
Roman Elizarovc32579e2018-09-09 19:21:43 +03001041newSingleThreadContext: I'm working in thread MyOwnThread
1042main runBlocking : I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001043```
1044
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001045<!--- TEST LINES_START_UNORDERED -->
1046
Roman Elizarovc32579e2018-09-09 19:21:43 +03001047When `launch { ... }` is used without parameters, it inherits the context (and thus dispatcher)
1048from the [CoroutineScope] that it is being launched from. In this case, it inherits the
1049context of the main `runBlocking` coroutine which runs in the `main` thread.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001050
Roman Elizarovdc29b072018-09-11 18:42:03 +03001051[Dispatchers.Unconfined] is a special dispatcher that also appears to run in the `main` thread, but it is,
Roman Elizarovc32579e2018-09-09 19:21:43 +03001052in fact, a different mechanism that is explained later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001053
Roman Elizarovc32579e2018-09-09 19:21:43 +03001054The default dispatcher, that is used when coroutines are launched in [GlobalScope],
Roman Elizarovdc29b072018-09-11 18:42:03 +03001055is represented by [Dispatchers.Default] and uses shared background pool of threads,
1056so `launch(Dispatchers.Default) { ... }` uses the same dispatcher as `GlobalScope.launch { ... }`.
Roman Elizarovc32579e2018-09-09 19:21:43 +03001057
1058[newSingleThreadContext] creates a new thread for the coroutine to run.
1059A dedicated thread is a very expensive resource.
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001060In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
1061function, or stored in a top-level variable and reused throughout the application.
1062
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001063### Unconfined vs confined dispatcher
1064
Roman Elizarovdc29b072018-09-11 18:42:03 +03001065The [Dispatchers.Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001066first suspension point. After suspension it resumes in the thread that is fully determined by the
1067suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
1068consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
1069
Roman Elizarovc32579e2018-09-09 19:21:43 +03001070On the other side, by default, a dispatcher for the outer [CoroutineScope] is inherited.
1071The default dispatcher for [runBlocking] coroutine, in particular,
Roman Elizarov66f018c2017-09-29 21:39:03 +03001072is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001073this thread with a predictable FIFO scheduling.
1074
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001075<!--- INCLUDE
1076import kotlin.coroutines.experimental.*
1077-->
1078
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001079```kotlin
1080fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovdc29b072018-09-11 18:42:03 +03001081 launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
Roman Elizarovc32579e2018-09-09 19:21:43 +03001082 println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +03001083 delay(500)
Roman Elizarovc32579e2018-09-09 19:21:43 +03001084 println("Unconfined : After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001085 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001086 launch { // context of the parent, main runBlocking coroutine
1087 println("main runBlocking: I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001088 delay(1000)
Roman Elizarovc32579e2018-09-09 19:21:43 +03001089 println("main runBlocking: After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001090 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001091}
1092```
1093
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001094> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001095
1096Produces the output:
1097
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001098```text
Roman Elizarovc32579e2018-09-09 19:21:43 +03001099Unconfined : I'm working in thread main
1100main runBlocking: I'm working in thread main
1101Unconfined : After delay in thread kotlinx.coroutines.DefaultExecutor
1102main runBlocking: After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001103```
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001104
1105<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001106
Roman Elizarovc32579e2018-09-09 19:21:43 +03001107So, the coroutine that had inherited context of `runBlocking {...}` continues to execute
Roman Elizarov43e3af72017-07-21 16:01:31 +03001108in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
1109function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001110
Roman Elizarovdc29b072018-09-11 18:42:03 +03001111> Unconfined dispatcher is an advanced mechanism that can be helpful in certain corner cases where
Roman Elizarovc32579e2018-09-09 19:21:43 +03001112dispatching of coroutine for its execution later is not needed or produces undesirable side-effects,
1113because some operation in a coroutine must be performed right away.
Roman Elizarovdc29b072018-09-11 18:42:03 +03001114Unconfined dispatcher should not be used in general code.
Roman Elizarovc32579e2018-09-09 19:21:43 +03001115
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001116### Debugging coroutines and threads
1117
Roman Elizarovc32579e2018-09-09 19:21:43 +03001118Coroutines can suspend on one thread and resume on another thread.
1119Even with a single-threaded dispatcher it might be hard to
paolopb019b102018-06-09 16:42:24 +00001120figure out what coroutine was doing, where, and when. The common approach to debugging applications with
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001121threads is to print the thread name in the log file on each log statement. This feature is universally supported
1122by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
1123`kotlinx.coroutines` includes debugging facilities to make it easier.
1124
1125Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
1126
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001127<!--- INCLUDE
1128import kotlin.coroutines.experimental.*
1129-->
1130
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001131```kotlin
1132fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1133
1134fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001135 val a = async {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001136 log("I'm computing a piece of the answer")
1137 6
1138 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001139 val b = async {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001140 log("I'm computing another piece of the answer")
1141 7
1142 }
1143 log("The answer is ${a.await() * b.await()}")
1144}
1145```
1146
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001147> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001148
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001149There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001150and two coroutines computing deferred values `a` (#2) and `b` (#3).
1151They are all executing in the context of `runBlocking` and are confined to the main thread.
1152The output of this code is:
1153
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001154```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001155[main @coroutine#2] I'm computing a piece of the answer
1156[main @coroutine#3] I'm computing another piece of the answer
1157[main @coroutine#1] The answer is 42
1158```
1159
Kirill Timofeeva5186962017-10-25 14:25:47 +03001160<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001161
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001162The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
1163thread, but the identifier of the currently executing coroutine is appended to it. This identifier
1164is consecutively assigned to all created coroutines when debugging mode is turned on.
1165
Roman Elizarov419a6c82017-02-09 18:36:22 +03001166You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001167
1168### Jumping between threads
1169
Roman Elizarovc32579e2018-09-09 19:21:43 +03001170Run the following code with `-Dkotlinx.coroutines.debug` JVM option (see [debug](#debugging-coroutines-and-threads)):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001171
1172```kotlin
1173fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1174
1175fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001176 newSingleThreadContext("Ctx1").use { ctx1 ->
1177 newSingleThreadContext("Ctx2").use { ctx2 ->
1178 runBlocking(ctx1) {
1179 log("Started in ctx1")
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001180 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001181 log("Working in ctx2")
1182 }
1183 log("Back to ctx1")
1184 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001185 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001186 }
1187}
1188```
1189
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001190> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001191
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001192It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001193the 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 +03001194same coroutine as you can see in the output below:
1195
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001196```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001197[Ctx1 @coroutine#1] Started in ctx1
1198[Ctx2 @coroutine#1] Working in ctx2
1199[Ctx1 @coroutine#1] Back to ctx1
1200```
1201
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001202<!--- TEST -->
1203
Artsiom Chapialioue185ed62018-06-03 19:34:22 -04001204Note, that this example also uses `use` function from the Kotlin standard library to release threads that
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001205are created with [newSingleThreadContext] when they are no longer needed.
1206
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001207### Job in the context
1208
Roman Elizarov66f018c2017-09-29 21:39:03 +03001209The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001210using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001211
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001212<!--- INCLUDE
1213import kotlin.coroutines.experimental.*
1214-->
1215
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001216```kotlin
1217fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001218 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001219}
1220```
1221
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001222> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001223
Roman Elizarov66f018c2017-09-29 21:39:03 +03001224It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001225
1226```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001227My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001228```
1229
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001230<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001231
Roman Elizarovc32579e2018-09-09 19:21:43 +03001232Note, that [isActive] in [CoroutineScope] is just a convenient shortcut for
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001233`coroutineContext[Job]?.isActive == true`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001234
1235### Children of a coroutine
1236
Roman Elizarovc32579e2018-09-09 19:21:43 +03001237When a coroutine is launched in the [CoroutineScope] of another coroutine,
1238it inherits its context via [CoroutineScope.coroutineContext] and
Roman Elizarov419a6c82017-02-09 18:36:22 +03001239the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001240a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1241are recursively cancelled, too.
Roman Elizarovc32579e2018-09-09 19:21:43 +03001242
1243However, when [GlobalScope] is used to launch a coroutine, it is not tied to the scope it
1244was launched from and operates independently.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001245
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001246<!--- INCLUDE
1247import kotlin.coroutines.experimental.*
1248-->
1249
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001250```kotlin
1251fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001252 // launch a coroutine to process some kind of incoming request
1253 val request = launch {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001254 // it spawns two other jobs, one with GlobalScope
1255 GlobalScope.launch {
1256 println("job1: I run in GlobalScope and execute independently!")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001257 delay(1000)
1258 println("job1: I am not affected by cancellation of the request")
1259 }
1260 // and the other inherits the parent context
Roman Elizarovc32579e2018-09-09 19:21:43 +03001261 launch {
Roman Elizarov74619c12017-11-09 10:32:15 +03001262 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001263 println("job2: I am a child of the request coroutine")
1264 delay(1000)
1265 println("job2: I will not execute this line if my parent request is cancelled")
1266 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001267 }
1268 delay(500)
1269 request.cancel() // cancel processing of the request
1270 delay(1000) // delay a second to see what happens
1271 println("main: Who has survived request cancellation?")
1272}
1273```
1274
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001275> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001276
1277The output of this code is:
1278
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001279```text
Roman Elizarovc32579e2018-09-09 19:21:43 +03001280job1: I run in GlobalScope and execute independently!
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001281job2: I am a child of the request coroutine
1282job1: I am not affected by cancellation of the request
1283main: Who has survived request cancellation?
1284```
1285
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001286<!--- TEST -->
1287
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001288### Parental responsibilities
1289
1290A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001291all 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 +03001292
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001293<!--- INCLUDE
1294import kotlin.coroutines.experimental.*
1295-->
1296
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001297```kotlin
1298fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001299 // launch a coroutine to process some kind of incoming request
1300 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001301 repeat(3) { i -> // launch a few children jobs
Roman Elizarovc32579e2018-09-09 19:21:43 +03001302 launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001303 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1304 println("Coroutine $i is done")
1305 }
1306 }
1307 println("request: I'm done and I don't explicitly join my children that are still active")
1308 }
1309 request.join() // wait for completion of the request, including all its children
1310 println("Now processing of the request is complete")
1311}
1312```
1313
Roman Elizarovc32579e2018-09-09 19:21:43 +03001314> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-07.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001315
1316The result is going to be:
1317
1318```text
1319request: I'm done and I don't explicitly join my children that are still active
1320Coroutine 0 is done
1321Coroutine 1 is done
1322Coroutine 2 is done
1323Now processing of the request is complete
1324```
1325
1326<!--- TEST -->
1327
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001328### Naming coroutines for debugging
1329
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001330Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001331coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1332or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001333[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1334is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001335
1336The following example demonstrates this concept:
1337
1338```kotlin
1339fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1340
1341fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1342 log("Started main coroutine")
1343 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001344 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001345 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001346 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001347 252
1348 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001349 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001350 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001351 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001352 6
1353 }
1354 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1355}
1356```
1357
Roman Elizarovc32579e2018-09-09 19:21:43 +03001358> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-08.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001359
1360The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1361
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001362```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001363[main @main#1] Started main coroutine
Roman Elizarovc32579e2018-09-09 19:21:43 +03001364[main @v1coroutine#2] Computing v1
1365[main @v2coroutine#3] Computing v2
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001366[main @main#1] The answer for v1 / v2 = 42
1367```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001368
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001369<!--- TEST FLEXIBLE_THREAD -->
1370
Roman Elizarovc32579e2018-09-09 19:21:43 +03001371### Combining context elements
1372
1373Sometimes we need to define multiple elements for coroutine context. We can use `+` operator for that.
1374For example, we can launch a coroutine with an explicitly specified dispatcher and an explicitly specified
1375name at the same time:
1376
1377<!--- INCLUDE
1378import kotlin.coroutines.experimental.*
1379-->
1380
1381```kotlin
1382fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovdc29b072018-09-11 18:42:03 +03001383 launch(Dispatchers.Default + CoroutineName("test")) {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001384 println("I'm working in thread ${Thread.currentThread().name}")
1385 }
1386}
1387```
1388
1389> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-09.kt)
1390
1391The output of this code with `-Dkotlinx.coroutines.debug` JVM option is:
1392
1393```text
1394I'm working in thread CommonPool-worker-1 @test#2
1395```
1396
Roman Elizarovbca98f42018-09-19 14:49:42 +03001397<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarovc32579e2018-09-09 19:21:43 +03001398
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001399### Cancellation via explicit job
1400
1401Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1402an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1403and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1404and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1405to avoid memory leaks.
1406
Roman Elizarovc32579e2018-09-09 19:21:43 +03001407We manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
1408the lifecycle of our activity. A job instance is created using [Job()] factory function when
1409activity is created and it is cancelled when an activity is destroyed like this:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001410
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001411<!--- INCLUDE
1412import kotlin.coroutines.experimental.*
1413-->
1414
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001415```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03001416class Activity : CoroutineScope {
1417 lateinit var job: Job
1418
1419 fun create() {
1420 job = Job()
1421 }
1422
1423 fun destroy() {
1424 job.cancel()
1425 }
1426 // to be continued ...
1427```
1428
1429We also implement [CoroutineScope] interface in this `Actvity` class. We only need to provide an override
1430for its [CoroutineScope.coroutineContext] property to specify the context for coroutines launched in its
Roman Elizarovdc29b072018-09-11 18:42:03 +03001431scope. We combine the desired dispatcher (we used [Dispatchers.Default] in this example) and a job:
Roman Elizarovc32579e2018-09-09 19:21:43 +03001432
1433```kotlin
1434 // class Activity continues
1435 override val coroutineContext: CoroutineContext
Roman Elizarovdc29b072018-09-11 18:42:03 +03001436 get() = Dispatchers.Default + job
Roman Elizarovc32579e2018-09-09 19:21:43 +03001437 // to be continued ...
1438```
1439
1440Now, we can launch coroutines in the scope of this `Activity` without having to explicitly
1441specify their context. For the demo, we launch ten coroutines that delay for a different time:
1442
1443```kotlin
1444 // class Activity continues
1445 fun doSomething() {
1446 // launch ten coroutines for a demo, each working for a different time
1447 repeat(10) { i ->
1448 launch {
1449 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
1450 println("Coroutine $i is done")
1451 }
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001452 }
1453 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001454} // class Activity ends
1455```
1456
1457In our main function we create activity, call our test `doSomething` function, and destroy activity after 500ms.
1458This cancels all the coroutines that were launched which we can confirm by noting that it does not print
1459onto the screen anymore if we wait:
1460
1461
1462```kotlin
1463fun main(args: Array<String>) = runBlocking<Unit> {
1464 val activity = Activity()
1465 activity.create() // create an activity
1466 activity.doSomething() // run test function
1467 println("Launched coroutines")
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001468 delay(500L) // delay for half a second
Roman Elizarovc32579e2018-09-09 19:21:43 +03001469 println("Destroying activity!")
1470 activity.destroy() // cancels all coroutines
1471 delay(1000) // visually confirm that they don't work
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001472}
1473```
1474
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001475> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-10.kt)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001476
1477The output of this example is:
1478
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001479```text
Roman Elizarovc32579e2018-09-09 19:21:43 +03001480Launched coroutines
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001481Coroutine 0 is done
1482Coroutine 1 is done
Roman Elizarovc32579e2018-09-09 19:21:43 +03001483Destroying activity!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001484```
1485
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001486<!--- TEST -->
1487
Roman Elizarovc32579e2018-09-09 19:21:43 +03001488As you can see, only the first two coroutines had printed a message and the others were cancelled
1489by a single invocation of `job.cancel()` in `Activity.destroy()`.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001490
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001491### Thread-local data
1492
Roman Elizarovc32579e2018-09-09 19:21:43 +03001493Sometimes it is convenient to have an ability to pass some thread-local data, but, for coroutines, which
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001494are not bound to any particular thread, it is hard to achieve it manually without writing a lot of boilerplate.
1495
1496For [`ThreadLocal`](https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html),
Roman Elizarovc32579e2018-09-09 19:21:43 +03001497[asContextElement] extension function is here for the rescue. It creates an additional context element,
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001498which keep the value of the given `ThreadLocal` and restores it every time the coroutine switches its context.
1499
1500It is easy to demonstrate it in action:
1501
1502<!--- INCLUDE
1503import kotlin.coroutines.experimental.*
1504-->
1505
1506```kotlin
1507val threadLocal = ThreadLocal<String?>() // declare thread-local variable
1508
1509fun main(args: Array<String>) = runBlocking<Unit> {
1510 threadLocal.set("main")
1511 println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
Roman Elizarovdc29b072018-09-11 18:42:03 +03001512 val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001513 println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001514 yield()
1515 println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
1516 }
1517 job.join()
1518 println("Post-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'")
1519}
1520```
1521
1522> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-11.kt)
1523
Roman Elizarovdc29b072018-09-11 18:42:03 +03001524In this example we launch new coroutine in a background thread pool using [Dispatchers.Default], so
Roman Elizarovc32579e2018-09-09 19:21:43 +03001525it works on a different threads from a thread pool, but it still has the value of thread local variable,
1526that we've specified using `threadLocal.asContextElement(value = "launch")`,
1527no matter on what thread the coroutine is executed.
1528Thus, output (with [debug](#debugging-coroutines-and-threads)) is:
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001529
1530```text
1531Pre-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
Roman Elizarovc32579e2018-09-09 19:21:43 +03001532Launch start, current thread: Thread[CommonPool-worker-1 @coroutine#2,5,main], thread local value: 'launch'
1533After yield, current thread: Thread[CommonPool-worker-2 @coroutine#2,5,main], thread local value: 'launch'
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001534Post-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'
1535```
1536
1537<!--- TEST FLEXIBLE_THREAD -->
1538
Daniel Tam719ee9a2018-09-12 22:10:09 +10001539`ThreadLocal` has first-class support and can be used with any primitive `kotlinx.coroutines` provides.
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001540It has one key limitation: when thread-local is mutated, a new value is not propagated to the coroutine caller
1541(as context element cannot track all `ThreadLocal` object accesses) and updated value is lost on the next suspension.
1542Use [withContext] to update the value of the thread-local in a coroutine, see [asContextElement] for more details.
1543
1544Alternatively, a value can be stored in a mutable box like `class Counter(var i: Int)`, which is, in turn,
1545is stored in a thread-local variable. However, in this case you are fully responsible to synchronize
Roman Elizarovc32579e2018-09-09 19:21:43 +03001546potentially concurrent modifications to the variable in this mutable box.
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03001547
1548For advanced usage, for example for integration with logging MDC, transactional contexts or any other libraries
1549which internally use thread-locals for passing data, see documentation for [ThreadContextElement] interface
1550that should be implemented.
1551
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001552## Exception handling
1553
1554<!--- INCLUDE .*/example-exceptions-([0-9]+).kt
1555-->
1556
1557This section covers exception handling and cancellation on exceptions.
1558We already know that cancelled coroutine throws [CancellationException] in suspension points and that it
1559is ignored by coroutines machinery. But what happens if an exception is thrown during cancellation or multiple children of the same
1560coroutine throw an exception?
1561
1562### Exception propagation
Roman Elizarov563da402018-08-10 19:18:56 +03001563
Roman Elizarovc32579e2018-09-09 19:21:43 +03001564Coroutine builders come in two flavors: propagating exceptions automatically ([launch] and [actor]) or
1565exposing them to users ([async] and [produce]).
1566The former treat exceptions as unhandled, similar to Java's `Thread.uncaughExceptionHandler`,
1567while the latter are relying on the user to consume the final
Roman Elizarov563da402018-08-10 19:18:56 +03001568exception, for example via [await][Deferred.await] or [receive][ReceiveChannel.receive]
1569([produce] and [receive][ReceiveChannel.receive] are covered later in [Channels](#channels) section).
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001570
Roman Elizarovc32579e2018-09-09 19:21:43 +03001571It can be demonstrated by a simple example that creates new coroutines in [GlobalScope]:
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001572
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001573```kotlin
1574fun main(args: Array<String>) = runBlocking {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001575 val job = GlobalScope.launch {
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001576 println("Throwing exception from launch")
1577 throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
1578 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001579 job.join()
1580 println("Joined failed job")
Roman Elizarovc32579e2018-09-09 19:21:43 +03001581 val deferred = GlobalScope.async {
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001582 println("Throwing exception from async")
1583 throw ArithmeticException() // Nothing is printed, relying on user to call await
1584 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001585 try {
1586 deferred.await()
1587 println("Unreached")
1588 } catch (e: ArithmeticException) {
1589 println("Caught ArithmeticException")
1590 }
1591}
1592```
1593
1594> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-01.kt)
1595
Roman Elizarovc32579e2018-09-09 19:21:43 +03001596The output of this code is (with [debug](#debugging-coroutines-and-threads)):
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001597
1598```text
1599Throwing exception from launch
1600Exception in thread "ForkJoinPool.commonPool-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
1601Joined failed job
1602Throwing exception from async
1603Caught ArithmeticException
1604```
1605
1606<!--- TEST EXCEPTION-->
1607
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001608### CoroutineExceptionHandler
1609
1610But what if one does not want to print all exceptions to the console?
1611[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 +03001612It is similar to using [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
1613
Roman Elizarovc32579e2018-09-09 19:21:43 +03001614On JVM it is possible to redefine global exception handler for all coroutines by registering [CoroutineExceptionHandler] via
Roman Elizarov563da402018-08-10 19:18:56 +03001615[`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html).
1616Global exception handler is similar to
1617[`Thread.defaultUncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler))
1618which is used when no more specific handlers are registered.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001619On Android, `uncaughtExceptionPreHandler` is installed as a global coroutine exception handler.
1620
Roman Elizarov563da402018-08-10 19:18:56 +03001621[CoroutineExceptionHandler] is invoked only on exceptions which are not expected to be handled by the user,
1622so registering it in [async] builder and the like of it has no effect.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001623
1624```kotlin
1625fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001626 val handler = CoroutineExceptionHandler { _, exception ->
1627 println("Caught $exception")
1628 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001629 val job = GlobalScope.launch(handler) {
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001630 throw AssertionError()
1631 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001632 val deferred = GlobalScope.async(handler) {
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001633 throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
1634 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001635 joinAll(job, deferred)
1636}
1637```
1638
1639> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-02.kt)
1640
1641The output of this code is:
1642
1643```text
1644Caught java.lang.AssertionError
1645```
1646
1647<!--- TEST-->
1648
1649### Cancellation and exceptions
Roman Elizarov563da402018-08-10 19:18:56 +03001650
1651Cancellation is tightly bound with exceptions. Coroutines internally use `CancellationException` for cancellation, these
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001652exceptions are ignored by all handlers, so they should be used only as the source of additional debug information, which can
1653be obtained by `catch` block.
Roman Elizarov563da402018-08-10 19:18:56 +03001654When a coroutine is cancelled using [Job.cancel] without a cause, it terminates, but it does not cancel its parent.
1655Cancelling without cause is a mechanism for parent to cancel its children without cancelling itself.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001656
1657<!--- INCLUDE
1658import kotlin.coroutines.experimental.*
1659-->
1660
1661```kotlin
1662fun main(args: Array<String>) = runBlocking {
Roman Elizarovc32579e2018-09-09 19:21:43 +03001663 val job = launch {
1664 val child = launch {
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001665 try {
1666 delay(Long.MAX_VALUE)
1667 } finally {
1668 println("Child is cancelled")
1669 }
1670 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001671 yield()
1672 println("Cancelling child")
1673 child.cancel()
1674 child.join()
1675 yield()
1676 println("Parent is not cancelled")
1677 }
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001678 job.join()
1679}
1680```
1681
1682> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-03.kt)
1683
1684The output of this code is:
1685
1686```text
1687Cancelling child
1688Child is cancelled
1689Parent is not cancelled
1690```
1691
1692<!--- TEST-->
1693
Roman Elizarov563da402018-08-10 19:18:56 +03001694If a coroutine encounters exception other than `CancellationException`, it cancels its parent with that exception.
Roman Elizarovc32579e2018-09-09 19:21:43 +03001695This behaviour cannot be overridden and is used to provide stable coroutines hierarchies for
1696[structured concurrency](#structured-concurrency) which do not depend on
1697[CoroutineExceptionHandler] implementation.
Roman Elizarov563da402018-08-10 19:18:56 +03001698The original exception is handled by the parent when all its children terminate.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001699
Roman Elizarovc32579e2018-09-09 19:21:43 +03001700> This also a reason why, in these examples, [CoroutineExceptionHandler] is always installed to a coroutine
1701that is created in [GlobalScope]. It does not make sense to install an exception handler to a coroutine that
1702is launched in the scope of the main [runBlocking], since the main coroutine is going to be always cancelled
1703when its child completes with exception despite the installed handler.
1704
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001705<!--- INCLUDE
1706import kotlin.coroutines.experimental.*
1707-->
1708
1709```kotlin
1710fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001711 val handler = CoroutineExceptionHandler { _, exception ->
1712 println("Caught $exception")
1713 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001714 val job = GlobalScope.launch(handler) {
1715 launch { // the first child
Roman Elizarov563da402018-08-10 19:18:56 +03001716 try {
1717 delay(Long.MAX_VALUE)
1718 } finally {
1719 withContext(NonCancellable) {
1720 println("Children are cancelled, but exception is not handled until all children terminate")
1721 delay(100)
Roman Elizarovc32579e2018-09-09 19:21:43 +03001722 println("The first child finished its non cancellable block")
Roman Elizarov563da402018-08-10 19:18:56 +03001723 }
1724 }
1725 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001726 launch { // the second child
Roman Elizarov563da402018-08-10 19:18:56 +03001727 delay(10)
1728 println("Second child throws an exception")
1729 throw ArithmeticException()
1730 }
1731 }
1732 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001733}
1734```
1735
1736> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-04.kt)
1737
1738The output of this code is:
1739
1740```text
Roman Elizarov563da402018-08-10 19:18:56 +03001741Second child throws an exception
1742Children are cancelled, but exception is not handled until all children terminate
Roman Elizarovc32579e2018-09-09 19:21:43 +03001743The first child finished its non cancellable block
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001744Caught java.lang.ArithmeticException
1745```
1746<!--- TEST-->
1747
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001748### Exceptions aggregation
Roman Elizarov563da402018-08-10 19:18:56 +03001749
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001750What happens if multiple children of a coroutine throw an exception?
Roman Elizarov563da402018-08-10 19:18:56 +03001751The general rule is "the first exception wins", so the first thrown exception is exposed to the handler.
1752But that may cause lost exceptions, for example if coroutine throws an exception in its `finally` block.
Roman Elizarovc32579e2018-09-09 19:21:43 +03001753So, additional exceptions are suppressed.
Roman Elizarov563da402018-08-10 19:18:56 +03001754
Roman Elizarovc32579e2018-09-09 19:21:43 +03001755> One of the solutions would have been to report each exception separately,
Roman Elizarov563da402018-08-10 19:18:56 +03001756but then [Deferred.await] should have had the same mechanism to avoid behavioural inconsistency and this
1757would cause implementation details of a coroutines (whether it had delegate parts of its work to its children or not)
1758to leak to its exception handler.
1759
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001760<!--- INCLUDE
1761import kotlinx.coroutines.experimental.exceptions.*
1762import kotlin.coroutines.experimental.*
1763import java.io.*
1764-->
1765
1766```kotlin
1767fun main(args: Array<String>) = runBlocking {
1768 val handler = CoroutineExceptionHandler { _, exception ->
Roman Elizarov563da402018-08-10 19:18:56 +03001769 println("Caught $exception with suppressed ${exception.suppressed().contentToString()}")
1770 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001771 val job = GlobalScope.launch(handler) {
1772 launch {
Roman Elizarov563da402018-08-10 19:18:56 +03001773 try {
1774 delay(Long.MAX_VALUE)
1775 } finally {
1776 throw ArithmeticException()
1777 }
1778 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001779 launch {
Roman Elizarov563da402018-08-10 19:18:56 +03001780 throw IOException()
1781 }
1782 delay(Long.MAX_VALUE)
1783 }
1784 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001785}
1786```
1787
1788> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-05.kt)
1789
1790The output of this code is:
1791
1792```text
1793Caught java.io.IOException with suppressed [java.lang.ArithmeticException]
1794```
Roman Elizarovc32579e2018-09-09 19:21:43 +03001795
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001796<!--- TEST-->
1797
Roman Elizarovc32579e2018-09-09 19:21:43 +03001798> Note, this mechanism currently works only on Java version 1.7+.
Roman Elizarov563da402018-08-10 19:18:56 +03001799Limitation on JS and Native is temporary and will be fixed in the future.
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001800
1801Cancellation exceptions are transparent and unwrapped by default:
1802
1803<!--- INCLUDE
1804import kotlin.coroutines.experimental.*
1805import java.io.*
1806-->
1807
1808```kotlin
1809fun main(args: Array<String>) = runBlocking {
Roman Elizarov563da402018-08-10 19:18:56 +03001810 val handler = CoroutineExceptionHandler { _, exception ->
1811 println("Caught original $exception")
1812 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03001813 val job = GlobalScope.launch(handler) {
1814 val inner = launch {
1815 launch {
1816 launch {
Roman Elizarov563da402018-08-10 19:18:56 +03001817 throw IOException()
1818 }
1819 }
1820 }
1821 try {
1822 inner.join()
1823 } catch (e: JobCancellationException) {
1824 println("Rethrowing JobCancellationException with original cause")
1825 throw e
1826 }
1827 }
1828 job.join()
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03001829}
1830```
1831
1832> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt)
1833
1834The output of this code is:
1835
1836```text
1837Rethrowing JobCancellationException with original cause
1838Caught original java.io.IOException
1839```
1840<!--- TEST-->
1841
Roman Elizarovc32579e2018-09-09 19:21:43 +03001842## Channels (experimental)
Roman Elizarov7deefb82017-01-31 10:33:17 +03001843
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001844Deferred values provide a convenient way to transfer a single value between coroutines.
1845Channels provide a way to transfer a stream of values.
1846
Roman Elizarovc32579e2018-09-09 19:21:43 +03001847> Channels are an experimental feature of `kotlinx.coroutines`. Their API is expected to
1848evolve in the upcoming updates of the `kotlinx.coroutines` library with potentially
1849breaking changes.
1850
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001851<!--- INCLUDE .*/example-channel-([0-9]+).kt
1852import kotlinx.coroutines.experimental.channels.*
1853-->
1854
1855### Channel basics
1856
Roman Elizarov419a6c82017-02-09 18:36:22 +03001857A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1858instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1859a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001860
1861```kotlin
1862fun main(args: Array<String>) = runBlocking<Unit> {
1863 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001864 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001865 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1866 for (x in 1..5) channel.send(x * x)
1867 }
1868 // here we print five received integers:
1869 repeat(5) { println(channel.receive()) }
1870 println("Done!")
1871}
1872```
1873
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001874> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-01.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001875
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001876The output of this code is:
1877
1878```text
18791
18804
18819
188216
188325
1884Done!
1885```
1886
1887<!--- TEST -->
1888
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001889### Closing and iteration over channels
1890
1891Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1892On the receiver side it is convenient to use a regular `for` loop to receive elements
1893from the channel.
1894
Roman Elizarov419a6c82017-02-09 18:36:22 +03001895Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001896The iteration stops as soon as this close token is received, so there is a guarantee
1897that all previously sent elements before the close are received:
1898
1899```kotlin
1900fun main(args: Array<String>) = runBlocking<Unit> {
1901 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001902 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001903 for (x in 1..5) channel.send(x * x)
1904 channel.close() // we're done sending
1905 }
1906 // here we print received values using `for` loop (until the channel is closed)
1907 for (y in channel) println(y)
1908 println("Done!")
1909}
1910```
1911
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001912> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001913
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001914<!--- TEST
19151
19164
19179
191816
191925
1920Done!
1921-->
1922
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001923### Building channel producers
1924
Roman Elizarova5e653f2017-02-13 13:49:55 +03001925The pattern where a coroutine is producing a sequence of elements is quite common.
1926This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001927You 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 +03001928to common sense that results must be returned from functions.
1929
Roman Elizarov86349be2017-03-17 16:47:37 +03001930There 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 +03001931and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001932
1933```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03001934fun CoroutineScope.produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001935 for (x in 1..5) send(x * x)
1936}
1937
1938fun main(args: Array<String>) = runBlocking<Unit> {
1939 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001940 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001941 println("Done!")
1942}
1943```
1944
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001945> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-03.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001946
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001947<!--- TEST
19481
19494
19509
195116
195225
1953Done!
1954-->
1955
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001956### Pipelines
1957
Roman Elizarov66f018c2017-09-29 21:39:03 +03001958A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001959
1960```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03001961fun CoroutineScope.produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001962 var x = 1
1963 while (true) send(x++) // infinite stream of integers starting from 1
1964}
1965```
1966
Roman Elizarova5e653f2017-02-13 13:49:55 +03001967And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001968In the below example the numbers are just squared:
1969
1970```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03001971fun CoroutineScope.square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001972 for (x in numbers) send(x * x)
1973}
1974```
1975
Roman Elizarova5e653f2017-02-13 13:49:55 +03001976The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001977
1978```kotlin
1979fun main(args: Array<String>) = runBlocking<Unit> {
1980 val numbers = produceNumbers() // produces integers from 1 and on
1981 val squares = square(numbers) // squares integers
1982 for (i in 1..5) println(squares.receive()) // print first five
1983 println("Done!") // we are done
Roman Elizarovc32579e2018-09-09 19:21:43 +03001984 coroutineContext.cancelChildren() // cancel children coroutines
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001985}
1986```
1987
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001988> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-04.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001989
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001990<!--- TEST
19911
19924
19939
199416
199525
1996Done!
1997-->
1998
Roman Elizarovc32579e2018-09-09 19:21:43 +03001999> All functions that create coroutines are defined as extensions on [CoroutineScope],
2000so that we can rely on [structured concurrency](#structured-concurrency) to make
2001sure that we don't have lingering global coroutines in our application.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002002
2003### Prime numbers with pipeline
2004
Cedric Beustfa0b28f2017-02-07 07:07:25 -08002005Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovc32579e2018-09-09 19:21:43 +03002006of coroutines. We start with an infinite sequence of numbers.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002007
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002008<!--- INCLUDE
2009import kotlin.coroutines.experimental.*
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002010-->
2011
2012```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002013fun CoroutineScope.numbersFrom(start: Int) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002014 var x = start
2015 while (true) send(x++) // infinite stream of integers from start
2016}
2017```
2018
2019The following pipeline stage filters an incoming stream of numbers, removing all the numbers
2020that are divisible by the given prime number:
2021
2022```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002023fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002024 for (x in numbers) if (x % prime != 0) send(x)
2025}
2026```
2027
2028Now 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 +03002029and launching new pipeline stage for each prime number found:
2030
2031```
Roman Elizarova5e653f2017-02-13 13:49:55 +03002032numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03002033```
2034
2035The following example prints the first ten prime numbers,
Roman Elizarovc32579e2018-09-09 19:21:43 +03002036running the whole pipeline in the context of the main thread. Since all the coroutines are launched in
2037the scope of the main [runBlocking] coroutine
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002038we don't have to keep an explicit list of all the coroutines we have started.
Roman Elizarov3e387b82017-12-04 13:49:11 +03002039We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
Roman Elizarovc32579e2018-09-09 19:21:43 +03002040extension function to cancel all the children coroutines after we have printed
2041the first ten prime numbers.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002042
2043```kotlin
2044fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002045 var cur = numbersFrom(2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002046 for (i in 1..10) {
2047 val prime = cur.receive()
2048 println(prime)
Roman Elizarovc32579e2018-09-09 19:21:43 +03002049 cur = filter(cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002050 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002051 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +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-05.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002056
2057The output of this code is:
2058
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002059```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030020602
20613
20625
20637
206411
206513
206617
206719
206823
206929
2070```
2071
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002072<!--- TEST -->
2073
Roman Elizarov66f018c2017-09-29 21:39:03 +03002074Note, that you can build the same pipeline using
2075[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
2076coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03002077Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarovc32579e2018-09-09 19:21:43 +03002078`ReceiveChannel` with `Iterator`, and get rid of the coroutine scope. You will not need `runBlocking` either.
Roman Elizarov62500ba2017-02-09 18:55:40 +03002079However, the benefit of a pipeline that uses channels as shown above is that it can actually use
Roman Elizarovdc29b072018-09-11 18:42:03 +03002080multiple CPU cores if you run it in [Dispatchers.Default] context.
Roman Elizarov62500ba2017-02-09 18:55:40 +03002081
Roman Elizarova5e653f2017-02-13 13:49:55 +03002082Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03002083other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
SashaKhyzhuncb2998b2018-07-31 11:51:35 +03002084built using `buildSequence`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03002085`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03002086
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002087### Fan-out
2088
2089Multiple coroutines may receive from the same channel, distributing work between themselves.
2090Let us start with a producer coroutine that is periodically producing integers
2091(ten numbers per second):
2092
2093```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002094fun CoroutineScope.produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002095 var x = 1 // start from 1
2096 while (true) {
2097 send(x++) // produce next
2098 delay(100) // wait 0.1s
2099 }
2100}
2101```
2102
2103Then we can have several processor coroutines. In this example, they just print their id and
2104received number:
2105
2106```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002107fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
bill58c61c72018-06-21 17:24:08 -05002108 for (msg in channel) {
2109 println("Processor #$id received $msg")
Roman Elizarovec9384c2017-03-02 22:09:08 +03002110 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002111}
2112```
2113
Roman Elizarov35d2c342017-07-20 14:54:39 +03002114Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002115
2116```kotlin
2117fun main(args: Array<String>) = runBlocking<Unit> {
2118 val producer = produceNumbers()
2119 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03002120 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002121 producer.cancel() // cancel producer coroutine and thus kill them all
2122}
2123```
2124
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002125> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-06.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002126
2127The output will be similar to the the following one, albeit the processor ids that receive
2128each specific integer may be different:
2129
2130```
2131Processor #2 received 1
2132Processor #4 received 2
2133Processor #0 received 3
2134Processor #1 received 4
2135Processor #3 received 5
2136Processor #2 received 6
2137Processor #4 received 7
2138Processor #0 received 8
2139Processor #1 received 9
2140Processor #3 received 10
2141```
2142
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002143<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
2144
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002145Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
2146over the channel that processor coroutines are doing.
2147
Roman Elizarov1ce6c0b2018-06-28 10:37:20 +03002148Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
2149Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
2150coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
Roman Elizarovc32579e2018-09-09 19:21:43 +03002151always consumes (cancels) the underlying channel on its normal or abnormal completion.
Roman Elizarov1ce6c0b2018-06-28 10:37:20 +03002152
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002153### Fan-in
2154
2155Multiple coroutines may send to the same channel.
2156For example, let us have a channel of strings, and a suspending function that
2157repeatedly sends a specified string to this channel with a specified delay:
2158
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002159<!--- INCLUDE
2160import kotlin.coroutines.experimental.*
2161-->
2162
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002163```kotlin
2164suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
2165 while (true) {
2166 delay(time)
2167 channel.send(s)
2168 }
2169}
2170```
2171
Cedric Beustfa0b28f2017-02-07 07:07:25 -08002172Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002173(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 +03002174
2175```kotlin
2176fun main(args: Array<String>) = runBlocking<Unit> {
2177 val channel = Channel<String>()
Roman Elizarovc32579e2018-09-09 19:21:43 +03002178 launch { sendString(channel, "foo", 200L) }
2179 launch { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002180 repeat(6) { // receive first six
2181 println(channel.receive())
2182 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002183 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002184}
2185```
2186
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002187> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-07.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002188
2189The output is:
2190
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002191```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002192foo
2193foo
2194BAR!
2195foo
2196foo
2197BAR!
2198```
2199
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002200<!--- TEST -->
2201
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002202### Buffered channels
2203
2204The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
2205meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
2206if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03002207
Roman Elizarov88396732017-09-27 21:30:47 +03002208Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002209specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
2210similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
2211
2212Take a look at the behavior of the following code:
2213
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002214<!--- INCLUDE
2215import kotlin.coroutines.experimental.*
2216-->
2217
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002218```kotlin
2219fun main(args: Array<String>) = runBlocking<Unit> {
2220 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarovc32579e2018-09-09 19:21:43 +03002221 val sender = launch { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002222 repeat(10) {
2223 println("Sending $it") // print before sending each element
2224 channel.send(it) // will suspend when buffer is full
2225 }
2226 }
2227 // don't receive anything... just wait....
2228 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002229 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002230}
2231```
2232
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002233> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002234
2235It prints "sending" _five_ times using a buffered channel with capacity of _four_:
2236
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002237```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002238Sending 0
2239Sending 1
2240Sending 2
2241Sending 3
2242Sending 4
2243```
2244
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002245<!--- TEST -->
2246
Roman Elizarovb7721cf2017-02-03 19:23:08 +03002247The 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 +03002248
Roman Elizarovc32579e2018-09-09 19:21:43 +03002249### Channels are fair
2250
2251Send and receive operations to channels are _fair_ with respect to the order of their invocation from
2252multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
2253gets the element. In the following example two coroutines "ping" and "pong" are
2254receiving the "ball" object from the shared "table" channel.
2255
2256<!--- INCLUDE
2257import kotlin.coroutines.experimental.*
2258-->
2259
2260```kotlin
2261data class Ball(var hits: Int)
2262
2263fun main(args: Array<String>) = runBlocking<Unit> {
2264 val table = Channel<Ball>() // a shared table
2265 launch { player("ping", table) }
2266 launch { player("pong", table) }
2267 table.send(Ball(0)) // serve the ball
2268 delay(1000) // delay 1 second
2269 coroutineContext.cancelChildren() // game over, cancel them
2270}
2271
2272suspend fun player(name: String, table: Channel<Ball>) {
2273 for (ball in table) { // receive the ball in a loop
2274 ball.hits++
2275 println("$name $ball")
2276 delay(300) // wait a bit
2277 table.send(ball) // send the ball back
2278 }
2279}
2280```
2281
2282> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-09.kt)
2283
2284The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
2285coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
2286received by the "pong" coroutine, because it was already waiting for it:
2287
2288```text
2289ping Ball(hits=1)
2290pong Ball(hits=2)
2291ping Ball(hits=3)
2292pong Ball(hits=4)
2293```
2294
2295<!--- TEST -->
2296
2297Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
2298that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
2299
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002300### Ticker channels
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002301
Roman Elizarovb5328a72018-06-06 18:31:21 +03002302Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
2303Though 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 +03002304pipelines and operators that do windowing and other time-dependent processing.
Roman Elizarovb5328a72018-06-06 18:31:21 +03002305Ticker channel can be used in [select] to perform "on tick" action.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002306
Roman Elizarovb5328a72018-06-06 18:31:21 +03002307To create such channel use a factory method [ticker].
2308To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002309
2310Now let's see how it works in practice:
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002311
2312```kotlin
2313fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovb5328a72018-06-06 18:31:21 +03002314 val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002315 var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
paolop1d6e4932018-07-02 08:46:34 +00002316 println("Initial element is available immediately: $nextElement") // initial delay hasn't passed yet
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002317
paolop1d6e4932018-07-02 08:46:34 +00002318 nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements has 100ms delay
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002319 println("Next element is not ready in 50 ms: $nextElement")
2320
Roman Elizarovb5328a72018-06-06 18:31:21 +03002321 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002322 println("Next element is ready in 100 ms: $nextElement")
2323
2324 // Emulate large consumption delays
Roman Elizarovb5328a72018-06-06 18:31:21 +03002325 println("Consumer pauses for 150ms")
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002326 delay(150)
2327 // Next element is available immediately
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002328 nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002329 println("Next element is available immediately after large consumer delay: $nextElement")
2330 // Note that the pause between `receive` calls is taken into account and next element arrives faster
Roman Elizarovb5328a72018-06-06 18:31:21 +03002331 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002332 println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
2333
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002334 tickerChannel.cancel() // indicate that no more elements are needed
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002335}
2336```
2337
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002338> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-10.kt)
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002339
2340It prints following lines:
2341
2342```text
2343Initial element is available immediately: kotlin.Unit
2344Next element is not ready in 50 ms: null
2345Next element is ready in 100 ms: kotlin.Unit
Roman Elizarovb5328a72018-06-06 18:31:21 +03002346Consumer pauses for 150ms
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002347Next element is available immediately after large consumer delay: kotlin.Unit
2348Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
2349```
2350
2351<!--- TEST -->
2352
Roman Elizarovb5328a72018-06-06 18:31:21 +03002353Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
2354delay if a pause occurs, trying to maintain a fixed rate of produced elements.
2355
Roman Elizarov0c090ed2018-06-29 19:51:07 +03002356Optionally, a `mode` parameter equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
Roman Elizarovb5328a72018-06-06 18:31:21 +03002357delay between elements.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002358
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002359## Shared mutable state and concurrency
2360
Roman Elizarovdc29b072018-09-11 18:42:03 +03002361Coroutines can be executed concurrently using a multi-threaded dispatcher like the [Dispatchers.Default]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002362all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
2363Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
2364but others are unique.
2365
2366### The problem
2367
Roman Elizarovc32579e2018-09-09 19:21:43 +03002368Let us launch a hundred coroutines all doing the same action thousand times.
Roman Elizarov1e459602017-02-27 11:05:17 +03002369We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002370
Roman Elizarov1e459602017-02-27 11:05:17 +03002371<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002372import java.util.concurrent.atomic.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002373-->
2374
Roman Elizarov1e459602017-02-27 11:05:17 +03002375<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002376import kotlinx.coroutines.experimental.sync.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002377-->
2378
Roman Elizarov1e459602017-02-27 11:05:17 +03002379<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002380import kotlinx.coroutines.experimental.channels.*
2381-->
2382
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002383<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
2384import kotlin.system.*
2385import kotlin.coroutines.experimental.*
2386-->
2387
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002388```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002389suspend fun CoroutineScope.massiveRun(action: suspend () -> Unit) {
2390 val n = 100 // number of coroutines to launch
Roman Elizarov1e459602017-02-27 11:05:17 +03002391 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002392 val time = measureTimeMillis {
2393 val jobs = List(n) {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002394 launch {
Roman Elizarov1e459602017-02-27 11:05:17 +03002395 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002396 }
2397 }
2398 jobs.forEach { it.join() }
2399 }
Roman Elizarov1e459602017-02-27 11:05:17 +03002400 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002401}
2402```
2403
Roman Elizarov43e90112017-05-10 11:25:20 +03002404<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002405
Roman Elizarov1e459602017-02-27 11:05:17 +03002406We start with a very simple action that increments a shared mutable variable using
Roman Elizarovdc29b072018-09-11 18:42:03 +03002407multi-threaded [Dispatchers.Default] that is used in [GlobalScope].
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002408
2409```kotlin
2410var counter = 0
2411
2412fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002413 GlobalScope.massiveRun {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002414 counter++
2415 }
2416 println("Counter = $counter")
2417}
2418```
2419
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002420> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002421
Roman Elizarov1e459602017-02-27 11:05:17 +03002422<!--- TEST LINES_START
Roman Elizarovc32579e2018-09-09 19:21:43 +03002423Completed 100000 actions in
Roman Elizarov1e459602017-02-27 11:05:17 +03002424Counter =
2425-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002426
Roman Elizarovc32579e2018-09-09 19:21:43 +03002427What does it print at the end? It is highly unlikely to ever print "Counter = 100000", because a thousand coroutines
Roman Elizarov1e459602017-02-27 11:05:17 +03002428increment the `counter` concurrently from multiple threads without any synchronization.
2429
Roman Elizarovc32579e2018-09-09 19:21:43 +03002430> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 100000, because
2431the thread pool is running in only one thread in this case. To reproduce the problem you'll need to make the
Roman Elizarov43e90112017-05-10 11:25:20 +03002432following change:
2433
2434```kotlin
2435val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
2436var counter = 0
2437
2438fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovdc29b072018-09-11 18:42:03 +03002439 CoroutineScope(mtContext).massiveRun { // use it instead of Dispatchers.Default in this sample and below
Roman Elizarov43e90112017-05-10 11:25:20 +03002440 counter++
2441 }
2442 println("Counter = $counter")
2443}
2444```
2445
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002446> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt)
Roman Elizarov43e90112017-05-10 11:25:20 +03002447
2448<!--- TEST LINES_START
Roman Elizarovc32579e2018-09-09 19:21:43 +03002449Completed 100000 actions in
Roman Elizarov43e90112017-05-10 11:25:20 +03002450Counter =
2451-->
2452
Roman Elizarov1e459602017-02-27 11:05:17 +03002453### Volatiles are of no help
2454
2455There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
2456
2457```kotlin
2458@Volatile // in Kotlin `volatile` is an annotation
2459var counter = 0
2460
2461fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002462 GlobalScope.massiveRun {
Roman Elizarov1e459602017-02-27 11:05:17 +03002463 counter++
2464 }
2465 println("Counter = $counter")
2466}
2467```
2468
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002469> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03002470
2471<!--- TEST LINES_START
Roman Elizarovc32579e2018-09-09 19:21:43 +03002472Completed 100000 actions in
Roman Elizarov1e459602017-02-27 11:05:17 +03002473Counter =
2474-->
2475
Roman Elizarovc32579e2018-09-09 19:21:43 +03002476This code works slower, but we still don't get "Counter = 100000" at the end, because volatile variables guarantee
Roman Elizarov1e459602017-02-27 11:05:17 +03002477linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
2478do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002479
2480### Thread-safe data structures
2481
2482The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
2483linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
2484operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03002485In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002486
2487```kotlin
2488var counter = AtomicInteger()
2489
2490fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002491 GlobalScope.massiveRun {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002492 counter.incrementAndGet()
2493 }
2494 println("Counter = ${counter.get()}")
2495}
2496```
2497
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002498> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002499
Roman Elizarov1e459602017-02-27 11:05:17 +03002500<!--- TEST ARBITRARY_TIME
Roman Elizarovc32579e2018-09-09 19:21:43 +03002501Completed 100000 actions in xxx ms
2502Counter = 100000
Roman Elizarov1e459602017-02-27 11:05:17 +03002503-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002504
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002505This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
2506standard data structures and basic operations on them. However, it does not easily scale to complex
2507state or to complex operations that do not have ready-to-use thread-safe implementations.
2508
Roman Elizarov1e459602017-02-27 11:05:17 +03002509### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002510
Roman Elizarov1e459602017-02-27 11:05:17 +03002511_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 +03002512state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
2513the single event-dispatch/application thread. It is easy to apply with coroutines by using a
Roman Elizarovc32579e2018-09-09 19:21:43 +03002514single-threaded context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002515
2516```kotlin
2517val counterContext = newSingleThreadContext("CounterContext")
2518var counter = 0
2519
2520fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002521 GlobalScope.massiveRun { // run each coroutine with DefaultDispathcer
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002522 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002523 counter++
2524 }
2525 }
2526 println("Counter = $counter")
2527}
2528```
2529
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002530> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002531
Roman Elizarov1e459602017-02-27 11:05:17 +03002532<!--- TEST ARBITRARY_TIME
Roman Elizarovc32579e2018-09-09 19:21:43 +03002533Completed 100000 actions in xxx ms
2534Counter = 100000
Roman Elizarov1e459602017-02-27 11:05:17 +03002535-->
2536
2537This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovdc29b072018-09-11 18:42:03 +03002538from multi-threaded [Dispatchers.Default] context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03002539
2540### Thread confinement coarse-grained
2541
2542In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
2543are confined to the single thread. The following example does it like that, running each coroutine in
Roman Elizarovc32579e2018-09-09 19:21:43 +03002544the single-threaded context to start with.
2545Here we use [CoroutineScope()] function to convert coroutine context reference to [CoroutineScope]:
Roman Elizarov1e459602017-02-27 11:05:17 +03002546
2547```kotlin
2548val counterContext = newSingleThreadContext("CounterContext")
2549var counter = 0
2550
2551fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002552 CoroutineScope(counterContext).massiveRun { // run each coroutine in the single-threaded context
Roman Elizarov1e459602017-02-27 11:05:17 +03002553 counter++
2554 }
2555 println("Counter = $counter")
2556}
2557```
2558
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002559> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-05.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03002560
2561<!--- TEST ARBITRARY_TIME
Roman Elizarovc32579e2018-09-09 19:21:43 +03002562Completed 100000 actions in xxx ms
2563Counter = 100000
Roman Elizarov1e459602017-02-27 11:05:17 +03002564-->
2565
2566This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002567
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002568### Mutual exclusion
2569
2570Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
2571that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
2572Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
paolop1d6e4932018-07-02 08:46:34 +00002573delimit 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 +03002574
Roman Elizarov88396732017-09-27 21:30:47 +03002575There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002576`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
2577
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002578```kotlin
2579val mutex = Mutex()
2580var counter = 0
2581
2582fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002583 GlobalScope.massiveRun {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002584 mutex.withLock {
2585 counter++
2586 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002587 }
2588 println("Counter = $counter")
2589}
2590```
2591
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002592> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002593
Roman Elizarov1e459602017-02-27 11:05:17 +03002594<!--- TEST ARBITRARY_TIME
Roman Elizarovc32579e2018-09-09 19:21:43 +03002595Completed 100000 actions in xxx ms
2596Counter = 100000
Roman Elizarov1e459602017-02-27 11:05:17 +03002597-->
2598
2599The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
2600where you absolutely must modify some shared state periodically, but there is no natural thread that this state
2601is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002602
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002603### Actors
2604
paolop1d6e4932018-07-02 08:46:34 +00002605An [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 +03002606and a channel to communicate with other coroutines. A simple actor can be written as a function,
2607but an actor with a complex state is better suited for a class.
2608
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002609There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
2610scope to receive messages from and combines the send channel into the resulting job object, so that a
2611single reference to the actor can be carried around as its handle.
2612
Roman Elizarov256812a2017-07-22 01:00:30 +03002613The first step of using an actor is to define a class of messages that an actor is going to process.
2614Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
2615We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
2616to get its value. The later needs to send a response. A [CompletableDeferred] communication
2617primitive, that represents a single value that will be known (communicated) in the future,
2618is used here for that purpose.
2619
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002620```kotlin
2621// Message types for counterActor
2622sealed class CounterMsg
2623object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03002624class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
2625```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002626
Roman Elizarov256812a2017-07-22 01:00:30 +03002627Then we define a function that launches an actor using an [actor] coroutine builder:
2628
2629```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002630// This function launches a new counter actor
Roman Elizarovc32579e2018-09-09 19:21:43 +03002631fun CoroutineScope.counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002632 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002633 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002634 when (msg) {
2635 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03002636 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002637 }
2638 }
2639}
Roman Elizarov256812a2017-07-22 01:00:30 +03002640```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002641
Roman Elizarov256812a2017-07-22 01:00:30 +03002642The main code is straightforward:
2643
2644```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002645fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002646 val counter = counterActor() // create the actor
Roman Elizarovc32579e2018-09-09 19:21:43 +03002647 GlobalScope.massiveRun {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002648 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002649 }
Roman Elizarov256812a2017-07-22 01:00:30 +03002650 // send a message to get a counter value from an actor
2651 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002652 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03002653 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002654 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002655}
2656```
2657
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002658> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002659
Roman Elizarov1e459602017-02-27 11:05:17 +03002660<!--- TEST ARBITRARY_TIME
Roman Elizarovc32579e2018-09-09 19:21:43 +03002661Completed 100000 actions in xxx ms
2662Counter = 100000
Roman Elizarov1e459602017-02-27 11:05:17 +03002663-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002664
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002665It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002666a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
paolop1d6e4932018-07-02 08:46:34 +00002667works 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 +03002668
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002669Actor is more efficient than locking under load, because in this case it always has work to do and it does not
2670have to switch to a different context at all.
2671
2672> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
2673 with the channel that it receives messages from, while a producer is associated with the channel that it
2674 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03002675
Roman Elizarovc32579e2018-09-09 19:21:43 +03002676## Select expression (experimental)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002677
Roman Elizarova84730b2017-02-22 11:58:50 +03002678Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002679the first one that becomes available.
2680
Roman Elizarovc32579e2018-09-09 19:21:43 +03002681> Select expressions are an experimental feature of `kotlinx.coroutines`. Their API is expected to
2682evolve in the upcoming updates of the `kotlinx.coroutines` library with potentially
2683breaking changes.
2684
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002685<!--- INCLUDE .*/example-select-([0-9]+).kt
2686import kotlinx.coroutines.experimental.channels.*
2687import kotlinx.coroutines.experimental.selects.*
2688-->
2689
2690### Selecting from channels
2691
Roman Elizarov57857202017-03-02 23:17:25 +03002692Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2693
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002694<!--- INCLUDE
2695import kotlinx.coroutines.experimental.*
2696import kotlin.coroutines.experimental.*
Roman Elizarov57857202017-03-02 23:17:25 +03002697-->
2698
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002699```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002700fun CoroutineScope.fizz() = produce<String> {
Roman Elizarov57857202017-03-02 23:17:25 +03002701 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002702 delay(300)
2703 send("Fizz")
2704 }
2705}
2706```
2707
Roman Elizarov57857202017-03-02 23:17:25 +03002708And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002709
2710```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002711fun CoroutineScope.buzz() = produce<String> {
Roman Elizarov57857202017-03-02 23:17:25 +03002712 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002713 delay(500)
2714 send("Buzz!")
2715 }
2716}
2717```
2718
2719Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2720other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002721[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002722
2723```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002724suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002725 select<Unit> { // <Unit> means that this select expression does not produce any result
2726 fizz.onReceive { value -> // this is the first select clause
2727 println("fizz -> '$value'")
2728 }
2729 buzz.onReceive { value -> // this is the second select clause
2730 println("buzz -> '$value'")
2731 }
2732 }
2733}
2734```
2735
Roman Elizarov57857202017-03-02 23:17:25 +03002736Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002737
2738```kotlin
2739fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002740 val fizz = fizz()
2741 val buzz = buzz()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002742 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002743 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002744 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002745 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002746}
2747```
2748
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002749> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-01.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002750
2751The result of this code is:
2752
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002753```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002754fizz -> 'Fizz'
2755buzz -> 'Buzz!'
2756fizz -> 'Fizz'
2757fizz -> 'Fizz'
2758buzz -> 'Buzz!'
2759fizz -> 'Fizz'
2760buzz -> 'Buzz!'
2761```
2762
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002763<!--- TEST -->
2764
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002765### Selecting on close
2766
paolop1d6e4932018-07-02 08:46:34 +00002767The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
2768`select` to throw an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002769specific 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 +03002770the result of its selected clause:
2771
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002772<!--- INCLUDE
2773import kotlin.coroutines.experimental.*
2774-->
2775
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002776```kotlin
2777suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2778 select<String> {
2779 a.onReceiveOrNull { value ->
2780 if (value == null)
2781 "Channel 'a' is closed"
2782 else
2783 "a -> '$value'"
2784 }
2785 b.onReceiveOrNull { value ->
2786 if (value == null)
2787 "Channel 'b' is closed"
2788 else
2789 "b -> '$value'"
2790 }
2791 }
2792```
2793
Roman Elizarova84730b2017-02-22 11:58:50 +03002794Let's use it with channel `a` that produces "Hello" string four times and
2795channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002796
2797```kotlin
2798fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc32579e2018-09-09 19:21:43 +03002799 val a = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002800 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002801 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03002802 val b = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002803 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002804 }
2805 repeat(8) { // print first eight results
2806 println(selectAorB(a, b))
2807 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002808 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002809}
2810```
2811
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002812> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-02.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002813
Roman Elizarova84730b2017-02-22 11:58:50 +03002814The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002815
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002816```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002817a -> 'Hello 0'
2818a -> 'Hello 1'
2819b -> 'World 0'
2820a -> 'Hello 2'
2821a -> 'Hello 3'
2822b -> 'World 1'
2823Channel 'a' is closed
2824Channel 'a' is closed
2825```
2826
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002827<!--- TEST -->
2828
Roman Elizarova84730b2017-02-22 11:58:50 +03002829There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002830
2831First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2832the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002833being 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 +03002834time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2835
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002836The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002837channel is already closed.
2838
2839### Selecting to send
2840
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002841Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002842with a biased nature of selection.
2843
Roman Elizarova84730b2017-02-22 11:58:50 +03002844Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002845the consumers on its primary channel cannot keep up with it:
2846
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002847<!--- INCLUDE
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002848import kotlin.coroutines.experimental.*
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002849-->
2850
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002851```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002852fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002853 for (num in 1..10) { // produce 10 numbers from 1 to 10
2854 delay(100) // every 100 ms
2855 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002856 onSend(num) {} // Send to the primary channel
2857 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002858 }
2859 }
2860}
2861```
2862
2863Consumer is going to be quite slow, taking 250 ms to process each number:
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002864
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002865```kotlin
2866fun main(args: Array<String>) = runBlocking<Unit> {
2867 val side = Channel<Int>() // allocate side channel
Roman Elizarovc32579e2018-09-09 19:21:43 +03002868 launch { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002869 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002870 }
Roman Elizarovc32579e2018-09-09 19:21:43 +03002871 produceNumbers(side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002872 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002873 delay(250) // let us digest the consumed number properly, do not hurry
2874 }
2875 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002876 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002877}
2878```
2879
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002880> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-03.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002881
2882So let us see what happens:
2883
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002884```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002885Consuming 1
2886Side channel has 2
2887Side channel has 3
2888Consuming 4
2889Side channel has 5
2890Side channel has 6
2891Consuming 7
2892Side channel has 8
2893Side channel has 9
2894Consuming 10
2895Done consuming
2896```
2897
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002898<!--- TEST -->
2899
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002900### Selecting deferred values
2901
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002902Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002903Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002904a random delay:
2905
2906<!--- INCLUDE .*/example-select-04.kt
2907import java.util.*
2908-->
2909
2910```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002911fun CoroutineScope.asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002912 delay(time.toLong())
2913 "Waited for $time ms"
2914}
2915```
2916
Roman Elizarova84730b2017-02-22 11:58:50 +03002917Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002918
2919```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002920fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002921 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002922 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002923}
2924```
2925
Roman Elizarova84730b2017-02-22 11:58:50 +03002926Now 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 +03002927that 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 +03002928so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2929of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002930
2931```kotlin
2932fun main(args: Array<String>) = runBlocking<Unit> {
2933 val list = asyncStringsList()
2934 val result = select<String> {
2935 list.withIndex().forEach { (index, deferred) ->
2936 deferred.onAwait { answer ->
2937 "Deferred $index produced answer '$answer'"
2938 }
2939 }
2940 }
2941 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002942 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002943 println("$countActive coroutines are still active")
2944}
2945```
2946
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002947> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-04.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002948
2949The output is:
2950
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002951```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002952Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300295311 coroutines are still active
2954```
2955
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002956<!--- TEST -->
2957
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002958### Switch over a channel of deferred values
2959
Roman Elizarova84730b2017-02-22 11:58:50 +03002960Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2961deferred 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 +03002962[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002963
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002964<!--- INCLUDE
2965import kotlin.coroutines.experimental.*
2966-->
2967
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002968```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002969fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002970 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002971 while (isActive) { // loop while not cancelled/closed
2972 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2973 input.onReceiveOrNull { update ->
2974 update // replaces next value to wait
2975 }
2976 current.onAwait { value ->
2977 send(value) // send value that current deferred has produced
2978 input.receiveOrNull() // and use the next deferred from the input channel
2979 }
2980 }
2981 if (next == null) {
2982 println("Channel was closed")
2983 break // out of loop
2984 } else {
2985 current = next
2986 }
2987 }
2988}
2989```
2990
2991To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2992
2993```kotlin
Roman Elizarovc32579e2018-09-09 19:21:43 +03002994fun CoroutineScope.asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002995 delay(time)
2996 str
2997}
2998```
2999
3000The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
3001data to it:
3002
3003```kotlin
3004fun main(args: Array<String>) = runBlocking<Unit> {
3005 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarovc32579e2018-09-09 19:21:43 +03003006 launch { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003007 for (s in switchMapDeferreds(chan))
3008 println(s) // print each received string
3009 }
3010 chan.send(asyncString("BEGIN", 100))
3011 delay(200) // enough time for "BEGIN" to be produced
3012 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03003013 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003014 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03003015 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003016 chan.send(asyncString("END", 500))
3017 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03003018 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003019 delay(500) // and wait some time to let it finish
3020}
3021```
3022
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03003023> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-05.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003024
3025The result of this code:
3026
Roman Elizarov731f0ad2017-02-22 20:48:45 +03003027```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003028BEGIN
3029Replace
3030END
3031Channel was closed
3032```
3033
Roman Elizarov731f0ad2017-02-22 20:48:45 +03003034<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003035
Roman Elizarov8db17332017-03-09 12:40:45 +03003036## Further reading
3037
3038* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03003039* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03003040* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
3041* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
3042
Roman Elizarove7e2ad12017-05-17 14:47:31 +03003043<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03003044<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003045[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
Roman Elizarovc32579e2018-09-09 19:21:43 +03003046[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
3047[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-global-scope/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003048[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
3049[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03003050[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarovc32579e2018-09-09 19:21:43 +03003051[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
3052[coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/coroutine-scope.html
3053[currentScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/current-scope.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03003054[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03003055[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03003056[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003057[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovc32579e2018-09-09 19:21:43 +03003058[isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/is-active.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03003059[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003060[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
3061[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03003062[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 +03003063[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
3064[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03003065[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 +03003066[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
3067[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03003068[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovdc29b072018-09-11 18:42:03 +03003069[Dispatchers.Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-unconfined.html
3070[Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-default.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08003071[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
3072[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 +03003073[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovc32579e2018-09-09 19:21:43 +03003074[CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03003075[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03003076[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Vsevolod Tolstopyatove3425972018-08-22 19:41:57 +03003077[asContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/java.lang.-thread-local/as-context-element.html
3078[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 +03003079[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 +03003080[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 Elizarovc32579e2018-09-09 19:21:43 +03003081[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope.html
Roman Elizarove82dee72017-08-18 16:49:09 +03003082[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03003083[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 +03003084<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03003085[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03003086[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
3087[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 +03003088[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03003089<!--- INDEX kotlinx.coroutines.experimental.channels -->
Vsevolod Tolstopyatov590696d2018-08-08 15:22:33 +03003090[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
3091[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
3092[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 +03003093[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03003094[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 +03003095[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 +03003096[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03003097[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03003098[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/ticker.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03003099[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 +03003100[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 +03003101[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 +03003102[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
3103[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 +03003104<!--- INDEX kotlinx.coroutines.experimental.selects -->
3105[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03003106<!--- END -->