blob: 591494fd418f24ffd628349e7311b4979c31f146 [file] [log] [blame] [view]
Roman Elizarov43e90112017-05-10 11:25:20 +03001<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
Roman Elizarova5e653f2017-02-13 13:49:55 +03002/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03003 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarova5e653f2017-02-13 13:49:55 +03004 */
Roman Elizarovf16fd272017-02-07 11:26:00 +03005
Roman Elizarova5e653f2017-02-13 13:49:55 +03006// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarova9687a32018-06-29 17:28:38 +03007package kotlinx.coroutines.experimental.guide.$$1$$2
Roman Elizarovf16fd272017-02-07 11:26:00 +03008
Roman Elizarova5e653f2017-02-13 13:49:55 +03009import kotlinx.coroutines.experimental.*
Roman Elizarovf16fd272017-02-07 11:26:00 +030010-->
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +030011<!--- KNIT core/kotlinx-coroutines-core/test/guide/.*\.kt -->
12<!--- TEST_OUT core/kotlinx-coroutines-core/test/guide/test/GuideTest.kt
Roman Elizarov731f0ad2017-02-22 20:48:45 +030013// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarova9687a32018-06-29 17:28:38 +030014package kotlinx.coroutines.experimental.guide.test
Roman Elizarov731f0ad2017-02-22 20:48:45 +030015
16import org.junit.Test
17
18class GuideTest {
19-->
Roman Elizarovf16fd272017-02-07 11:26:00 +030020
Roman Elizarov7deefb82017-01-31 10:33:17 +030021# Guide to kotlinx.coroutines by example
22
Roman Elizarova4d45d22017-11-20 16:47:09 +030023This is a guide on core features of `kotlinx.coroutines` with a series of examples.
Roman Elizarov7deefb82017-01-31 10:33:17 +030024
Roman Elizarov2a638922017-03-04 10:22:43 +030025## Introduction and setup
26
27Kotlin, as a language, provides only minimal low-level APIs in its standard library to enable various other
28libraries to utilize coroutines. Unlike many other languages with similar capabilities, `async` and `await`
29are not keywords in Kotlin and are not even part of its standard library.
30
Robert Hencke497d3432017-04-11 00:14:29 -040031`kotlinx.coroutines` is one such rich library. It contains a number of high-level
Roman Elizarova4d45d22017-11-20 16:47:09 +030032coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
Roman Elizarov2a638922017-03-04 10:22:43 +030033You need to add a dependency on `kotlinx-coroutines-core` module as explained
34[here](README.md#using-in-your-projects) to use primitives from this guide in your projects.
35
Roman Elizarov1293ccd2017-02-01 18:49:54 +030036## Table of contents
37
Roman Elizarovfa7723e2017-02-06 11:17:51 +030038<!--- TOC -->
39
Roman Elizarov1293ccd2017-02-01 18:49:54 +030040* [Coroutine basics](#coroutine-basics)
41 * [Your first coroutine](#your-first-coroutine)
42 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
43 * [Waiting for a job](#waiting-for-a-job)
44 * [Extract function refactoring](#extract-function-refactoring)
45 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
46 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
47* [Cancellation and timeouts](#cancellation-and-timeouts)
48 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
49 * [Cancellation is cooperative](#cancellation-is-cooperative)
50 * [Making computation code cancellable](#making-computation-code-cancellable)
51 * [Closing resources with finally](#closing-resources-with-finally)
52 * [Run non-cancellable block](#run-non-cancellable-block)
53 * [Timeout](#timeout)
54* [Composing suspending functions](#composing-suspending-functions)
55 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030056 * [Concurrent using async](#concurrent-using-async)
57 * [Lazily started async](#lazily-started-async)
58 * [Async-style functions](#async-style-functions)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030059* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030060 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030061 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
62 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
63 * [Jumping between threads](#jumping-between-threads)
64 * [Job in the context](#job-in-the-context)
65 * [Children of a coroutine](#children-of-a-coroutine)
66 * [Combining contexts](#combining-contexts)
Roman Elizarov8b38fa22017-09-27 17:44:31 +030067 * [Parental responsibilities](#parental-responsibilities)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030068 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030069 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030070* [Channels](#channels)
71 * [Channel basics](#channel-basics)
72 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
73 * [Building channel producers](#building-channel-producers)
74 * [Pipelines](#pipelines)
75 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
76 * [Fan-out](#fan-out)
77 * [Fan-in](#fan-in)
78 * [Buffered channels](#buffered-channels)
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +030079 * [Ticker channels](#ticker-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030080 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030081* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
82 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030083 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030084 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030085 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
86 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030087 * [Mutual exclusion](#mutual-exclusion)
88 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +030089* [Select expression](#select-expression)
90 * [Selecting from channels](#selecting-from-channels)
91 * [Selecting on close](#selecting-on-close)
92 * [Selecting to send](#selecting-to-send)
93 * [Selecting deferred values](#selecting-deferred-values)
94 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +030095* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030096
Roman Elizarova5e653f2017-02-13 13:49:55 +030097<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +030098
99## Coroutine basics
100
101This section covers basic coroutine concepts.
102
103### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300104
105Run the following code:
106
107```kotlin
108fun main(args: Array<String>) {
Roman Elizarova4d45d22017-11-20 16:47:09 +0300109 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300110 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
111 println("World!") // print after delay
112 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300113 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300114 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
115}
116```
117
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300118> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300119
120Run this code:
121
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300122```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300123Hello,
124World!
125```
126
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300127<!--- TEST -->
128
Roman Elizarov419a6c82017-02-09 18:36:22 +0300129Essentially, coroutines are light-weight threads.
130They are launched with [launch] _coroutine builder_.
131You can achieve the same result replacing
Roman Elizarov66f018c2017-09-29 21:39:03 +0300132`launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300133
Roman Elizarov66f018c2017-09-29 21:39:03 +0300134If you start by replacing `launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300135
136```
137Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
138```
139
Roman Elizarov419a6c82017-02-09 18:36:22 +0300140That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300141coroutine and it can be only used from a coroutine.
142
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300143### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300144
Roman Elizarova4d45d22017-11-20 16:47:09 +0300145The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
146It is easy to get lost which one is blocking and which one is not.
147Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300148
149```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300150fun main(args: Array<String>) {
151 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300152 delay(1000L)
153 println("World!")
154 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300155 println("Hello,") // main thread continues here immediately
156 runBlocking { // but this expression blocks the main thread
157 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
158 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300159}
160```
161
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300162> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300163
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300164<!--- TEST
165Hello,
166World!
167-->
168
Roman Elizarov419a6c82017-02-09 18:36:22 +0300169The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100170The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300171
Roman Elizarova4d45d22017-11-20 16:47:09 +0300172This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
173the execution of the main function:
174
175```kotlin
176fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
177 launch { // launch new coroutine in background and continue
178 delay(1000L)
179 println("World!")
180 }
181 println("Hello,") // main coroutine continues here immediately
182 delay(2000L) // delaying for 2 seconds to keep JVM alive
183}
184```
185
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300186> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt)
Roman Elizarova4d45d22017-11-20 16:47:09 +0300187
188<!--- TEST
189Hello,
190World!
191-->
192
193Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
194We explicitly specify its `Unit` return type, because a well-formed `main` function in Kotlin has to return `Unit`.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300195
196This is also a way to write unit-tests for suspending functions:
197
198```kotlin
199class MyTest {
200 @Test
201 fun testMySuspendingFunction() = runBlocking<Unit> {
202 // here we can use suspending functions using any assertion style that we like
203 }
204}
205```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300206
207<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300208
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300209### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300210
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300211Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300212wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300213
214```kotlin
215fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300216 val job = launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300217 delay(1000L)
218 println("World!")
219 }
220 println("Hello,")
221 job.join() // wait until child coroutine completes
222}
223```
224
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300225> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300226
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300227<!--- TEST
228Hello,
229World!
230-->
231
Roman Elizarov7deefb82017-01-31 10:33:17 +0300232Now the result is still the same, but the code of the main coroutine is not tied to the duration of
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300233the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300234
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300235### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300236
Roman Elizarov66f018c2017-09-29 21:39:03 +0300237Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300238perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
239That is your first _suspending function_. Suspending functions can be used inside coroutines
240just like regular functions, but their additional feature is that they can, in turn,
241use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
242
243```kotlin
244fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300245 val job = launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300246 println("Hello,")
247 job.join()
248}
249
250// this is your first suspending function
251suspend fun doWorld() {
252 delay(1000L)
253 println("World!")
254}
255```
256
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300257> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300258
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300259<!--- TEST
260Hello,
261World!
262-->
263
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300264### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300265
266Run the following code:
267
268```kotlin
269fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300270 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
271 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300272 delay(1000L)
273 print(".")
274 }
275 }
276 jobs.forEach { it.join() } // wait for all jobs to complete
277}
278```
279
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300280> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300281
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300282<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
283
Roman Elizarov66f018c2017-09-29 21:39:03 +0300284It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300285Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
286
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300287### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300288
289The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300290returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300291
292```kotlin
293fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300294 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300295 repeat(1000) { i ->
296 println("I'm sleeping $i ...")
297 delay(500L)
298 }
299 }
300 delay(1300L) // just quit after delay
301}
302```
303
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300304> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300305
306You can run and see that it prints three lines and terminates:
307
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300308```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300309I'm sleeping 0 ...
310I'm sleeping 1 ...
311I'm sleeping 2 ...
312```
313
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300314<!--- TEST -->
315
Roman Elizarov7deefb82017-01-31 10:33:17 +0300316Active coroutines do not keep the process alive. They are like daemon threads.
317
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300318## Cancellation and timeouts
319
320This section covers coroutine cancellation and timeouts.
321
322### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300323
324In small application the return from "main" method might sound like a good idea to get all coroutines
325implicitly terminated. In a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300326The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300327
328```kotlin
329fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300330 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300331 repeat(1000) { i ->
332 println("I'm sleeping $i ...")
333 delay(500L)
334 }
335 }
336 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300337 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300338 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300339 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300340 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300341}
342```
343
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300344> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300345
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300346It produces the following output:
347
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300348```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300349I'm sleeping 0 ...
350I'm sleeping 1 ...
351I'm sleeping 2 ...
352main: I'm tired of waiting!
353main: Now I can quit.
354```
355
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300356<!--- TEST -->
357
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300358As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
Roman Elizarov88396732017-09-27 21:30:47 +0300359There is also a [Job] extension function [cancelAndJoin]
360that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300361
362### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300363
Tair Rzayevaf734622017-02-01 22:30:16 +0200364Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300365All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300366coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300367a computation and does not check for cancellation, then it cannot be cancelled, like the following
368example shows:
369
370```kotlin
371fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700372 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300373 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700374 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300375 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300376 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700377 // print a message twice a second
378 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300379 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300380 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300381 }
382 }
383 }
384 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300385 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300386 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300387 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300388}
389```
390
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300391> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300392
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300393Run it to see that it continues to print "I'm sleeping" even after cancellation
394until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300395
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300396<!--- TEST
397I'm sleeping 0 ...
398I'm sleeping 1 ...
399I'm sleeping 2 ...
400main: I'm tired of waiting!
401I'm sleeping 3 ...
402I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300403main: Now I can quit.
404-->
405
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300406### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300407
408There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300409invoke a suspending function that checks for cancellation. There is a [yield] function that is a good choice for that purpose.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300410The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300411
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300412Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300413
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300414```kotlin
415fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700416 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300417 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700418 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300419 var i = 0
420 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700421 // print a message twice a second
422 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300423 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700424 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300425 }
426 }
427 }
428 delay(1300L) // delay a bit
429 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300430 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300431 println("main: Now I can quit.")
432}
433```
434
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300435> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300436
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300437As you can see, now this loop is cancelled. [isActive][CoroutineScope.isActive] is a property that is available inside
Roman Elizarov419a6c82017-02-09 18:36:22 +0300438the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300439
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300440<!--- TEST
441I'm sleeping 0 ...
442I'm sleeping 1 ...
443I'm sleeping 2 ...
444main: I'm tired of waiting!
445main: Now I can quit.
446-->
447
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300448### Closing resources with finally
449
Roman Elizarov419a6c82017-02-09 18:36:22 +0300450Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarov66f018c2017-09-29 21:39:03 +0300451all the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300452finalization actions normally when coroutine is cancelled:
453
454```kotlin
455fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300456 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300457 try {
458 repeat(1000) { i ->
459 println("I'm sleeping $i ...")
460 delay(500L)
461 }
462 } finally {
463 println("I'm running finally")
464 }
465 }
466 delay(1300L) // delay a bit
467 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300468 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300469 println("main: Now I can quit.")
470}
471```
472
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300473> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300474
Roman Elizarov88396732017-09-27 21:30:47 +0300475Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
476so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300477
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300478```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300479I'm sleeping 0 ...
480I'm sleeping 1 ...
481I'm sleeping 2 ...
482main: I'm tired of waiting!
483I'm running finally
484main: Now I can quit.
485```
486
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300487<!--- TEST -->
488
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300489### Run non-cancellable block
490
491Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300492[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300493problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
494communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
495rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300496`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300497
498```kotlin
499fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300500 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300501 try {
502 repeat(1000) { i ->
503 println("I'm sleeping $i ...")
504 delay(500L)
505 }
506 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300507 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300508 println("I'm running finally")
509 delay(1000L)
510 println("And I've just delayed for 1 sec because I'm non-cancellable")
511 }
512 }
513 }
514 delay(1300L) // delay a bit
515 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300516 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300517 println("main: Now I can quit.")
518}
519```
520
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300521> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300522
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300523<!--- TEST
524I'm sleeping 0 ...
525I'm sleeping 1 ...
526I'm sleeping 2 ...
527main: I'm tired of waiting!
528I'm running finally
529And I've just delayed for 1 sec because I'm non-cancellable
530main: Now I can quit.
531-->
532
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300533### Timeout
534
535The most obvious reason to cancel coroutine execution in practice,
536is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300537While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
538the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300539Look at the following example:
540
541```kotlin
542fun main(args: Array<String>) = runBlocking<Unit> {
543 withTimeout(1300L) {
544 repeat(1000) { i ->
545 println("I'm sleeping $i ...")
546 delay(500L)
547 }
548 }
549}
550```
551
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300552> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300553
554It produces the following output:
555
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300556```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300557I'm sleeping 0 ...
558I'm sleeping 1 ...
559I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300560Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300561```
562
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300563<!--- TEST STARTS_WITH -->
564
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300565The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300566We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300567inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300568However, in this example we have used `withTimeout` right inside the `main` function.
569
570Because cancellation is just an exception, all the resources will be closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300571You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
572you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300573that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
574
575```kotlin
576fun main(args: Array<String>) = runBlocking<Unit> {
577 val result = withTimeoutOrNull(1300L) {
578 repeat(1000) { i ->
579 println("I'm sleeping $i ...")
580 delay(500L)
581 }
582 "Done" // will get cancelled before it produces this result
583 }
584 println("Result is $result")
585}
586```
587
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300588> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300589
590There is no longer an exception when running this code:
591
592```text
593I'm sleeping 0 ...
594I'm sleeping 1 ...
595I'm sleeping 2 ...
596Result is null
597```
598
599<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300600
601## Composing suspending functions
602
603This section covers various approaches to composition of suspending functions.
604
605### Sequential by default
606
607Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300608remote service call or computation. We just pretend they are useful, but actually each one just
609delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300610
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300611<!--- INCLUDE .*/example-compose-([0-9]+).kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300612import kotlin.system.*
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300613-->
614
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300615```kotlin
616suspend fun doSomethingUsefulOne(): Int {
617 delay(1000L) // pretend we are doing something useful here
618 return 13
619}
620
621suspend fun doSomethingUsefulTwo(): Int {
622 delay(1000L) // pretend we are doing something useful here, too
623 return 29
624}
625```
626
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300627<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
628
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300629What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
630`doSomethingUsefulTwo` and compute the sum of their results?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200631In practice we do this if we use the results of the first function to make a decision on whether we need
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300632to invoke the second one or to decide on how to invoke it.
633
634We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300635code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300636time it takes to execute both suspending functions:
637
638```kotlin
639fun main(args: Array<String>) = runBlocking<Unit> {
640 val time = measureTimeMillis {
641 val one = doSomethingUsefulOne()
642 val two = doSomethingUsefulTwo()
643 println("The answer is ${one + two}")
644 }
645 println("Completed in $time ms")
646}
647```
648
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300649> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300650
651It produces something like this:
652
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300653```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300654The answer is 42
655Completed in 2017 ms
656```
657
Roman Elizarov35d2c342017-07-20 14:54:39 +0300658<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300659
Roman Elizarov32d95322017-02-09 15:57:31 +0300660### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300661
662What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300663we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300664
Roman Elizarov419a6c82017-02-09 18:36:22 +0300665Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
666that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
667does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300668that represents a promise to provide a result later. You can use `.await()` on a deferred value to get its eventual result,
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300669but `Deferred` is also a `Job`, so you can cancel it if needed.
670
671```kotlin
672fun main(args: Array<String>) = runBlocking<Unit> {
673 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300674 val one = async { doSomethingUsefulOne() }
675 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300676 println("The answer is ${one.await() + two.await()}")
677 }
678 println("Completed in $time ms")
679}
680```
681
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300682> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300683
684It produces something like this:
685
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300686```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300687The answer is 42
688Completed in 1017 ms
689```
690
Roman Elizarov35d2c342017-07-20 14:54:39 +0300691<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300692
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300693This is twice as fast, because we have concurrent execution of two coroutines.
694Note, that concurrency with coroutines is always explicit.
695
Roman Elizarov32d95322017-02-09 15:57:31 +0300696### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300697
Roman Elizarov66f018c2017-09-29 21:39:03 +0300698There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300699It starts coroutine only when its result is needed by some
700[await][Deferred.await] or if a [start][Job.start] function
Roman Elizarov32d95322017-02-09 15:57:31 +0300701is invoked. Run the following example that differs from the previous one only by this option:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300702
703```kotlin
704fun main(args: Array<String>) = runBlocking<Unit> {
705 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300706 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
707 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300708 println("The answer is ${one.await() + two.await()}")
709 }
710 println("Completed in $time ms")
711}
712```
713
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300714> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300715
716It produces something like this:
717
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300718```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300719The answer is 42
720Completed in 2017 ms
721```
722
Roman Elizarov35d2c342017-07-20 14:54:39 +0300723<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300724
Roman Elizarov32d95322017-02-09 15:57:31 +0300725So, we are back to sequential execution, because we _first_ start and await for `one`, _and then_ start and await
726for `two`. It is not the intended use-case for laziness. It is designed as a replacement for
727the standard `lazy` function in cases when computation of the value involves suspending functions.
728
729### Async-style functions
730
731We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300732_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100733"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
734to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300735
736```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100737// The result type of somethingUsefulOneAsync is Deferred<Int>
738fun somethingUsefulOneAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300739 doSomethingUsefulOne()
740}
741
Marcin Moskała7e94e702018-01-29 18:39:02 +0100742// The result type of somethingUsefulTwoAsync is Deferred<Int>
743fun somethingUsefulTwoAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300744 doSomethingUsefulTwo()
745}
746```
747
Marcin Moskała7e94e702018-01-29 18:39:02 +0100748Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300749However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
750with the invoking code.
751
752The following example shows their use outside of coroutine:
753
754```kotlin
755// note, that we don't have `runBlocking` to the right of `main` in this example
756fun main(args: Array<String>) {
757 val time = measureTimeMillis {
758 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100759 val one = somethingUsefulOneAsync()
760 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300761 // but waiting for a result must involve either suspending or blocking.
762 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
763 runBlocking {
764 println("The answer is ${one.await() + two.await()}")
765 }
766 }
767 println("Completed in $time ms")
768}
769```
770
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300771> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300772
Roman Elizarov35d2c342017-07-20 14:54:39 +0300773<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300774The answer is 42
775Completed in 1085 ms
776-->
777
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300778## Coroutine context and dispatchers
779
Roman Elizarov66f018c2017-09-29 21:39:03 +0300780Coroutines always execute in some context which is represented by the value of
781[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
782type, defined in the Kotlin standard library.
783
784The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
785which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300786
787### Dispatchers and threads
788
Roman Elizarov66f018c2017-09-29 21:39:03 +0300789Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300790the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +0300791to a specific thread, dispatch it to a thread pool, or let it run unconfined.
792
793All coroutines builders like [launch] and [async] accept an optional
794[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
795parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
796
797Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300798
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300799<!--- INCLUDE
800import kotlin.coroutines.experimental.*
801-->
802
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300803```kotlin
804fun main(args: Array<String>) = runBlocking<Unit> {
805 val jobs = arrayListOf<Job>()
806 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300807 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300808 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300809 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
810 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300811 }
812 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300813 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300814 }
815 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300816 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300817 }
818 jobs.forEach { it.join() }
819}
820```
821
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300822> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300823
824It produces the following output (maybe in different order):
825
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300826```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300827 'Unconfined': I'm working in thread main
828 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
829 'newSTC': I'm working in thread MyOwnThread
830'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300831```
832
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300833<!--- TEST LINES_START_UNORDERED -->
834
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800835The default dispatcher that we've used in previous sections is representend by [DefaultDispatcher], which
Roman Elizarov66f018c2017-09-29 21:39:03 +0300836is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same
Charles Muchenefa13beb2018-01-08 16:56:54 +0300837as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300838
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300839The difference between parent
840[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html) and
Roman Elizarov43e3af72017-07-21 16:01:31 +0300841[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300842
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800843Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource.
844In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
845function, or stored in a top-level variable and reused throughout the application.
846
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300847### Unconfined vs confined dispatcher
848
Roman Elizarov419a6c82017-02-09 18:36:22 +0300849The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300850first suspension point. After suspension it resumes in the thread that is fully determined by the
851suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
852consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
853
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300854On the other side,
855[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
856property, that is available inside any coroutine, is a reference to a context of this particular coroutine.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300857This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
858is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300859this thread with a predictable FIFO scheduling.
860
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300861<!--- INCLUDE
862import kotlin.coroutines.experimental.*
863-->
864
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300865```kotlin
866fun main(args: Array<String>) = runBlocking<Unit> {
867 val jobs = arrayListOf<Job>()
868 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300869 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300870 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300871 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300872 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300873 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
874 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300875 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300876 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300877 }
878 jobs.forEach { it.join() }
879}
880```
881
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300882> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300883
884Produces the output:
885
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300886```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300887 'Unconfined': I'm working in thread main
888'coroutineContext': I'm working in thread main
889 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
890'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300891```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300892
893<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300894
Roman Elizarov43e3af72017-07-21 16:01:31 +0300895So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
896in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
897function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300898
899### Debugging coroutines and threads
900
Roman Elizarov419a6c82017-02-09 18:36:22 +0300901Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
Roman Elizarov66f018c2017-09-29 21:39:03 +0300902with a default multi-threaded dispatcher. Even with a single-threaded dispatcher it might be hard to
paolopb019b102018-06-09 16:42:24 +0000903figure out what coroutine was doing, where, and when. The common approach to debugging applications with
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300904threads is to print the thread name in the log file on each log statement. This feature is universally supported
905by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
906`kotlinx.coroutines` includes debugging facilities to make it easier.
907
908Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
909
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300910<!--- INCLUDE
911import kotlin.coroutines.experimental.*
912-->
913
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300914```kotlin
915fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
916
917fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300918 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300919 log("I'm computing a piece of the answer")
920 6
921 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300922 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300923 log("I'm computing another piece of the answer")
924 7
925 }
926 log("The answer is ${a.await() * b.await()}")
927}
928```
929
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300930> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300931
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300932There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300933and two coroutines computing deferred values `a` (#2) and `b` (#3).
934They are all executing in the context of `runBlocking` and are confined to the main thread.
935The output of this code is:
936
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300937```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300938[main @coroutine#2] I'm computing a piece of the answer
939[main @coroutine#3] I'm computing another piece of the answer
940[main @coroutine#1] The answer is 42
941```
942
Kirill Timofeeva5186962017-10-25 14:25:47 +0300943<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300944
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300945The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
946thread, but the identifier of the currently executing coroutine is appended to it. This identifier
947is consecutively assigned to all created coroutines when debugging mode is turned on.
948
Roman Elizarov419a6c82017-02-09 18:36:22 +0300949You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300950
951### Jumping between threads
952
953Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
954
955```kotlin
956fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
957
958fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800959 newSingleThreadContext("Ctx1").use { ctx1 ->
960 newSingleThreadContext("Ctx2").use { ctx2 ->
961 runBlocking(ctx1) {
962 log("Started in ctx1")
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300963 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800964 log("Working in ctx2")
965 }
966 log("Back to ctx1")
967 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300968 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300969 }
970}
971```
972
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +0300973> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300974
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800975It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300976the 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 +0300977same coroutine as you can see in the output below:
978
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300979```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300980[Ctx1 @coroutine#1] Started in ctx1
981[Ctx2 @coroutine#1] Working in ctx2
982[Ctx1 @coroutine#1] Back to ctx1
983```
984
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300985<!--- TEST -->
986
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800987
Artsiom Chapialioue185ed62018-06-03 19:34:22 -0400988Note, that this example also uses `use` function from the Kotlin standard library to release threads that
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800989are created with [newSingleThreadContext] when they are no longer needed.
990
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300991### Job in the context
992
Roman Elizarov66f018c2017-09-29 21:39:03 +0300993The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +0300994using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300995
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300996<!--- INCLUDE
997import kotlin.coroutines.experimental.*
998-->
999
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001000```kotlin
1001fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001002 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001003}
1004```
1005
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001006> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001007
Roman Elizarov66f018c2017-09-29 21:39:03 +03001008It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001009
1010```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001011My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001012```
1013
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001014<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001015
Roman Elizarov43e3af72017-07-21 16:01:31 +03001016So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001017`coroutineContext[Job]?.isActive == true`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001018
1019### Children of a coroutine
1020
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001021When
1022[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
1023of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +03001024the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001025a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1026are recursively cancelled, too.
1027
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001028<!--- INCLUDE
1029import kotlin.coroutines.experimental.*
1030-->
1031
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001032```kotlin
1033fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001034 // launch a coroutine to process some kind of incoming request
1035 val request = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001036 // it spawns two other jobs, one with its separate context
Roman Elizarov66f018c2017-09-29 21:39:03 +03001037 val job1 = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001038 println("job1: I have my own context and execute independently!")
1039 delay(1000)
1040 println("job1: I am not affected by cancellation of the request")
1041 }
1042 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001043 val job2 = launch(coroutineContext) {
Roman Elizarov74619c12017-11-09 10:32:15 +03001044 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001045 println("job2: I am a child of the request coroutine")
1046 delay(1000)
1047 println("job2: I will not execute this line if my parent request is cancelled")
1048 }
1049 // request completes when both its sub-jobs complete:
1050 job1.join()
1051 job2.join()
1052 }
1053 delay(500)
1054 request.cancel() // cancel processing of the request
1055 delay(1000) // delay a second to see what happens
1056 println("main: Who has survived request cancellation?")
1057}
1058```
1059
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001060> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001061
1062The output of this code is:
1063
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001064```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001065job1: I have my own context and execute independently!
1066job2: I am a child of the request coroutine
1067job1: I am not affected by cancellation of the request
1068main: Who has survived request cancellation?
1069```
1070
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001071<!--- TEST -->
1072
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001073### Combining contexts
1074
Roman Elizarov66f018c2017-09-29 21:39:03 +03001075Coroutine contexts can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +03001076of the context on the left-hand side. For example, a [Job] of the parent coroutine can be inherited, while
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001077its dispatcher replaced:
1078
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001079<!--- INCLUDE
1080import kotlin.coroutines.experimental.*
1081-->
1082
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001083```kotlin
1084fun main(args: Array<String>) = runBlocking<Unit> {
1085 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +03001086 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001087 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +03001088 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001089 println("job: I am a child of the request coroutine, but with a different dispatcher")
1090 delay(1000)
1091 println("job: I will not execute this line if my parent request is cancelled")
1092 }
1093 job.join() // request completes when its sub-job completes
1094 }
1095 delay(500)
1096 request.cancel() // cancel processing of the request
1097 delay(1000) // delay a second to see what happens
1098 println("main: Who has survived request cancellation?")
1099}
1100```
1101
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001102> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001103
1104The expected outcome of this code is:
1105
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001106```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001107job: I am a child of the request coroutine, but with a different dispatcher
1108main: Who has survived request cancellation?
1109```
1110
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001111<!--- TEST -->
1112
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001113### Parental responsibilities
1114
1115A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001116all 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 +03001117
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001118<!--- INCLUDE
1119import kotlin.coroutines.experimental.*
1120-->
1121
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001122```kotlin
1123fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001124 // launch a coroutine to process some kind of incoming request
1125 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001126 repeat(3) { i -> // launch a few children jobs
1127 launch(coroutineContext) {
1128 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1129 println("Coroutine $i is done")
1130 }
1131 }
1132 println("request: I'm done and I don't explicitly join my children that are still active")
1133 }
1134 request.join() // wait for completion of the request, including all its children
1135 println("Now processing of the request is complete")
1136}
1137```
1138
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001139> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-08.kt)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001140
1141The result is going to be:
1142
1143```text
1144request: I'm done and I don't explicitly join my children that are still active
1145Coroutine 0 is done
1146Coroutine 1 is done
1147Coroutine 2 is done
1148Now processing of the request is complete
1149```
1150
1151<!--- TEST -->
1152
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001153### Naming coroutines for debugging
1154
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001155Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001156coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1157or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001158[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1159is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001160
1161The following example demonstrates this concept:
1162
1163```kotlin
1164fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1165
1166fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1167 log("Started main coroutine")
1168 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001169 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001170 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001171 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001172 252
1173 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001174 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001175 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001176 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001177 6
1178 }
1179 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1180}
1181```
1182
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001183> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-09.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001184
1185The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1186
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001187```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001188[main @main#1] Started main coroutine
1189[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1190[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1191[main @main#1] The answer for v1 / v2 = 42
1192```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001193
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001194<!--- TEST FLEXIBLE_THREAD -->
1195
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001196### Cancellation via explicit job
1197
1198Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1199an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1200and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1201and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1202to avoid memory leaks.
1203
1204We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
Roman Elizarov88396732017-09-27 21:30:47 +03001205the lifecycle of our activity. A job instance is created using [Job()] factory function
Roman Elizarove8f694e2017-11-28 10:12:00 +03001206as the following example shows. For convenience, rather than using `launch(coroutineContext + job)` expression,
1207we can write `launch(coroutineContext, parent = job)` to make explicit the fact that the parent job is being used.
1208
1209Now, a single invocation of [Job.cancel] cancels all the children we've launched.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001210Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1211this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001212
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001213<!--- INCLUDE
1214import kotlin.coroutines.experimental.*
1215-->
1216
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001217```kotlin
1218fun main(args: Array<String>) = runBlocking<Unit> {
1219 val job = Job() // create a job object to manage our lifecycle
1220 // now launch ten coroutines for a demo, each working for a different time
1221 val coroutines = List(10) { i ->
1222 // they are all children of our job object
Roman Elizarove8f694e2017-11-28 10:12:00 +03001223 launch(coroutineContext, parent = job) { // we use the context of main runBlocking thread, but with our parent job
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001224 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001225 println("Coroutine $i is done")
1226 }
1227 }
1228 println("Launched ${coroutines.size} coroutines")
1229 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001230 println("Cancelling the job!")
1231 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001232}
1233```
1234
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001235> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-context-10.kt)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001236
1237The output of this example is:
1238
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001239```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001240Launched 10 coroutines
1241Coroutine 0 is done
1242Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001243Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001244```
1245
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001246<!--- TEST -->
1247
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001248As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001249by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001250application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001251and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1252since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1253resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001254
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001255## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001256
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001257Deferred values provide a convenient way to transfer a single value between coroutines.
1258Channels provide a way to transfer a stream of values.
1259
1260<!--- INCLUDE .*/example-channel-([0-9]+).kt
1261import kotlinx.coroutines.experimental.channels.*
1262-->
1263
1264### Channel basics
1265
Roman Elizarov419a6c82017-02-09 18:36:22 +03001266A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1267instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1268a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001269
1270```kotlin
1271fun main(args: Array<String>) = runBlocking<Unit> {
1272 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001273 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001274 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1275 for (x in 1..5) channel.send(x * x)
1276 }
1277 // here we print five received integers:
1278 repeat(5) { println(channel.receive()) }
1279 println("Done!")
1280}
1281```
1282
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001283> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-01.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001284
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001285The output of this code is:
1286
1287```text
12881
12894
12909
129116
129225
1293Done!
1294```
1295
1296<!--- TEST -->
1297
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001298### Closing and iteration over channels
1299
1300Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1301On the receiver side it is convenient to use a regular `for` loop to receive elements
1302from the channel.
1303
Roman Elizarov419a6c82017-02-09 18:36:22 +03001304Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001305The iteration stops as soon as this close token is received, so there is a guarantee
1306that all previously sent elements before the close are received:
1307
1308```kotlin
1309fun main(args: Array<String>) = runBlocking<Unit> {
1310 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001311 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001312 for (x in 1..5) channel.send(x * x)
1313 channel.close() // we're done sending
1314 }
1315 // here we print received values using `for` loop (until the channel is closed)
1316 for (y in channel) println(y)
1317 println("Done!")
1318}
1319```
1320
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001321> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001322
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001323<!--- TEST
13241
13254
13269
132716
132825
1329Done!
1330-->
1331
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001332### Building channel producers
1333
Roman Elizarova5e653f2017-02-13 13:49:55 +03001334The pattern where a coroutine is producing a sequence of elements is quite common.
1335This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001336You 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 +03001337to common sense that results must be returned from functions.
1338
Roman Elizarov86349be2017-03-17 16:47:37 +03001339There 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 +03001340and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001341
1342```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001343fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001344 for (x in 1..5) send(x * x)
1345}
1346
1347fun main(args: Array<String>) = runBlocking<Unit> {
1348 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001349 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001350 println("Done!")
1351}
1352```
1353
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001354> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-03.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001355
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001356<!--- TEST
13571
13584
13599
136016
136125
1362Done!
1363-->
1364
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001365### Pipelines
1366
Roman Elizarov66f018c2017-09-29 21:39:03 +03001367A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001368
1369```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001370fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001371 var x = 1
1372 while (true) send(x++) // infinite stream of integers starting from 1
1373}
1374```
1375
Roman Elizarova5e653f2017-02-13 13:49:55 +03001376And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001377In the below example the numbers are just squared:
1378
1379```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001380fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001381 for (x in numbers) send(x * x)
1382}
1383```
1384
Roman Elizarova5e653f2017-02-13 13:49:55 +03001385The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001386
1387```kotlin
1388fun main(args: Array<String>) = runBlocking<Unit> {
1389 val numbers = produceNumbers() // produces integers from 1 and on
1390 val squares = square(numbers) // squares integers
1391 for (i in 1..5) println(squares.receive()) // print first five
1392 println("Done!") // we are done
1393 squares.cancel() // need to cancel these coroutines in a larger app
1394 numbers.cancel()
1395}
1396```
1397
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001398> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-04.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001399
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001400<!--- TEST
14011
14024
14039
140416
140525
1406Done!
1407-->
1408
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001409We don't have to cancel these coroutines in this example app, because
1410[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1411but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1412Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001413[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001414
1415### Prime numbers with pipeline
1416
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001417Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001418of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001419explicit `context` parameter and pass it to [produce] builder,
1420so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001421
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001422<!--- INCLUDE
1423import kotlin.coroutines.experimental.*
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001424-->
1425
1426```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001427fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001428 var x = start
1429 while (true) send(x++) // infinite stream of integers from start
1430}
1431```
1432
1433The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1434that are divisible by the given prime number:
1435
1436```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001437fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001438 for (x in numbers) if (x % prime != 0) send(x)
1439}
1440```
1441
1442Now 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 +03001443and launching new pipeline stage for each prime number found:
1444
1445```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001446numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001447```
1448
1449The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001450running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001451children of the main [runBlocking] coroutine in its
1452[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html),
1453we don't have to keep an explicit list of all the coroutines we have started.
Roman Elizarov3e387b82017-12-04 13:49:11 +03001454We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
1455extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001456
1457```kotlin
1458fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001459 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001460 for (i in 1..10) {
1461 val prime = cur.receive()
1462 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001463 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001464 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001465 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001466}
1467```
1468
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001469> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-05.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001470
1471The output of this code is:
1472
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001473```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030014742
14753
14765
14777
147811
147913
148017
148119
148223
148329
1484```
1485
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001486<!--- TEST -->
1487
Roman Elizarov66f018c2017-09-29 21:39:03 +03001488Note, that you can build the same pipeline using
1489[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1490coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001491Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001492`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1493However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1494multiple CPU cores if you run it in [CommonPool] context.
1495
Roman Elizarova5e653f2017-02-13 13:49:55 +03001496Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001497other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1498built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001499`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001500
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001501### Fan-out
1502
1503Multiple coroutines may receive from the same channel, distributing work between themselves.
1504Let us start with a producer coroutine that is periodically producing integers
1505(ten numbers per second):
1506
1507```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001508fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001509 var x = 1 // start from 1
1510 while (true) {
1511 send(x++) // produce next
1512 delay(100) // wait 0.1s
1513 }
1514}
1515```
1516
1517Then we can have several processor coroutines. In this example, they just print their id and
1518received number:
1519
1520```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001521fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
bill58c61c72018-06-21 17:24:08 -05001522 for (msg in channel) {
1523 println("Processor #$id received $msg")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001524 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001525}
1526```
1527
Roman Elizarov35d2c342017-07-20 14:54:39 +03001528Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001529
1530```kotlin
1531fun main(args: Array<String>) = runBlocking<Unit> {
1532 val producer = produceNumbers()
1533 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001534 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001535 producer.cancel() // cancel producer coroutine and thus kill them all
1536}
1537```
1538
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001539> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-06.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001540
1541The output will be similar to the the following one, albeit the processor ids that receive
1542each specific integer may be different:
1543
1544```
1545Processor #2 received 1
1546Processor #4 received 2
1547Processor #0 received 3
1548Processor #1 received 4
1549Processor #3 received 5
1550Processor #2 received 6
1551Processor #4 received 7
1552Processor #0 received 8
1553Processor #1 received 9
1554Processor #3 received 10
1555```
1556
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001557<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1558
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001559Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1560over the channel that processor coroutines are doing.
1561
Roman Elizarov1ce6c0b2018-06-28 10:37:20 +03001562Also, pay attention to how we explicitly iterate over channel with `for` loop to perform fan-out in `launchProcessor` code.
1563Unlike `consumeEach`, this `for` loop pattern is perfectly safe to use from multiple coroutines. If one of the processor
1564coroutines fails, then others would still be processing the channel, while a processor that is written via `consumeEach`
1565always consumes (cancels) the underlying channel on its normal or abnormal termination.
1566
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001567### Fan-in
1568
1569Multiple coroutines may send to the same channel.
1570For example, let us have a channel of strings, and a suspending function that
1571repeatedly sends a specified string to this channel with a specified delay:
1572
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001573<!--- INCLUDE
1574import kotlin.coroutines.experimental.*
1575-->
1576
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001577```kotlin
1578suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1579 while (true) {
1580 delay(time)
1581 channel.send(s)
1582 }
1583}
1584```
1585
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001586Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001587(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 +03001588
1589```kotlin
1590fun main(args: Array<String>) = runBlocking<Unit> {
1591 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001592 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1593 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001594 repeat(6) { // receive first six
1595 println(channel.receive())
1596 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001597 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001598}
1599```
1600
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001601> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-07.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001602
1603The output is:
1604
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001605```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001606foo
1607foo
1608BAR!
1609foo
1610foo
1611BAR!
1612```
1613
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001614<!--- TEST -->
1615
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001616### Buffered channels
1617
1618The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1619meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1620if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001621
Roman Elizarov88396732017-09-27 21:30:47 +03001622Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001623specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1624similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1625
1626Take a look at the behavior of the following code:
1627
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001628<!--- INCLUDE
1629import kotlin.coroutines.experimental.*
1630-->
1631
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001632```kotlin
1633fun main(args: Array<String>) = runBlocking<Unit> {
1634 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001635 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001636 repeat(10) {
1637 println("Sending $it") // print before sending each element
1638 channel.send(it) // will suspend when buffer is full
1639 }
1640 }
1641 // don't receive anything... just wait....
1642 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001643 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001644}
1645```
1646
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001647> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001648
1649It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1650
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001651```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001652Sending 0
1653Sending 1
1654Sending 2
1655Sending 3
1656Sending 4
1657```
1658
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001659<!--- TEST -->
1660
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001661The 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 +03001662
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001663### Ticker channels
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001664
Roman Elizarovb5328a72018-06-06 18:31:21 +03001665Ticker channel is a special rendezvous channel that produces `Unit` every time given delay passes since last consumption from this channel.
1666Though it may seem to be useless standalone, it is a useful building block to create complex time-based [produce]
1667pipelines and operators that do windowing and other time-dependend processing.
1668Ticker channel can be used in [select] to perform "on tick" action.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001669
Roman Elizarovb5328a72018-06-06 18:31:21 +03001670To create such channel use a factory method [ticker].
1671To indicate that no further elements are needed use [ReceiveChannel.cancel] method on it.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001672
1673Now let's see how it works in practice:
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001674
1675```kotlin
1676fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovb5328a72018-06-06 18:31:21 +03001677 val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001678 var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
1679 println("Initial element is available immediately: $nextElement") // Initial delay hasn't passed yet
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001680
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001681 nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // All subsequent elements has 100ms delay
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001682 println("Next element is not ready in 50 ms: $nextElement")
1683
Roman Elizarovb5328a72018-06-06 18:31:21 +03001684 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001685 println("Next element is ready in 100 ms: $nextElement")
1686
1687 // Emulate large consumption delays
Roman Elizarovb5328a72018-06-06 18:31:21 +03001688 println("Consumer pauses for 150ms")
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001689 delay(150)
1690 // Next element is available immediately
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001691 nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001692 println("Next element is available immediately after large consumer delay: $nextElement")
1693 // Note that the pause between `receive` calls is taken into account and next element arrives faster
Roman Elizarovb5328a72018-06-06 18:31:21 +03001694 nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001695 println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
1696
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03001697 tickerChannel.cancel() // indicate that no more elements are needed
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001698}
1699```
1700
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001701> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-10.kt)
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001702
1703It prints following lines:
1704
1705```text
1706Initial element is available immediately: kotlin.Unit
1707Next element is not ready in 50 ms: null
1708Next element is ready in 100 ms: kotlin.Unit
Roman Elizarovb5328a72018-06-06 18:31:21 +03001709Consumer pauses for 150ms
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001710Next element is available immediately after large consumer delay: kotlin.Unit
1711Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
1712```
1713
1714<!--- TEST -->
1715
Roman Elizarovb5328a72018-06-06 18:31:21 +03001716Note that [ticker] is aware of possible consumer pauses and, by default, adjusts next produced element
1717delay if a pause occurs, trying to maintain a fixed rate of produced elements.
1718
1719Optionally, a `mode` parameters equal to [TickerMode.FIXED_DELAY] can be specified to maintain a fixed
1720delay between elements.
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03001721
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001722### Channels are fair
1723
1724Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1725multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1726gets the element. In the following example two coroutines "ping" and "pong" are
1727receiving the "ball" object from the shared "table" channel.
1728
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001729<!--- INCLUDE
1730import kotlin.coroutines.experimental.*
1731-->
1732
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001733```kotlin
1734data class Ball(var hits: Int)
1735
1736fun main(args: Array<String>) = runBlocking<Unit> {
1737 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001738 launch(coroutineContext) { player("ping", table) }
1739 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001740 table.send(Ball(0)) // serve the ball
1741 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001742 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001743}
1744
1745suspend fun player(name: String, table: Channel<Ball>) {
1746 for (ball in table) { // receive the ball in a loop
1747 ball.hits++
1748 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001749 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001750 table.send(ball) // send the ball back
1751 }
1752}
1753```
1754
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001755> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-channel-09.kt)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001756
1757The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1758coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1759received by the "pong" coroutine, because it was already waiting for it:
1760
1761```text
1762ping Ball(hits=1)
1763pong Ball(hits=2)
1764ping Ball(hits=3)
1765pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001766```
1767
1768<!--- TEST -->
1769
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001770Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
1771that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
1772
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001773## Shared mutable state and concurrency
1774
Roman Elizarov66f018c2017-09-29 21:39:03 +03001775Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001776all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1777Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1778but others are unique.
1779
1780### The problem
1781
Roman Elizarov1e459602017-02-27 11:05:17 +03001782Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1783We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001784
Roman Elizarov1e459602017-02-27 11:05:17 +03001785<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001786import java.util.concurrent.atomic.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001787-->
1788
Roman Elizarov1e459602017-02-27 11:05:17 +03001789<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001790import kotlinx.coroutines.experimental.sync.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001791-->
1792
Roman Elizarov1e459602017-02-27 11:05:17 +03001793<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001794import kotlinx.coroutines.experimental.channels.*
1795-->
1796
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001797<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
1798import kotlin.system.*
1799import kotlin.coroutines.experimental.*
1800-->
1801
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001802```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001803suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1804 val n = 1000 // number of coroutines to launch
1805 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001806 val time = measureTimeMillis {
1807 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001808 launch(context) {
1809 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001810 }
1811 }
1812 jobs.forEach { it.join() }
1813 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001814 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001815}
1816```
1817
Roman Elizarov43e90112017-05-10 11:25:20 +03001818<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001819
Roman Elizarov1e459602017-02-27 11:05:17 +03001820We start with a very simple action that increments a shared mutable variable using
1821multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001822
1823```kotlin
1824var counter = 0
1825
1826fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001827 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001828 counter++
1829 }
1830 println("Counter = $counter")
1831}
1832```
1833
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001834> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001835
Roman Elizarov1e459602017-02-27 11:05:17 +03001836<!--- TEST LINES_START
1837Completed 1000000 actions in
1838Counter =
1839-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001840
Roman Elizarov1e459602017-02-27 11:05:17 +03001841What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1842increment the `counter` concurrently from multiple threads without any synchronization.
1843
Roman Elizarov43e90112017-05-10 11:25:20 +03001844> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1845`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1846following change:
1847
1848```kotlin
1849val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1850var counter = 0
1851
1852fun main(args: Array<String>) = runBlocking<Unit> {
1853 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1854 counter++
1855 }
1856 println("Counter = $counter")
1857}
1858```
1859
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001860> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt)
Roman Elizarov43e90112017-05-10 11:25:20 +03001861
1862<!--- TEST LINES_START
1863Completed 1000000 actions in
1864Counter =
1865-->
1866
Roman Elizarov1e459602017-02-27 11:05:17 +03001867### Volatiles are of no help
1868
1869There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1870
1871```kotlin
1872@Volatile // in Kotlin `volatile` is an annotation
1873var counter = 0
1874
1875fun main(args: Array<String>) = runBlocking<Unit> {
1876 massiveRun(CommonPool) {
1877 counter++
1878 }
1879 println("Counter = $counter")
1880}
1881```
1882
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001883> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001884
1885<!--- TEST LINES_START
1886Completed 1000000 actions in
1887Counter =
1888-->
1889
1890This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1891linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1892do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001893
1894### Thread-safe data structures
1895
1896The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1897linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1898operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001899In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001900
1901```kotlin
1902var counter = AtomicInteger()
1903
1904fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001905 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001906 counter.incrementAndGet()
1907 }
1908 println("Counter = ${counter.get()}")
1909}
1910```
1911
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001912> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001913
Roman Elizarov1e459602017-02-27 11:05:17 +03001914<!--- TEST ARBITRARY_TIME
1915Completed 1000000 actions in xxx ms
1916Counter = 1000000
1917-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001918
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001919This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1920standard data structures and basic operations on them. However, it does not easily scale to complex
1921state or to complex operations that do not have ready-to-use thread-safe implementations.
1922
Roman Elizarov1e459602017-02-27 11:05:17 +03001923### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001924
Roman Elizarov1e459602017-02-27 11:05:17 +03001925_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 +03001926state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1927the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1928single-threaded context:
1929
1930```kotlin
1931val counterContext = newSingleThreadContext("CounterContext")
1932var counter = 0
1933
1934fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001935 massiveRun(CommonPool) { // run each coroutine in CommonPool
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001936 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001937 counter++
1938 }
1939 }
1940 println("Counter = $counter")
1941}
1942```
1943
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001944> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001945
Roman Elizarov1e459602017-02-27 11:05:17 +03001946<!--- TEST ARBITRARY_TIME
1947Completed 1000000 actions in xxx ms
1948Counter = 1000000
1949-->
1950
1951This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001952from multi-threaded `CommonPool` context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03001953
1954### Thread confinement coarse-grained
1955
1956In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1957are confined to the single thread. The following example does it like that, running each coroutine in
1958the single-threaded context to start with.
1959
1960```kotlin
1961val counterContext = newSingleThreadContext("CounterContext")
1962var counter = 0
1963
1964fun main(args: Array<String>) = runBlocking<Unit> {
1965 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1966 counter++
1967 }
1968 println("Counter = $counter")
1969}
1970```
1971
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03001972> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-05.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001973
1974<!--- TEST ARBITRARY_TIME
1975Completed 1000000 actions in xxx ms
1976Counter = 1000000
1977-->
1978
1979This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001980
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001981### Mutual exclusion
1982
1983Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1984that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1985Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1986delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1987
Roman Elizarov88396732017-09-27 21:30:47 +03001988There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001989`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
1990
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001991```kotlin
1992val mutex = Mutex()
1993var counter = 0
1994
1995fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001996 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001997 mutex.withLock {
1998 counter++
1999 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002000 }
2001 println("Counter = $counter")
2002}
2003```
2004
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002005> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002006
Roman Elizarov1e459602017-02-27 11:05:17 +03002007<!--- TEST ARBITRARY_TIME
2008Completed 1000000 actions in xxx ms
2009Counter = 1000000
2010-->
2011
2012The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
2013where you absolutely must modify some shared state periodically, but there is no natural thread that this state
2014is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002015
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002016### Actors
2017
2018An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
2019and a channel to communicate with other coroutines. A simple actor can be written as a function,
2020but an actor with a complex state is better suited for a class.
2021
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002022There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
2023scope to receive messages from and combines the send channel into the resulting job object, so that a
2024single reference to the actor can be carried around as its handle.
2025
Roman Elizarov256812a2017-07-22 01:00:30 +03002026The first step of using an actor is to define a class of messages that an actor is going to process.
2027Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
2028We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
2029to get its value. The later needs to send a response. A [CompletableDeferred] communication
2030primitive, that represents a single value that will be known (communicated) in the future,
2031is used here for that purpose.
2032
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002033```kotlin
2034// Message types for counterActor
2035sealed class CounterMsg
2036object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03002037class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
2038```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002039
Roman Elizarov256812a2017-07-22 01:00:30 +03002040Then we define a function that launches an actor using an [actor] coroutine builder:
2041
2042```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002043// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03002044fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002045 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002046 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002047 when (msg) {
2048 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03002049 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002050 }
2051 }
2052}
Roman Elizarov256812a2017-07-22 01:00:30 +03002053```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002054
Roman Elizarov256812a2017-07-22 01:00:30 +03002055The main code is straightforward:
2056
2057```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002058fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002059 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03002060 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002061 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002062 }
Roman Elizarov256812a2017-07-22 01:00:30 +03002063 // send a message to get a counter value from an actor
2064 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002065 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03002066 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002067 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002068}
2069```
2070
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002071> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002072
Roman Elizarov1e459602017-02-27 11:05:17 +03002073<!--- TEST ARBITRARY_TIME
2074Completed 1000000 actions in xxx ms
2075Counter = 1000000
2076-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002077
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002078It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002079a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
2080works as a solution to the problem of shared mutable state.
2081
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002082Actor is more efficient than locking under load, because in this case it always has work to do and it does not
2083have to switch to a different context at all.
2084
2085> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
2086 with the channel that it receives messages from, while a producer is associated with the channel that it
2087 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03002088
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002089## Select expression
2090
Roman Elizarova84730b2017-02-22 11:58:50 +03002091Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002092the first one that becomes available.
2093
2094<!--- INCLUDE .*/example-select-([0-9]+).kt
2095import kotlinx.coroutines.experimental.channels.*
2096import kotlinx.coroutines.experimental.selects.*
2097-->
2098
2099### Selecting from channels
2100
Roman Elizarov57857202017-03-02 23:17:25 +03002101Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2102
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002103<!--- INCLUDE
2104import kotlinx.coroutines.experimental.*
2105import kotlin.coroutines.experimental.*
Roman Elizarov57857202017-03-02 23:17:25 +03002106-->
2107
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002108```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002109fun fizz(context: CoroutineContext) = produce<String>(context) {
2110 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002111 delay(300)
2112 send("Fizz")
2113 }
2114}
2115```
2116
Roman Elizarov57857202017-03-02 23:17:25 +03002117And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002118
2119```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002120fun buzz(context: CoroutineContext) = produce<String>(context) {
2121 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002122 delay(500)
2123 send("Buzz!")
2124 }
2125}
2126```
2127
2128Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2129other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002130[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002131
2132```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002133suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002134 select<Unit> { // <Unit> means that this select expression does not produce any result
2135 fizz.onReceive { value -> // this is the first select clause
2136 println("fizz -> '$value'")
2137 }
2138 buzz.onReceive { value -> // this is the second select clause
2139 println("buzz -> '$value'")
2140 }
2141 }
2142}
2143```
2144
Roman Elizarov57857202017-03-02 23:17:25 +03002145Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002146
2147```kotlin
2148fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002149 val fizz = fizz(coroutineContext)
2150 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002151 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002152 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002153 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002154 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002155}
2156```
2157
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002158> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-01.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002159
2160The result of this code is:
2161
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002162```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002163fizz -> 'Fizz'
2164buzz -> 'Buzz!'
2165fizz -> 'Fizz'
2166fizz -> 'Fizz'
2167buzz -> 'Buzz!'
2168fizz -> 'Fizz'
2169buzz -> 'Buzz!'
2170```
2171
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002172<!--- TEST -->
2173
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002174### Selecting on close
2175
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002176The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed and the corresponding
2177`select` throws an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002178specific 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 +03002179the result of its selected clause:
2180
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002181<!--- INCLUDE
2182import kotlin.coroutines.experimental.*
2183-->
2184
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002185```kotlin
2186suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2187 select<String> {
2188 a.onReceiveOrNull { value ->
2189 if (value == null)
2190 "Channel 'a' is closed"
2191 else
2192 "a -> '$value'"
2193 }
2194 b.onReceiveOrNull { value ->
2195 if (value == null)
2196 "Channel 'b' is closed"
2197 else
2198 "b -> '$value'"
2199 }
2200 }
2201```
2202
Roman Elizarova84730b2017-02-22 11:58:50 +03002203Let's use it with channel `a` that produces "Hello" string four times and
2204channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002205
2206```kotlin
2207fun main(args: Array<String>) = runBlocking<Unit> {
2208 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002209 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002210 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002211 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002212 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002213 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002214 }
2215 repeat(8) { // print first eight results
2216 println(selectAorB(a, b))
2217 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002218 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002219}
2220```
2221
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002222> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-02.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002223
Roman Elizarova84730b2017-02-22 11:58:50 +03002224The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002225
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002226```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002227a -> 'Hello 0'
2228a -> 'Hello 1'
2229b -> 'World 0'
2230a -> 'Hello 2'
2231a -> 'Hello 3'
2232b -> 'World 1'
2233Channel 'a' is closed
2234Channel 'a' is closed
2235```
2236
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002237<!--- TEST -->
2238
Roman Elizarova84730b2017-02-22 11:58:50 +03002239There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002240
2241First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2242the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002243being 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 +03002244time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2245
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002246The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002247channel is already closed.
2248
2249### Selecting to send
2250
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002251Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002252with a biased nature of selection.
2253
Roman Elizarova84730b2017-02-22 11:58:50 +03002254Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002255the consumers on its primary channel cannot keep up with it:
2256
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002257<!--- INCLUDE
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002258import kotlin.coroutines.experimental.*
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002259-->
2260
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002261```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002262fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002263 for (num in 1..10) { // produce 10 numbers from 1 to 10
2264 delay(100) // every 100 ms
2265 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002266 onSend(num) {} // Send to the primary channel
2267 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002268 }
2269 }
2270}
2271```
2272
2273Consumer is going to be quite slow, taking 250 ms to process each number:
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002274
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002275```kotlin
2276fun main(args: Array<String>) = runBlocking<Unit> {
2277 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002278 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002279 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002280 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002281 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002282 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002283 delay(250) // let us digest the consumed number properly, do not hurry
2284 }
2285 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002286 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002287}
2288```
2289
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002290> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-03.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002291
2292So let us see what happens:
2293
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002294```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002295Consuming 1
2296Side channel has 2
2297Side channel has 3
2298Consuming 4
2299Side channel has 5
2300Side channel has 6
2301Consuming 7
2302Side channel has 8
2303Side channel has 9
2304Consuming 10
2305Done consuming
2306```
2307
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002308<!--- TEST -->
2309
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002310### Selecting deferred values
2311
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002312Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002313Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002314a random delay:
2315
2316<!--- INCLUDE .*/example-select-04.kt
2317import java.util.*
2318-->
2319
2320```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002321fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002322 delay(time.toLong())
2323 "Waited for $time ms"
2324}
2325```
2326
Roman Elizarova84730b2017-02-22 11:58:50 +03002327Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002328
2329```kotlin
2330fun asyncStringsList(): List<Deferred<String>> {
2331 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002332 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002333}
2334```
2335
Roman Elizarova84730b2017-02-22 11:58:50 +03002336Now 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 +03002337that 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 +03002338so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2339of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002340
2341```kotlin
2342fun main(args: Array<String>) = runBlocking<Unit> {
2343 val list = asyncStringsList()
2344 val result = select<String> {
2345 list.withIndex().forEach { (index, deferred) ->
2346 deferred.onAwait { answer ->
2347 "Deferred $index produced answer '$answer'"
2348 }
2349 }
2350 }
2351 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002352 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002353 println("$countActive coroutines are still active")
2354}
2355```
2356
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002357> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-04.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002358
2359The output is:
2360
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002361```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002362Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300236311 coroutines are still active
2364```
2365
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002366<!--- TEST -->
2367
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002368### Switch over a channel of deferred values
2369
Roman Elizarova84730b2017-02-22 11:58:50 +03002370Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2371deferred 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 +03002372[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002373
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002374<!--- INCLUDE
2375import kotlin.coroutines.experimental.*
2376-->
2377
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002378```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002379fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002380 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002381 while (isActive) { // loop while not cancelled/closed
2382 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2383 input.onReceiveOrNull { update ->
2384 update // replaces next value to wait
2385 }
2386 current.onAwait { value ->
2387 send(value) // send value that current deferred has produced
2388 input.receiveOrNull() // and use the next deferred from the input channel
2389 }
2390 }
2391 if (next == null) {
2392 println("Channel was closed")
2393 break // out of loop
2394 } else {
2395 current = next
2396 }
2397 }
2398}
2399```
2400
2401To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2402
2403```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002404fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002405 delay(time)
2406 str
2407}
2408```
2409
2410The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2411data to it:
2412
2413```kotlin
2414fun main(args: Array<String>) = runBlocking<Unit> {
2415 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002416 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002417 for (s in switchMapDeferreds(chan))
2418 println(s) // print each received string
2419 }
2420 chan.send(asyncString("BEGIN", 100))
2421 delay(200) // enough time for "BEGIN" to be produced
2422 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002423 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002424 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002425 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002426 chan.send(asyncString("END", 500))
2427 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002428 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002429 delay(500) // and wait some time to let it finish
2430}
2431```
2432
Vsevolod Tolstopyatovc1eb19f2018-06-19 17:04:09 +03002433> You can get full code [here](core/kotlinx-coroutines-core/test/guide/example-select-05.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002434
2435The result of this code:
2436
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002437```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002438BEGIN
2439Replace
2440END
2441Channel was closed
2442```
2443
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002444<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002445
Roman Elizarov8db17332017-03-09 12:40:45 +03002446## Further reading
2447
2448* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002449* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002450* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2451* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2452
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002453<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002454<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002455[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2456[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2457[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002458[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002459[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002460[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2461[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03002462[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002463[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002464[CoroutineScope.isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/is-active.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002465[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002466[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002467[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2468[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002469[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 +03002470[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2471[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002472[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 +03002473[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2474[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002475[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002476[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002477[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002478[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002479[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2480[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 +03002481[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002482[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002483[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Roman Elizarov3e387b82017-12-04 13:49:11 +03002484[kotlin.coroutines.experimental.CoroutineContext.cancelChildren]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/kotlin.coroutines.experimental.-coroutine-context/cancel-children.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002485[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002486[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 +03002487<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002488[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002489[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2490[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 +03002491[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002492<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002493[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002494[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2495[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2496[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/close.html
Roman Elizarova5e653f2017-02-13 13:49:55 +03002497[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002498[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002499[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Vsevolod Tolstopyatov03d2ff72018-05-29 17:28:20 +03002500[ticker]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/ticker.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002501[ReceiveChannel.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/cancel.html
Vsevolod Tolstopyatov1dbc25e2018-04-18 14:50:26 +03002502[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarovb5328a72018-06-06 18:31:21 +03002503[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 +03002504[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2505[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 +03002506<!--- INDEX kotlinx.coroutines.experimental.selects -->
2507[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002508<!--- END -->