blob: 90ff4be2690755b88a5dcf784ab123c0e05e845a [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/*
3 * Copyright 2016-2017 JetBrains s.r.o.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Roman Elizarovf16fd272017-02-07 11:26:00 +030017
Roman Elizarova5e653f2017-02-13 13:49:55 +030018// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
19package guide.$$1.example$$2
Roman Elizarovf16fd272017-02-07 11:26:00 +030020
Roman Elizarova5e653f2017-02-13 13:49:55 +030021import kotlinx.coroutines.experimental.*
Roman Elizarovf16fd272017-02-07 11:26:00 +030022-->
Roman Elizarove8d79342017-08-29 15:21:21 +030023<!--- KNIT core/kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
24<!--- TEST_OUT core/kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt
Roman Elizarov731f0ad2017-02-22 20:48:45 +030025// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
26package guide.test
27
28import org.junit.Test
29
30class GuideTest {
31-->
Roman Elizarovf16fd272017-02-07 11:26:00 +030032
Roman Elizarov7deefb82017-01-31 10:33:17 +030033# Guide to kotlinx.coroutines by example
34
Roman Elizarova4d45d22017-11-20 16:47:09 +030035This is a guide on core features of `kotlinx.coroutines` with a series of examples.
Roman Elizarov7deefb82017-01-31 10:33:17 +030036
Roman Elizarov2a638922017-03-04 10:22:43 +030037## Introduction and setup
38
39Kotlin, as a language, provides only minimal low-level APIs in its standard library to enable various other
40libraries to utilize coroutines. Unlike many other languages with similar capabilities, `async` and `await`
41are not keywords in Kotlin and are not even part of its standard library.
42
Robert Hencke497d3432017-04-11 00:14:29 -040043`kotlinx.coroutines` is one such rich library. It contains a number of high-level
Roman Elizarova4d45d22017-11-20 16:47:09 +030044coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
Roman Elizarov2a638922017-03-04 10:22:43 +030045You need to add a dependency on `kotlinx-coroutines-core` module as explained
46[here](README.md#using-in-your-projects) to use primitives from this guide in your projects.
47
Roman Elizarov1293ccd2017-02-01 18:49:54 +030048## Table of contents
49
Roman Elizarovfa7723e2017-02-06 11:17:51 +030050<!--- TOC -->
51
Roman Elizarov1293ccd2017-02-01 18:49:54 +030052* [Coroutine basics](#coroutine-basics)
53 * [Your first coroutine](#your-first-coroutine)
54 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
55 * [Waiting for a job](#waiting-for-a-job)
56 * [Extract function refactoring](#extract-function-refactoring)
57 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
58 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
59* [Cancellation and timeouts](#cancellation-and-timeouts)
60 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
61 * [Cancellation is cooperative](#cancellation-is-cooperative)
62 * [Making computation code cancellable](#making-computation-code-cancellable)
63 * [Closing resources with finally](#closing-resources-with-finally)
64 * [Run non-cancellable block](#run-non-cancellable-block)
65 * [Timeout](#timeout)
66* [Composing suspending functions](#composing-suspending-functions)
67 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030068 * [Concurrent using async](#concurrent-using-async)
69 * [Lazily started async](#lazily-started-async)
70 * [Async-style functions](#async-style-functions)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030071* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030072 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030073 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
74 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
75 * [Jumping between threads](#jumping-between-threads)
76 * [Job in the context](#job-in-the-context)
77 * [Children of a coroutine](#children-of-a-coroutine)
78 * [Combining contexts](#combining-contexts)
Roman Elizarov8b38fa22017-09-27 17:44:31 +030079 * [Parental responsibilities](#parental-responsibilities)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030080 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030081 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030082* [Channels](#channels)
83 * [Channel basics](#channel-basics)
84 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
85 * [Building channel producers](#building-channel-producers)
86 * [Pipelines](#pipelines)
87 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
88 * [Fan-out](#fan-out)
89 * [Fan-in](#fan-in)
90 * [Buffered channels](#buffered-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030091 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030092* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
93 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030094 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030095 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030096 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
97 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030098 * [Mutual exclusion](#mutual-exclusion)
99 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300100* [Select expression](#select-expression)
101 * [Selecting from channels](#selecting-from-channels)
102 * [Selecting on close](#selecting-on-close)
103 * [Selecting to send](#selecting-to-send)
104 * [Selecting deferred values](#selecting-deferred-values)
105 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +0300106* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300107
Roman Elizarova5e653f2017-02-13 13:49:55 +0300108<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300109
110## Coroutine basics
111
112This section covers basic coroutine concepts.
113
114### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300115
116Run the following code:
117
118```kotlin
119fun main(args: Array<String>) {
Roman Elizarova4d45d22017-11-20 16:47:09 +0300120 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300121 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
122 println("World!") // print after delay
123 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300124 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300125 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
126}
127```
128
Roman Elizarove8d79342017-08-29 15:21:21 +0300129> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300130
131Run this code:
132
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300133```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300134Hello,
135World!
136```
137
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300138<!--- TEST -->
139
Roman Elizarov419a6c82017-02-09 18:36:22 +0300140Essentially, coroutines are light-weight threads.
141They are launched with [launch] _coroutine builder_.
142You can achieve the same result replacing
Roman Elizarov66f018c2017-09-29 21:39:03 +0300143`launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300144
Roman Elizarov66f018c2017-09-29 21:39:03 +0300145If you start by replacing `launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300146
147```
148Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
149```
150
Roman Elizarov419a6c82017-02-09 18:36:22 +0300151That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300152coroutine and it can be only used from a coroutine.
153
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300154### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300155
Roman Elizarova4d45d22017-11-20 16:47:09 +0300156The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
157It is easy to get lost which one is blocking and which one is not.
158Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300159
160```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300161fun main(args: Array<String>) {
162 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300163 delay(1000L)
164 println("World!")
165 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300166 println("Hello,") // main thread continues here immediately
167 runBlocking { // but this expression blocks the main thread
168 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
169 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300170}
171```
172
Roman Elizarove8d79342017-08-29 15:21:21 +0300173> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300174
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300175<!--- TEST
176Hello,
177World!
178-->
179
Roman Elizarov419a6c82017-02-09 18:36:22 +0300180The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100181The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300182
Roman Elizarova4d45d22017-11-20 16:47:09 +0300183This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
184the execution of the main function:
185
186```kotlin
187fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
188 launch { // launch new coroutine in background and continue
189 delay(1000L)
190 println("World!")
191 }
192 println("Hello,") // main coroutine continues here immediately
193 delay(2000L) // delaying for 2 seconds to keep JVM alive
194}
195```
196
197> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02b.kt)
198
199<!--- TEST
200Hello,
201World!
202-->
203
204Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
205We 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 +0300206
207This is also a way to write unit-tests for suspending functions:
208
209```kotlin
210class MyTest {
211 @Test
212 fun testMySuspendingFunction() = runBlocking<Unit> {
213 // here we can use suspending functions using any assertion style that we like
214 }
215}
216```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300217
218<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300219
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300220### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300221
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300222Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300223wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300224
225```kotlin
226fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300227 val job = launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300228 delay(1000L)
229 println("World!")
230 }
231 println("Hello,")
232 job.join() // wait until child coroutine completes
233}
234```
235
Roman Elizarove8d79342017-08-29 15:21:21 +0300236> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300237
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300238<!--- TEST
239Hello,
240World!
241-->
242
Roman Elizarov7deefb82017-01-31 10:33:17 +0300243Now 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 +0300244the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300245
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300246### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300247
Roman Elizarov66f018c2017-09-29 21:39:03 +0300248Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300249perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
250That is your first _suspending function_. Suspending functions can be used inside coroutines
251just like regular functions, but their additional feature is that they can, in turn,
252use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
253
254```kotlin
255fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300256 val job = launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300257 println("Hello,")
258 job.join()
259}
260
261// this is your first suspending function
262suspend fun doWorld() {
263 delay(1000L)
264 println("World!")
265}
266```
267
Roman Elizarove8d79342017-08-29 15:21:21 +0300268> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300269
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300270<!--- TEST
271Hello,
272World!
273-->
274
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300275### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300276
277Run the following code:
278
279```kotlin
280fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300281 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
282 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300283 delay(1000L)
284 print(".")
285 }
286 }
287 jobs.forEach { it.join() } // wait for all jobs to complete
288}
289```
290
Roman Elizarove8d79342017-08-29 15:21:21 +0300291> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300292
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300293<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
294
Roman Elizarov66f018c2017-09-29 21:39:03 +0300295It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300296Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
297
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300298### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300299
300The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300301returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300302
303```kotlin
304fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300305 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300306 repeat(1000) { i ->
307 println("I'm sleeping $i ...")
308 delay(500L)
309 }
310 }
311 delay(1300L) // just quit after delay
312}
313```
314
Roman Elizarove8d79342017-08-29 15:21:21 +0300315> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300316
317You can run and see that it prints three lines and terminates:
318
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300319```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300320I'm sleeping 0 ...
321I'm sleeping 1 ...
322I'm sleeping 2 ...
323```
324
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300325<!--- TEST -->
326
Roman Elizarov7deefb82017-01-31 10:33:17 +0300327Active coroutines do not keep the process alive. They are like daemon threads.
328
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300329## Cancellation and timeouts
330
331This section covers coroutine cancellation and timeouts.
332
333### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300334
335In small application the return from "main" method might sound like a good idea to get all coroutines
336implicitly terminated. In a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300337The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300338
339```kotlin
340fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300341 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300342 repeat(1000) { i ->
343 println("I'm sleeping $i ...")
344 delay(500L)
345 }
346 }
347 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300348 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300349 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300350 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300351 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300352}
353```
354
Roman Elizarove8d79342017-08-29 15:21:21 +0300355> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300356
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300357It produces the following output:
358
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300359```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300360I'm sleeping 0 ...
361I'm sleeping 1 ...
362I'm sleeping 2 ...
363main: I'm tired of waiting!
364main: Now I can quit.
365```
366
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300367<!--- TEST -->
368
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300369As 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 +0300370There is also a [Job] extension function [cancelAndJoin]
371that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300372
373### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300374
Tair Rzayevaf734622017-02-01 22:30:16 +0200375Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300376All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300377coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300378a computation and does not check for cancellation, then it cannot be cancelled, like the following
379example shows:
380
381```kotlin
382fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700383 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300384 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700385 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300386 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300387 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700388 // print a message twice a second
389 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300390 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300391 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300392 }
393 }
394 }
395 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300396 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300397 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300398 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300399}
400```
401
Roman Elizarove8d79342017-08-29 15:21:21 +0300402> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300403
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300404Run it to see that it continues to print "I'm sleeping" even after cancellation
405until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300406
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300407<!--- TEST
408I'm sleeping 0 ...
409I'm sleeping 1 ...
410I'm sleeping 2 ...
411main: I'm tired of waiting!
412I'm sleeping 3 ...
413I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300414main: Now I can quit.
415-->
416
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300417### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300418
419There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300420invoke 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 +0300421The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300422
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300423Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300424
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300425```kotlin
426fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700427 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300428 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700429 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300430 var i = 0
431 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700432 // print a message twice a second
433 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300434 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700435 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300436 }
437 }
438 }
439 delay(1300L) // delay a bit
440 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300441 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300442 println("main: Now I can quit.")
443}
444```
445
Roman Elizarove8d79342017-08-29 15:21:21 +0300446> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300447
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300448As 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 +0300449the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300450
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300451<!--- TEST
452I'm sleeping 0 ...
453I'm sleeping 1 ...
454I'm sleeping 2 ...
455main: I'm tired of waiting!
456main: Now I can quit.
457-->
458
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300459### Closing resources with finally
460
Roman Elizarov419a6c82017-02-09 18:36:22 +0300461Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarov66f018c2017-09-29 21:39:03 +0300462all the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300463finalization actions normally when coroutine is cancelled:
464
465```kotlin
466fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300467 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300468 try {
469 repeat(1000) { i ->
470 println("I'm sleeping $i ...")
471 delay(500L)
472 }
473 } finally {
474 println("I'm running finally")
475 }
476 }
477 delay(1300L) // delay a bit
478 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300479 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300480 println("main: Now I can quit.")
481}
482```
483
Roman Elizarove8d79342017-08-29 15:21:21 +0300484> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300485
Roman Elizarov88396732017-09-27 21:30:47 +0300486Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
487so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300488
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300489```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300490I'm sleeping 0 ...
491I'm sleeping 1 ...
492I'm sleeping 2 ...
493main: I'm tired of waiting!
494I'm running finally
495main: Now I can quit.
496```
497
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300498<!--- TEST -->
499
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300500### Run non-cancellable block
501
502Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300503[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300504problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
505communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
506rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300507`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300508
509```kotlin
510fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300511 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300512 try {
513 repeat(1000) { i ->
514 println("I'm sleeping $i ...")
515 delay(500L)
516 }
517 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300518 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300519 println("I'm running finally")
520 delay(1000L)
521 println("And I've just delayed for 1 sec because I'm non-cancellable")
522 }
523 }
524 }
525 delay(1300L) // delay a bit
526 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300527 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300528 println("main: Now I can quit.")
529}
530```
531
Roman Elizarove8d79342017-08-29 15:21:21 +0300532> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300533
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300534<!--- TEST
535I'm sleeping 0 ...
536I'm sleeping 1 ...
537I'm sleeping 2 ...
538main: I'm tired of waiting!
539I'm running finally
540And I've just delayed for 1 sec because I'm non-cancellable
541main: Now I can quit.
542-->
543
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300544### Timeout
545
546The most obvious reason to cancel coroutine execution in practice,
547is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300548While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
549the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300550Look at the following example:
551
552```kotlin
553fun main(args: Array<String>) = runBlocking<Unit> {
554 withTimeout(1300L) {
555 repeat(1000) { i ->
556 println("I'm sleeping $i ...")
557 delay(500L)
558 }
559 }
560}
561```
562
Roman Elizarove8d79342017-08-29 15:21:21 +0300563> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300564
565It produces the following output:
566
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300567```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300568I'm sleeping 0 ...
569I'm sleeping 1 ...
570I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300571Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300572```
573
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300574<!--- TEST STARTS_WITH -->
575
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300576The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300577We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300578inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300579However, in this example we have used `withTimeout` right inside the `main` function.
580
581Because cancellation is just an exception, all the resources will be closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300582You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
583you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300584that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
585
586```kotlin
587fun main(args: Array<String>) = runBlocking<Unit> {
588 val result = withTimeoutOrNull(1300L) {
589 repeat(1000) { i ->
590 println("I'm sleeping $i ...")
591 delay(500L)
592 }
593 "Done" // will get cancelled before it produces this result
594 }
595 println("Result is $result")
596}
597```
598
599> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-07.kt)
600
601There is no longer an exception when running this code:
602
603```text
604I'm sleeping 0 ...
605I'm sleeping 1 ...
606I'm sleeping 2 ...
607Result is null
608```
609
610<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300611
612## Composing suspending functions
613
614This section covers various approaches to composition of suspending functions.
615
616### Sequential by default
617
618Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300619remote service call or computation. We just pretend they are useful, but actually each one just
620delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300621
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300622<!--- INCLUDE .*/example-compose-([0-9]+).kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300623import kotlin.system.*
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300624-->
625
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300626```kotlin
627suspend fun doSomethingUsefulOne(): Int {
628 delay(1000L) // pretend we are doing something useful here
629 return 13
630}
631
632suspend fun doSomethingUsefulTwo(): Int {
633 delay(1000L) // pretend we are doing something useful here, too
634 return 29
635}
636```
637
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300638<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
639
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300640What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
641`doSomethingUsefulTwo` and compute the sum of their results?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200642In 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 +0300643to invoke the second one or to decide on how to invoke it.
644
645We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300646code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300647time it takes to execute both suspending functions:
648
649```kotlin
650fun main(args: Array<String>) = runBlocking<Unit> {
651 val time = measureTimeMillis {
652 val one = doSomethingUsefulOne()
653 val two = doSomethingUsefulTwo()
654 println("The answer is ${one + two}")
655 }
656 println("Completed in $time ms")
657}
658```
659
Roman Elizarove8d79342017-08-29 15:21:21 +0300660> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300661
662It produces something like this:
663
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300664```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300665The answer is 42
666Completed in 2017 ms
667```
668
Roman Elizarov35d2c342017-07-20 14:54:39 +0300669<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300670
Roman Elizarov32d95322017-02-09 15:57:31 +0300671### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300672
673What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300674we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300675
Roman Elizarov419a6c82017-02-09 18:36:22 +0300676Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
677that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
678does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300679that 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 +0300680but `Deferred` is also a `Job`, so you can cancel it if needed.
681
682```kotlin
683fun main(args: Array<String>) = runBlocking<Unit> {
684 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300685 val one = async { doSomethingUsefulOne() }
686 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300687 println("The answer is ${one.await() + two.await()}")
688 }
689 println("Completed in $time ms")
690}
691```
692
Roman Elizarove8d79342017-08-29 15:21:21 +0300693> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300694
695It produces something like this:
696
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300697```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300698The answer is 42
699Completed in 1017 ms
700```
701
Roman Elizarov35d2c342017-07-20 14:54:39 +0300702<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300703
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300704This is twice as fast, because we have concurrent execution of two coroutines.
705Note, that concurrency with coroutines is always explicit.
706
Roman Elizarov32d95322017-02-09 15:57:31 +0300707### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300708
Roman Elizarov66f018c2017-09-29 21:39:03 +0300709There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300710It starts coroutine only when its result is needed by some
711[await][Deferred.await] or if a [start][Job.start] function
Roman Elizarov32d95322017-02-09 15:57:31 +0300712is invoked. Run the following example that differs from the previous one only by this option:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300713
714```kotlin
715fun main(args: Array<String>) = runBlocking<Unit> {
716 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300717 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
718 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300719 println("The answer is ${one.await() + two.await()}")
720 }
721 println("Completed in $time ms")
722}
723```
724
Roman Elizarove8d79342017-08-29 15:21:21 +0300725> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300726
727It produces something like this:
728
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300729```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300730The answer is 42
731Completed in 2017 ms
732```
733
Roman Elizarov35d2c342017-07-20 14:54:39 +0300734<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300735
Roman Elizarov32d95322017-02-09 15:57:31 +0300736So, we are back to sequential execution, because we _first_ start and await for `one`, _and then_ start and await
737for `two`. It is not the intended use-case for laziness. It is designed as a replacement for
738the standard `lazy` function in cases when computation of the value involves suspending functions.
739
740### Async-style functions
741
742We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300743_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100744"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
745to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300746
747```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100748// The result type of somethingUsefulOneAsync is Deferred<Int>
749fun somethingUsefulOneAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300750 doSomethingUsefulOne()
751}
752
Marcin Moskała7e94e702018-01-29 18:39:02 +0100753// The result type of somethingUsefulTwoAsync is Deferred<Int>
754fun somethingUsefulTwoAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300755 doSomethingUsefulTwo()
756}
757```
758
Marcin Moskała7e94e702018-01-29 18:39:02 +0100759Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300760However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
761with the invoking code.
762
763The following example shows their use outside of coroutine:
764
765```kotlin
766// note, that we don't have `runBlocking` to the right of `main` in this example
767fun main(args: Array<String>) {
768 val time = measureTimeMillis {
769 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100770 val one = somethingUsefulOneAsync()
771 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300772 // but waiting for a result must involve either suspending or blocking.
773 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
774 runBlocking {
775 println("The answer is ${one.await() + two.await()}")
776 }
777 }
778 println("Completed in $time ms")
779}
780```
781
Roman Elizarove8d79342017-08-29 15:21:21 +0300782> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300783
Roman Elizarov35d2c342017-07-20 14:54:39 +0300784<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300785The answer is 42
786Completed in 1085 ms
787-->
788
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300789## Coroutine context and dispatchers
790
Roman Elizarov66f018c2017-09-29 21:39:03 +0300791Coroutines always execute in some context which is represented by the value of
792[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
793type, defined in the Kotlin standard library.
794
795The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
796which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300797
798### Dispatchers and threads
799
Roman Elizarov66f018c2017-09-29 21:39:03 +0300800Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300801the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +0300802to a specific thread, dispatch it to a thread pool, or let it run unconfined.
803
804All coroutines builders like [launch] and [async] accept an optional
805[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
806parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
807
808Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300809
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300810<!--- INCLUDE
811import kotlin.coroutines.experimental.*
812-->
813
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300814```kotlin
815fun main(args: Array<String>) = runBlocking<Unit> {
816 val jobs = arrayListOf<Job>()
817 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300818 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300819 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300820 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
821 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300822 }
823 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300824 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300825 }
826 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300827 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300828 }
829 jobs.forEach { it.join() }
830}
831```
832
Roman Elizarove8d79342017-08-29 15:21:21 +0300833> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300834
835It produces the following output (maybe in different order):
836
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300837```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300838 'Unconfined': I'm working in thread main
839 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
840 'newSTC': I'm working in thread MyOwnThread
841'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300842```
843
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300844<!--- TEST LINES_START_UNORDERED -->
845
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800846The default dispatcher that we've used in previous sections is representend by [DefaultDispatcher], which
Roman Elizarov66f018c2017-09-29 21:39:03 +0300847is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same
Charles Muchenefa13beb2018-01-08 16:56:54 +0300848as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300849
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300850The difference between parent
851[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html) and
Roman Elizarov43e3af72017-07-21 16:01:31 +0300852[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300853
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800854Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource.
855In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
856function, or stored in a top-level variable and reused throughout the application.
857
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300858### Unconfined vs confined dispatcher
859
Roman Elizarov419a6c82017-02-09 18:36:22 +0300860The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300861first suspension point. After suspension it resumes in the thread that is fully determined by the
862suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
863consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
864
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300865On the other side,
866[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
867property, that is available inside any coroutine, is a reference to a context of this particular coroutine.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300868This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
869is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300870this thread with a predictable FIFO scheduling.
871
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300872<!--- INCLUDE
873import kotlin.coroutines.experimental.*
874-->
875
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300876```kotlin
877fun main(args: Array<String>) = runBlocking<Unit> {
878 val jobs = arrayListOf<Job>()
879 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300880 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300881 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300882 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300883 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300884 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
885 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300886 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300887 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300888 }
889 jobs.forEach { it.join() }
890}
891```
892
Roman Elizarove8d79342017-08-29 15:21:21 +0300893> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300894
895Produces the output:
896
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300897```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300898 'Unconfined': I'm working in thread main
899'coroutineContext': I'm working in thread main
900 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
901'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300902```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300903
904<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300905
Roman Elizarov43e3af72017-07-21 16:01:31 +0300906So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
907in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
908function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300909
910### Debugging coroutines and threads
911
Roman Elizarov419a6c82017-02-09 18:36:22 +0300912Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
Roman Elizarov66f018c2017-09-29 21:39:03 +0300913with a default multi-threaded dispatcher. Even with a single-threaded dispatcher it might be hard to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300914figure out what coroutine was doing what, where, and when. The common approach to debugging applications with
915threads is to print the thread name in the log file on each log statement. This feature is universally supported
916by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
917`kotlinx.coroutines` includes debugging facilities to make it easier.
918
919Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
920
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300921<!--- INCLUDE
922import kotlin.coroutines.experimental.*
923-->
924
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300925```kotlin
926fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
927
928fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300929 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300930 log("I'm computing a piece of the answer")
931 6
932 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300933 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300934 log("I'm computing another piece of the answer")
935 7
936 }
937 log("The answer is ${a.await() * b.await()}")
938}
939```
940
Roman Elizarove8d79342017-08-29 15:21:21 +0300941> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300942
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300943There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300944and two coroutines computing deferred values `a` (#2) and `b` (#3).
945They are all executing in the context of `runBlocking` and are confined to the main thread.
946The output of this code is:
947
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300948```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300949[main @coroutine#2] I'm computing a piece of the answer
950[main @coroutine#3] I'm computing another piece of the answer
951[main @coroutine#1] The answer is 42
952```
953
Kirill Timofeeva5186962017-10-25 14:25:47 +0300954<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300955
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300956The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
957thread, but the identifier of the currently executing coroutine is appended to it. This identifier
958is consecutively assigned to all created coroutines when debugging mode is turned on.
959
Roman Elizarov419a6c82017-02-09 18:36:22 +0300960You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300961
962### Jumping between threads
963
964Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
965
966```kotlin
967fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
968
969fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800970 newSingleThreadContext("Ctx1").use { ctx1 ->
971 newSingleThreadContext("Ctx2").use { ctx2 ->
972 runBlocking(ctx1) {
973 log("Started in ctx1")
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300974 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800975 log("Working in ctx2")
976 }
977 log("Back to ctx1")
978 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300979 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300980 }
981}
982```
983
Roman Elizarove8d79342017-08-29 15:21:21 +0300984> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300985
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800986It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300987the 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 +0300988same coroutine as you can see in the output below:
989
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300990```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300991[Ctx1 @coroutine#1] Started in ctx1
992[Ctx2 @coroutine#1] Working in ctx2
993[Ctx1 @coroutine#1] Back to ctx1
994```
995
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300996<!--- TEST -->
997
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800998
Artsiom Chapialioue185ed62018-06-03 19:34:22 -0400999Note, that this example also uses `use` function from the Kotlin standard library to release threads that
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08001000are created with [newSingleThreadContext] when they are no longer needed.
1001
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001002### Job in the context
1003
Roman Elizarov66f018c2017-09-29 21:39:03 +03001004The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001005using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001006
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001007<!--- INCLUDE
1008import kotlin.coroutines.experimental.*
1009-->
1010
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001011```kotlin
1012fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001013 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001014}
1015```
1016
Roman Elizarove8d79342017-08-29 15:21:21 +03001017> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001018
Roman Elizarov66f018c2017-09-29 21:39:03 +03001019It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001020
1021```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001022My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001023```
1024
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001025<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001026
Roman Elizarov43e3af72017-07-21 16:01:31 +03001027So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001028`coroutineContext[Job]?.isActive == true`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001029
1030### Children of a coroutine
1031
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001032When
1033[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html)
1034of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +03001035the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001036a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1037are recursively cancelled, too.
1038
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001039<!--- INCLUDE
1040import kotlin.coroutines.experimental.*
1041-->
1042
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001043```kotlin
1044fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001045 // launch a coroutine to process some kind of incoming request
1046 val request = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001047 // it spawns two other jobs, one with its separate context
Roman Elizarov66f018c2017-09-29 21:39:03 +03001048 val job1 = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001049 println("job1: I have my own context and execute independently!")
1050 delay(1000)
1051 println("job1: I am not affected by cancellation of the request")
1052 }
1053 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001054 val job2 = launch(coroutineContext) {
Roman Elizarov74619c12017-11-09 10:32:15 +03001055 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001056 println("job2: I am a child of the request coroutine")
1057 delay(1000)
1058 println("job2: I will not execute this line if my parent request is cancelled")
1059 }
1060 // request completes when both its sub-jobs complete:
1061 job1.join()
1062 job2.join()
1063 }
1064 delay(500)
1065 request.cancel() // cancel processing of the request
1066 delay(1000) // delay a second to see what happens
1067 println("main: Who has survived request cancellation?")
1068}
1069```
1070
Roman Elizarove8d79342017-08-29 15:21:21 +03001071> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001072
1073The output of this code is:
1074
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001075```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001076job1: I have my own context and execute independently!
1077job2: I am a child of the request coroutine
1078job1: I am not affected by cancellation of the request
1079main: Who has survived request cancellation?
1080```
1081
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001082<!--- TEST -->
1083
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001084### Combining contexts
1085
Roman Elizarov66f018c2017-09-29 21:39:03 +03001086Coroutine contexts can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +03001087of 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 +03001088its dispatcher replaced:
1089
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001090<!--- INCLUDE
1091import kotlin.coroutines.experimental.*
1092-->
1093
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001094```kotlin
1095fun main(args: Array<String>) = runBlocking<Unit> {
1096 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +03001097 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001098 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +03001099 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001100 println("job: I am a child of the request coroutine, but with a different dispatcher")
1101 delay(1000)
1102 println("job: I will not execute this line if my parent request is cancelled")
1103 }
1104 job.join() // request completes when its sub-job completes
1105 }
1106 delay(500)
1107 request.cancel() // cancel processing of the request
1108 delay(1000) // delay a second to see what happens
1109 println("main: Who has survived request cancellation?")
1110}
1111```
1112
Roman Elizarove8d79342017-08-29 15:21:21 +03001113> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001114
1115The expected outcome of this code is:
1116
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001117```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001118job: I am a child of the request coroutine, but with a different dispatcher
1119main: Who has survived request cancellation?
1120```
1121
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001122<!--- TEST -->
1123
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001124### Parental responsibilities
1125
1126A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001127all 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 +03001128
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001129<!--- INCLUDE
1130import kotlin.coroutines.experimental.*
1131-->
1132
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001133```kotlin
1134fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001135 // launch a coroutine to process some kind of incoming request
1136 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001137 repeat(3) { i -> // launch a few children jobs
1138 launch(coroutineContext) {
1139 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1140 println("Coroutine $i is done")
1141 }
1142 }
1143 println("request: I'm done and I don't explicitly join my children that are still active")
1144 }
1145 request.join() // wait for completion of the request, including all its children
1146 println("Now processing of the request is complete")
1147}
1148```
1149
1150> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt)
1151
1152The result is going to be:
1153
1154```text
1155request: I'm done and I don't explicitly join my children that are still active
1156Coroutine 0 is done
1157Coroutine 1 is done
1158Coroutine 2 is done
1159Now processing of the request is complete
1160```
1161
1162<!--- TEST -->
1163
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001164### Naming coroutines for debugging
1165
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001166Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001167coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1168or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001169[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1170is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001171
1172The following example demonstrates this concept:
1173
1174```kotlin
1175fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1176
1177fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1178 log("Started main coroutine")
1179 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001180 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001181 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001182 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001183 252
1184 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001185 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001186 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001187 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001188 6
1189 }
1190 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1191}
1192```
1193
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001194> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-09.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001195
1196The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1197
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001198```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001199[main @main#1] Started main coroutine
1200[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1201[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1202[main @main#1] The answer for v1 / v2 = 42
1203```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001204
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001205<!--- TEST FLEXIBLE_THREAD -->
1206
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001207### Cancellation via explicit job
1208
1209Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1210an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1211and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1212and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1213to avoid memory leaks.
1214
1215We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
Roman Elizarov88396732017-09-27 21:30:47 +03001216the lifecycle of our activity. A job instance is created using [Job()] factory function
Roman Elizarove8f694e2017-11-28 10:12:00 +03001217as the following example shows. For convenience, rather than using `launch(coroutineContext + job)` expression,
1218we can write `launch(coroutineContext, parent = job)` to make explicit the fact that the parent job is being used.
1219
1220Now, a single invocation of [Job.cancel] cancels all the children we've launched.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001221Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1222this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001223
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001224<!--- INCLUDE
1225import kotlin.coroutines.experimental.*
1226-->
1227
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001228```kotlin
1229fun main(args: Array<String>) = runBlocking<Unit> {
1230 val job = Job() // create a job object to manage our lifecycle
1231 // now launch ten coroutines for a demo, each working for a different time
1232 val coroutines = List(10) { i ->
1233 // they are all children of our job object
Roman Elizarove8f694e2017-11-28 10:12:00 +03001234 launch(coroutineContext, parent = job) { // we use the context of main runBlocking thread, but with our parent job
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001235 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001236 println("Coroutine $i is done")
1237 }
1238 }
1239 println("Launched ${coroutines.size} coroutines")
1240 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001241 println("Cancelling the job!")
1242 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001243}
1244```
1245
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001246> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-10.kt)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001247
1248The output of this example is:
1249
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001250```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001251Launched 10 coroutines
1252Coroutine 0 is done
1253Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001254Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001255```
1256
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001257<!--- TEST -->
1258
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001259As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001260by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001261application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001262and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1263since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1264resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001265
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001266## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001267
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001268Deferred values provide a convenient way to transfer a single value between coroutines.
1269Channels provide a way to transfer a stream of values.
1270
1271<!--- INCLUDE .*/example-channel-([0-9]+).kt
1272import kotlinx.coroutines.experimental.channels.*
1273-->
1274
1275### Channel basics
1276
Roman Elizarov419a6c82017-02-09 18:36:22 +03001277A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1278instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1279a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001280
1281```kotlin
1282fun main(args: Array<String>) = runBlocking<Unit> {
1283 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001284 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001285 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1286 for (x in 1..5) channel.send(x * x)
1287 }
1288 // here we print five received integers:
1289 repeat(5) { println(channel.receive()) }
1290 println("Done!")
1291}
1292```
1293
Roman Elizarove8d79342017-08-29 15:21:21 +03001294> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-01.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001295
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001296The output of this code is:
1297
1298```text
12991
13004
13019
130216
130325
1304Done!
1305```
1306
1307<!--- TEST -->
1308
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001309### Closing and iteration over channels
1310
1311Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1312On the receiver side it is convenient to use a regular `for` loop to receive elements
1313from the channel.
1314
Roman Elizarov419a6c82017-02-09 18:36:22 +03001315Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001316The iteration stops as soon as this close token is received, so there is a guarantee
1317that all previously sent elements before the close are received:
1318
1319```kotlin
1320fun main(args: Array<String>) = runBlocking<Unit> {
1321 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001322 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001323 for (x in 1..5) channel.send(x * x)
1324 channel.close() // we're done sending
1325 }
1326 // here we print received values using `for` loop (until the channel is closed)
1327 for (y in channel) println(y)
1328 println("Done!")
1329}
1330```
1331
Roman Elizarove8d79342017-08-29 15:21:21 +03001332> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001333
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001334<!--- TEST
13351
13364
13379
133816
133925
1340Done!
1341-->
1342
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001343### Building channel producers
1344
Roman Elizarova5e653f2017-02-13 13:49:55 +03001345The pattern where a coroutine is producing a sequence of elements is quite common.
1346This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001347You 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 +03001348to common sense that results must be returned from functions.
1349
Roman Elizarov86349be2017-03-17 16:47:37 +03001350There 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 +03001351and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001352
1353```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001354fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001355 for (x in 1..5) send(x * x)
1356}
1357
1358fun main(args: Array<String>) = runBlocking<Unit> {
1359 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001360 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001361 println("Done!")
1362}
1363```
1364
Roman Elizarove8d79342017-08-29 15:21:21 +03001365> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-03.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001366
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001367<!--- TEST
13681
13694
13709
137116
137225
1373Done!
1374-->
1375
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001376### Pipelines
1377
Roman Elizarov66f018c2017-09-29 21:39:03 +03001378A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001379
1380```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001381fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001382 var x = 1
1383 while (true) send(x++) // infinite stream of integers starting from 1
1384}
1385```
1386
Roman Elizarova5e653f2017-02-13 13:49:55 +03001387And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001388In the below example the numbers are just squared:
1389
1390```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001391fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001392 for (x in numbers) send(x * x)
1393}
1394```
1395
Roman Elizarova5e653f2017-02-13 13:49:55 +03001396The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001397
1398```kotlin
1399fun main(args: Array<String>) = runBlocking<Unit> {
1400 val numbers = produceNumbers() // produces integers from 1 and on
1401 val squares = square(numbers) // squares integers
1402 for (i in 1..5) println(squares.receive()) // print first five
1403 println("Done!") // we are done
1404 squares.cancel() // need to cancel these coroutines in a larger app
1405 numbers.cancel()
1406}
1407```
1408
Roman Elizarove8d79342017-08-29 15:21:21 +03001409> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-04.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001410
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001411<!--- TEST
14121
14134
14149
141516
141625
1417Done!
1418-->
1419
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001420We don't have to cancel these coroutines in this example app, because
1421[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1422but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1423Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001424[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001425
1426### Prime numbers with pipeline
1427
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001428Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001429of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001430explicit `context` parameter and pass it to [produce] builder,
1431so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001432
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001433<!--- INCLUDE
1434import kotlin.coroutines.experimental.*
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001435-->
1436
1437```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001438fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001439 var x = start
1440 while (true) send(x++) // infinite stream of integers from start
1441}
1442```
1443
1444The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1445that are divisible by the given prime number:
1446
1447```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001448fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001449 for (x in numbers) if (x % prime != 0) send(x)
1450}
1451```
1452
1453Now 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 +03001454and launching new pipeline stage for each prime number found:
1455
1456```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001457numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001458```
1459
1460The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001461running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001462children of the main [runBlocking] coroutine in its
1463[coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/coroutine-context.html),
1464we don't have to keep an explicit list of all the coroutines we have started.
Roman Elizarov3e387b82017-12-04 13:49:11 +03001465We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
1466extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001467
1468```kotlin
1469fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001470 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001471 for (i in 1..10) {
1472 val prime = cur.receive()
1473 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001474 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001475 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001476 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001477}
1478```
1479
Roman Elizarove8d79342017-08-29 15:21:21 +03001480> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001481
1482The output of this code is:
1483
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001484```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030014852
14863
14875
14887
148911
149013
149117
149219
149323
149429
1495```
1496
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001497<!--- TEST -->
1498
Roman Elizarov66f018c2017-09-29 21:39:03 +03001499Note, that you can build the same pipeline using
1500[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1501coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001502Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001503`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1504However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1505multiple CPU cores if you run it in [CommonPool] context.
1506
Roman Elizarova5e653f2017-02-13 13:49:55 +03001507Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001508other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1509built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001510`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001511
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001512### Fan-out
1513
1514Multiple coroutines may receive from the same channel, distributing work between themselves.
1515Let us start with a producer coroutine that is periodically producing integers
1516(ten numbers per second):
1517
1518```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001519fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001520 var x = 1 // start from 1
1521 while (true) {
1522 send(x++) // produce next
1523 delay(100) // wait 0.1s
1524 }
1525}
1526```
1527
1528Then we can have several processor coroutines. In this example, they just print their id and
1529received number:
1530
1531```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001532fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
Roman Elizarov86349be2017-03-17 16:47:37 +03001533 channel.consumeEach {
1534 println("Processor #$id received $it")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001535 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001536}
1537```
1538
Roman Elizarov35d2c342017-07-20 14:54:39 +03001539Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001540
1541```kotlin
1542fun main(args: Array<String>) = runBlocking<Unit> {
1543 val producer = produceNumbers()
1544 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001545 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001546 producer.cancel() // cancel producer coroutine and thus kill them all
1547}
1548```
1549
Roman Elizarove8d79342017-08-29 15:21:21 +03001550> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-06.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001551
1552The output will be similar to the the following one, albeit the processor ids that receive
1553each specific integer may be different:
1554
1555```
1556Processor #2 received 1
1557Processor #4 received 2
1558Processor #0 received 3
1559Processor #1 received 4
1560Processor #3 received 5
1561Processor #2 received 6
1562Processor #4 received 7
1563Processor #0 received 8
1564Processor #1 received 9
1565Processor #3 received 10
1566```
1567
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001568<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1569
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001570Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1571over the channel that processor coroutines are doing.
1572
1573### Fan-in
1574
1575Multiple coroutines may send to the same channel.
1576For example, let us have a channel of strings, and a suspending function that
1577repeatedly sends a specified string to this channel with a specified delay:
1578
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001579<!--- INCLUDE
1580import kotlin.coroutines.experimental.*
1581-->
1582
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001583```kotlin
1584suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1585 while (true) {
1586 delay(time)
1587 channel.send(s)
1588 }
1589}
1590```
1591
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001592Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001593(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 +03001594
1595```kotlin
1596fun main(args: Array<String>) = runBlocking<Unit> {
1597 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001598 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1599 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001600 repeat(6) { // receive first six
1601 println(channel.receive())
1602 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001603 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001604}
1605```
1606
Roman Elizarove8d79342017-08-29 15:21:21 +03001607> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001608
1609The output is:
1610
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001611```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001612foo
1613foo
1614BAR!
1615foo
1616foo
1617BAR!
1618```
1619
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001620<!--- TEST -->
1621
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001622### Buffered channels
1623
1624The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1625meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1626if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001627
Roman Elizarov88396732017-09-27 21:30:47 +03001628Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001629specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1630similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1631
1632Take a look at the behavior of the following code:
1633
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001634<!--- INCLUDE
1635import kotlin.coroutines.experimental.*
1636-->
1637
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001638```kotlin
1639fun main(args: Array<String>) = runBlocking<Unit> {
1640 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001641 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001642 repeat(10) {
1643 println("Sending $it") // print before sending each element
1644 channel.send(it) // will suspend when buffer is full
1645 }
1646 }
1647 // don't receive anything... just wait....
1648 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001649 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001650}
1651```
1652
Roman Elizarove8d79342017-08-29 15:21:21 +03001653> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001654
1655It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1656
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001657```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001658Sending 0
1659Sending 1
1660Sending 2
1661Sending 3
1662Sending 4
1663```
1664
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001665<!--- TEST -->
1666
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001667The 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 +03001668
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001669### Channels are fair
1670
1671Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1672multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1673gets the element. In the following example two coroutines "ping" and "pong" are
1674receiving the "ball" object from the shared "table" channel.
1675
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001676<!--- INCLUDE
1677import kotlin.coroutines.experimental.*
1678-->
1679
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001680```kotlin
1681data class Ball(var hits: Int)
1682
1683fun main(args: Array<String>) = runBlocking<Unit> {
1684 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001685 launch(coroutineContext) { player("ping", table) }
1686 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001687 table.send(Ball(0)) // serve the ball
1688 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001689 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001690}
1691
1692suspend fun player(name: String, table: Channel<Ball>) {
1693 for (ball in table) { // receive the ball in a loop
1694 ball.hits++
1695 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001696 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001697 table.send(ball) // send the ball back
1698 }
1699}
1700```
1701
Roman Elizarove8d79342017-08-29 15:21:21 +03001702> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001703
1704The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1705coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1706received by the "pong" coroutine, because it was already waiting for it:
1707
1708```text
1709ping Ball(hits=1)
1710pong Ball(hits=2)
1711ping Ball(hits=3)
1712pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001713```
1714
1715<!--- TEST -->
1716
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001717Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
1718that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
1719
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001720## Shared mutable state and concurrency
1721
Roman Elizarov66f018c2017-09-29 21:39:03 +03001722Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001723all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1724Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1725but others are unique.
1726
1727### The problem
1728
Roman Elizarov1e459602017-02-27 11:05:17 +03001729Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1730We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001731
Roman Elizarov1e459602017-02-27 11:05:17 +03001732<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001733import java.util.concurrent.atomic.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001734-->
1735
Roman Elizarov1e459602017-02-27 11:05:17 +03001736<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001737import kotlinx.coroutines.experimental.sync.*
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001738-->
1739
Roman Elizarov1e459602017-02-27 11:05:17 +03001740<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001741import kotlinx.coroutines.experimental.channels.*
1742-->
1743
Roman Elizarov9fe5f462018-02-21 19:05:52 +03001744<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
1745import kotlin.system.*
1746import kotlin.coroutines.experimental.*
1747-->
1748
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001749```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001750suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1751 val n = 1000 // number of coroutines to launch
1752 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001753 val time = measureTimeMillis {
1754 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001755 launch(context) {
1756 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001757 }
1758 }
1759 jobs.forEach { it.join() }
1760 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001761 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001762}
1763```
1764
Roman Elizarov43e90112017-05-10 11:25:20 +03001765<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001766
Roman Elizarov1e459602017-02-27 11:05:17 +03001767We start with a very simple action that increments a shared mutable variable using
1768multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001769
1770```kotlin
1771var counter = 0
1772
1773fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001774 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001775 counter++
1776 }
1777 println("Counter = $counter")
1778}
1779```
1780
Roman Elizarove8d79342017-08-29 15:21:21 +03001781> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001782
Roman Elizarov1e459602017-02-27 11:05:17 +03001783<!--- TEST LINES_START
1784Completed 1000000 actions in
1785Counter =
1786-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001787
Roman Elizarov1e459602017-02-27 11:05:17 +03001788What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1789increment the `counter` concurrently from multiple threads without any synchronization.
1790
Roman Elizarov43e90112017-05-10 11:25:20 +03001791> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1792`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1793following change:
1794
1795```kotlin
1796val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1797var counter = 0
1798
1799fun main(args: Array<String>) = runBlocking<Unit> {
1800 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1801 counter++
1802 }
1803 println("Counter = $counter")
1804}
1805```
1806
Roman Elizarove8d79342017-08-29 15:21:21 +03001807> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt)
Roman Elizarov43e90112017-05-10 11:25:20 +03001808
1809<!--- TEST LINES_START
1810Completed 1000000 actions in
1811Counter =
1812-->
1813
Roman Elizarov1e459602017-02-27 11:05:17 +03001814### Volatiles are of no help
1815
1816There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1817
1818```kotlin
1819@Volatile // in Kotlin `volatile` is an annotation
1820var counter = 0
1821
1822fun main(args: Array<String>) = runBlocking<Unit> {
1823 massiveRun(CommonPool) {
1824 counter++
1825 }
1826 println("Counter = $counter")
1827}
1828```
1829
Roman Elizarove8d79342017-08-29 15:21:21 +03001830> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001831
1832<!--- TEST LINES_START
1833Completed 1000000 actions in
1834Counter =
1835-->
1836
1837This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1838linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1839do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001840
1841### Thread-safe data structures
1842
1843The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1844linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1845operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001846In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001847
1848```kotlin
1849var counter = AtomicInteger()
1850
1851fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001852 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001853 counter.incrementAndGet()
1854 }
1855 println("Counter = ${counter.get()}")
1856}
1857```
1858
Roman Elizarove8d79342017-08-29 15:21:21 +03001859> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001860
Roman Elizarov1e459602017-02-27 11:05:17 +03001861<!--- TEST ARBITRARY_TIME
1862Completed 1000000 actions in xxx ms
1863Counter = 1000000
1864-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001865
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001866This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1867standard data structures and basic operations on them. However, it does not easily scale to complex
1868state or to complex operations that do not have ready-to-use thread-safe implementations.
1869
Roman Elizarov1e459602017-02-27 11:05:17 +03001870### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001871
Roman Elizarov1e459602017-02-27 11:05:17 +03001872_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 +03001873state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1874the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1875single-threaded context:
1876
1877```kotlin
1878val counterContext = newSingleThreadContext("CounterContext")
1879var counter = 0
1880
1881fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001882 massiveRun(CommonPool) { // run each coroutine in CommonPool
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001883 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001884 counter++
1885 }
1886 }
1887 println("Counter = $counter")
1888}
1889```
1890
Roman Elizarove8d79342017-08-29 15:21:21 +03001891> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001892
Roman Elizarov1e459602017-02-27 11:05:17 +03001893<!--- TEST ARBITRARY_TIME
1894Completed 1000000 actions in xxx ms
1895Counter = 1000000
1896-->
1897
1898This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001899from multi-threaded `CommonPool` context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03001900
1901### Thread confinement coarse-grained
1902
1903In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1904are confined to the single thread. The following example does it like that, running each coroutine in
1905the single-threaded context to start with.
1906
1907```kotlin
1908val counterContext = newSingleThreadContext("CounterContext")
1909var counter = 0
1910
1911fun main(args: Array<String>) = runBlocking<Unit> {
1912 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1913 counter++
1914 }
1915 println("Counter = $counter")
1916}
1917```
1918
Roman Elizarove8d79342017-08-29 15:21:21 +03001919> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001920
1921<!--- TEST ARBITRARY_TIME
1922Completed 1000000 actions in xxx ms
1923Counter = 1000000
1924-->
1925
1926This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001927
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001928### Mutual exclusion
1929
1930Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1931that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1932Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1933delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1934
Roman Elizarov88396732017-09-27 21:30:47 +03001935There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001936`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
1937
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001938```kotlin
1939val mutex = Mutex()
1940var counter = 0
1941
1942fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001943 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001944 mutex.withLock {
1945 counter++
1946 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001947 }
1948 println("Counter = $counter")
1949}
1950```
1951
Roman Elizarove8d79342017-08-29 15:21:21 +03001952> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001953
Roman Elizarov1e459602017-02-27 11:05:17 +03001954<!--- TEST ARBITRARY_TIME
1955Completed 1000000 actions in xxx ms
1956Counter = 1000000
1957-->
1958
1959The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
1960where you absolutely must modify some shared state periodically, but there is no natural thread that this state
1961is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001962
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001963### Actors
1964
1965An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
1966and a channel to communicate with other coroutines. A simple actor can be written as a function,
1967but an actor with a complex state is better suited for a class.
1968
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001969There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
1970scope to receive messages from and combines the send channel into the resulting job object, so that a
1971single reference to the actor can be carried around as its handle.
1972
Roman Elizarov256812a2017-07-22 01:00:30 +03001973The first step of using an actor is to define a class of messages that an actor is going to process.
1974Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
1975We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
1976to get its value. The later needs to send a response. A [CompletableDeferred] communication
1977primitive, that represents a single value that will be known (communicated) in the future,
1978is used here for that purpose.
1979
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001980```kotlin
1981// Message types for counterActor
1982sealed class CounterMsg
1983object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03001984class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
1985```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001986
Roman Elizarov256812a2017-07-22 01:00:30 +03001987Then we define a function that launches an actor using an [actor] coroutine builder:
1988
1989```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001990// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03001991fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001992 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001993 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001994 when (msg) {
1995 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03001996 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001997 }
1998 }
1999}
Roman Elizarov256812a2017-07-22 01:00:30 +03002000```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002001
Roman Elizarov256812a2017-07-22 01:00:30 +03002002The main code is straightforward:
2003
2004```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002005fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002006 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03002007 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002008 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002009 }
Roman Elizarov256812a2017-07-22 01:00:30 +03002010 // send a message to get a counter value from an actor
2011 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002012 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03002013 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002014 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002015}
2016```
2017
Roman Elizarove8d79342017-08-29 15:21:21 +03002018> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002019
Roman Elizarov1e459602017-02-27 11:05:17 +03002020<!--- TEST ARBITRARY_TIME
2021Completed 1000000 actions in xxx ms
2022Counter = 1000000
2023-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002024
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002025It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002026a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
2027works as a solution to the problem of shared mutable state.
2028
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002029Actor is more efficient than locking under load, because in this case it always has work to do and it does not
2030have to switch to a different context at all.
2031
2032> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
2033 with the channel that it receives messages from, while a producer is associated with the channel that it
2034 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03002035
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002036## Select expression
2037
Roman Elizarova84730b2017-02-22 11:58:50 +03002038Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002039the first one that becomes available.
2040
2041<!--- INCLUDE .*/example-select-([0-9]+).kt
2042import kotlinx.coroutines.experimental.channels.*
2043import kotlinx.coroutines.experimental.selects.*
2044-->
2045
2046### Selecting from channels
2047
Roman Elizarov57857202017-03-02 23:17:25 +03002048Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2049
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002050<!--- INCLUDE
2051import kotlinx.coroutines.experimental.*
2052import kotlin.coroutines.experimental.*
Roman Elizarov57857202017-03-02 23:17:25 +03002053-->
2054
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002055```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002056fun fizz(context: CoroutineContext) = produce<String>(context) {
2057 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002058 delay(300)
2059 send("Fizz")
2060 }
2061}
2062```
2063
Roman Elizarov57857202017-03-02 23:17:25 +03002064And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002065
2066```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002067fun buzz(context: CoroutineContext) = produce<String>(context) {
2068 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002069 delay(500)
2070 send("Buzz!")
2071 }
2072}
2073```
2074
2075Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2076other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002077[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002078
2079```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002080suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002081 select<Unit> { // <Unit> means that this select expression does not produce any result
2082 fizz.onReceive { value -> // this is the first select clause
2083 println("fizz -> '$value'")
2084 }
2085 buzz.onReceive { value -> // this is the second select clause
2086 println("buzz -> '$value'")
2087 }
2088 }
2089}
2090```
2091
Roman Elizarov57857202017-03-02 23:17:25 +03002092Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002093
2094```kotlin
2095fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002096 val fizz = fizz(coroutineContext)
2097 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002098 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002099 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002100 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002101 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002102}
2103```
2104
Roman Elizarove8d79342017-08-29 15:21:21 +03002105> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002106
2107The result of this code is:
2108
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002109```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002110fizz -> 'Fizz'
2111buzz -> 'Buzz!'
2112fizz -> 'Fizz'
2113fizz -> 'Fizz'
2114buzz -> 'Buzz!'
2115fizz -> 'Fizz'
2116buzz -> 'Buzz!'
2117```
2118
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002119<!--- TEST -->
2120
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002121### Selecting on close
2122
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002123The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed and the corresponding
2124`select` throws an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002125specific 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 +03002126the result of its selected clause:
2127
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002128<!--- INCLUDE
2129import kotlin.coroutines.experimental.*
2130-->
2131
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002132```kotlin
2133suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2134 select<String> {
2135 a.onReceiveOrNull { value ->
2136 if (value == null)
2137 "Channel 'a' is closed"
2138 else
2139 "a -> '$value'"
2140 }
2141 b.onReceiveOrNull { value ->
2142 if (value == null)
2143 "Channel 'b' is closed"
2144 else
2145 "b -> '$value'"
2146 }
2147 }
2148```
2149
Roman Elizarova84730b2017-02-22 11:58:50 +03002150Let's use it with channel `a` that produces "Hello" string four times and
2151channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002152
2153```kotlin
2154fun main(args: Array<String>) = runBlocking<Unit> {
2155 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002156 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002157 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002158 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002159 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002160 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002161 }
2162 repeat(8) { // print first eight results
2163 println(selectAorB(a, b))
2164 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002165 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002166}
2167```
2168
Roman Elizarove8d79342017-08-29 15:21:21 +03002169> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002170
Roman Elizarova84730b2017-02-22 11:58:50 +03002171The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002172
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002173```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002174a -> 'Hello 0'
2175a -> 'Hello 1'
2176b -> 'World 0'
2177a -> 'Hello 2'
2178a -> 'Hello 3'
2179b -> 'World 1'
2180Channel 'a' is closed
2181Channel 'a' is closed
2182```
2183
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002184<!--- TEST -->
2185
Roman Elizarova84730b2017-02-22 11:58:50 +03002186There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002187
2188First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2189the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002190being 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 +03002191time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2192
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002193The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002194channel is already closed.
2195
2196### Selecting to send
2197
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002198Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002199with a biased nature of selection.
2200
Roman Elizarova84730b2017-02-22 11:58:50 +03002201Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002202the consumers on its primary channel cannot keep up with it:
2203
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002204<!--- INCLUDE
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002205import kotlin.coroutines.experimental.*
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002206-->
2207
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002208```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002209fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002210 for (num in 1..10) { // produce 10 numbers from 1 to 10
2211 delay(100) // every 100 ms
2212 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002213 onSend(num) {} // Send to the primary channel
2214 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002215 }
2216 }
2217}
2218```
2219
2220Consumer is going to be quite slow, taking 250 ms to process each number:
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002221
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002222```kotlin
2223fun main(args: Array<String>) = runBlocking<Unit> {
2224 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002225 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002226 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002227 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002228 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002229 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002230 delay(250) // let us digest the consumed number properly, do not hurry
2231 }
2232 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002233 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002234}
2235```
2236
Roman Elizarove8d79342017-08-29 15:21:21 +03002237> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002238
2239So let us see what happens:
2240
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002241```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002242Consuming 1
2243Side channel has 2
2244Side channel has 3
2245Consuming 4
2246Side channel has 5
2247Side channel has 6
2248Consuming 7
2249Side channel has 8
2250Side channel has 9
2251Consuming 10
2252Done consuming
2253```
2254
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002255<!--- TEST -->
2256
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002257### Selecting deferred values
2258
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002259Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002260Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002261a random delay:
2262
2263<!--- INCLUDE .*/example-select-04.kt
2264import java.util.*
2265-->
2266
2267```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002268fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002269 delay(time.toLong())
2270 "Waited for $time ms"
2271}
2272```
2273
Roman Elizarova84730b2017-02-22 11:58:50 +03002274Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002275
2276```kotlin
2277fun asyncStringsList(): List<Deferred<String>> {
2278 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002279 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002280}
2281```
2282
Roman Elizarova84730b2017-02-22 11:58:50 +03002283Now 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 +03002284that 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 +03002285so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2286of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002287
2288```kotlin
2289fun main(args: Array<String>) = runBlocking<Unit> {
2290 val list = asyncStringsList()
2291 val result = select<String> {
2292 list.withIndex().forEach { (index, deferred) ->
2293 deferred.onAwait { answer ->
2294 "Deferred $index produced answer '$answer'"
2295 }
2296 }
2297 }
2298 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002299 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002300 println("$countActive coroutines are still active")
2301}
2302```
2303
Roman Elizarove8d79342017-08-29 15:21:21 +03002304> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-04.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002305
2306The output is:
2307
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002308```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002309Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300231011 coroutines are still active
2311```
2312
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002313<!--- TEST -->
2314
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002315### Switch over a channel of deferred values
2316
Roman Elizarova84730b2017-02-22 11:58:50 +03002317Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2318deferred 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 +03002319[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002320
Roman Elizarov9fe5f462018-02-21 19:05:52 +03002321<!--- INCLUDE
2322import kotlin.coroutines.experimental.*
2323-->
2324
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002325```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002326fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002327 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002328 while (isActive) { // loop while not cancelled/closed
2329 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2330 input.onReceiveOrNull { update ->
2331 update // replaces next value to wait
2332 }
2333 current.onAwait { value ->
2334 send(value) // send value that current deferred has produced
2335 input.receiveOrNull() // and use the next deferred from the input channel
2336 }
2337 }
2338 if (next == null) {
2339 println("Channel was closed")
2340 break // out of loop
2341 } else {
2342 current = next
2343 }
2344 }
2345}
2346```
2347
2348To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2349
2350```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002351fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002352 delay(time)
2353 str
2354}
2355```
2356
2357The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2358data to it:
2359
2360```kotlin
2361fun main(args: Array<String>) = runBlocking<Unit> {
2362 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002363 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002364 for (s in switchMapDeferreds(chan))
2365 println(s) // print each received string
2366 }
2367 chan.send(asyncString("BEGIN", 100))
2368 delay(200) // enough time for "BEGIN" to be produced
2369 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002370 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002371 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002372 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002373 chan.send(asyncString("END", 500))
2374 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002375 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002376 delay(500) // and wait some time to let it finish
2377}
2378```
2379
Roman Elizarove8d79342017-08-29 15:21:21 +03002380> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002381
2382The result of this code:
2383
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002384```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002385BEGIN
2386Replace
2387END
2388Channel was closed
2389```
2390
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002391<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002392
Roman Elizarov8db17332017-03-09 12:40:45 +03002393## Further reading
2394
2395* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002396* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002397* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2398* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2399
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002400<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002401<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002402[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2403[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2404[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002405[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002406[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002407[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2408[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03002409[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002410[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002411[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 +03002412[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002413[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002414[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2415[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002416[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 +03002417[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2418[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002419[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 +03002420[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2421[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002422[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002423[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002424[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002425[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002426[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2427[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 +03002428[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002429[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002430[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Roman Elizarov3e387b82017-12-04 13:49:11 +03002431[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 +03002432[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002433[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 +03002434<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002435[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002436[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2437[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 +03002438[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002439<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002440[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002441[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2442[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2443[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 +03002444[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002445[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002446[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002447[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002448[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive.html
2449[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2450[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 +03002451<!--- INDEX kotlinx.coroutines.experimental.selects -->
2452[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002453<!--- END -->