blob: 6d1074819f7137d3d3d06acca60d619f8b6f9f51 [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].
Roman Elizarova4d45d22017-11-20 16:47:09 +0300181The the main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` is active.
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 Elizarov419a6c82017-02-09 18:36:22 +0300507`run(NonCancellable) {...}` using [run] 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 {
518 run(NonCancellable) {
519 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
623import kotlin.system.measureTimeMillis
624-->
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?
642In practise we do this if we use the results of the first function to make a decision on whether we need
643to 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
Roman Elizarov32d95322017-02-09 15:57:31 +0300744either "async" prefix of "Async" suffix to highlight the fact that they only start asynchronous
745computation and one needs to use the resulting deferred value to get the result.
746
747```kotlin
748// The result type of asyncSomethingUsefulOne is Deferred<Int>
Roman Elizarov66f018c2017-09-29 21:39:03 +0300749fun asyncSomethingUsefulOne() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300750 doSomethingUsefulOne()
751}
752
753// The result type of asyncSomethingUsefulTwo is Deferred<Int>
Roman Elizarov66f018c2017-09-29 21:39:03 +0300754fun asyncSomethingUsefulTwo() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300755 doSomethingUsefulTwo()
756}
757```
758
759Note, that these `asyncXXX` function are **not** _suspending_ functions. They can be used from anywhere.
760However, 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
770 val one = asyncSomethingUsefulOne()
771 val two = asyncSomethingUsefulTwo()
772 // 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
810```kotlin
811fun main(args: Array<String>) = runBlocking<Unit> {
812 val jobs = arrayListOf<Job>()
813 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300814 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300815 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300816 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
817 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300818 }
819 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300820 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300821 }
822 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300823 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300824 }
825 jobs.forEach { it.join() }
826}
827```
828
Roman Elizarove8d79342017-08-29 15:21:21 +0300829> 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 +0300830
831It produces the following output (maybe in different order):
832
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300833```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300834 'Unconfined': I'm working in thread main
835 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
836 'newSTC': I'm working in thread MyOwnThread
837'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300838```
839
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300840<!--- TEST LINES_START_UNORDERED -->
841
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800842The default dispatcher that we've used in previous sections is representend by [DefaultDispatcher], which
Roman Elizarov66f018c2017-09-29 21:39:03 +0300843is equal to [CommonPool] in the current implementation. So, `launch { ... }` is the same
844as `launch(DefaultDispather) { ... }`, which is the same as `launch(CommonPool) { ... }`.
845
Roman Elizarov43e3af72017-07-21 16:01:31 +0300846The difference between parent [coroutineContext][CoroutineScope.coroutineContext] and
847[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300848
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800849Note, that [newSingleThreadContext] creates a new thread, which is a very expensive resource.
850In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close]
851function, or stored in a top-level variable and reused throughout the application.
852
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300853### Unconfined vs confined dispatcher
854
Roman Elizarov419a6c82017-02-09 18:36:22 +0300855The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300856first suspension point. After suspension it resumes in the thread that is fully determined by the
857suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
858consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
859
Roman Elizarov43e3af72017-07-21 16:01:31 +0300860On the other side, [coroutineContext][CoroutineScope.coroutineContext] property that is available inside the block of any coroutine
Roman Elizarov419a6c82017-02-09 18:36:22 +0300861via [CoroutineScope] interface, is a reference to a context of this particular coroutine.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300862This way, a parent context can be inherited. The default dispatcher for [runBlocking] coroutine, in particular,
863is confined to the invoker thread, so inheriting it has the effect of confining execution to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300864this thread with a predictable FIFO scheduling.
865
866```kotlin
867fun main(args: Array<String>) = runBlocking<Unit> {
868 val jobs = arrayListOf<Job>()
869 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300870 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300871 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300872 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300873 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300874 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
875 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300876 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300877 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300878 }
879 jobs.forEach { it.join() }
880}
881```
882
Roman Elizarove8d79342017-08-29 15:21:21 +0300883> 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 +0300884
885Produces the output:
886
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300887```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300888 'Unconfined': I'm working in thread main
889'coroutineContext': I'm working in thread main
890 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
891'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300892```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300893
894<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300895
Roman Elizarov43e3af72017-07-21 16:01:31 +0300896So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
897in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
898function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300899
900### Debugging coroutines and threads
901
Roman Elizarov419a6c82017-02-09 18:36:22 +0300902Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
Roman Elizarov66f018c2017-09-29 21:39:03 +0300903with a default multi-threaded dispatcher. Even with a single-threaded dispatcher it might be hard to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300904figure out what coroutine was doing what, where, and when. The common approach to debugging applications with
905threads is to print the thread name in the log file on each log statement. This feature is universally supported
906by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
907`kotlinx.coroutines` includes debugging facilities to make it easier.
908
909Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
910
911```kotlin
912fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
913
914fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300915 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300916 log("I'm computing a piece of the answer")
917 6
918 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300919 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300920 log("I'm computing another piece of the answer")
921 7
922 }
923 log("The answer is ${a.await() * b.await()}")
924}
925```
926
Roman Elizarove8d79342017-08-29 15:21:21 +0300927> 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 +0300928
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300929There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300930and two coroutines computing deferred values `a` (#2) and `b` (#3).
931They are all executing in the context of `runBlocking` and are confined to the main thread.
932The output of this code is:
933
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300934```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300935[main @coroutine#2] I'm computing a piece of the answer
936[main @coroutine#3] I'm computing another piece of the answer
937[main @coroutine#1] The answer is 42
938```
939
Kirill Timofeeva5186962017-10-25 14:25:47 +0300940<!--- TEST FLEXIBLE_THREAD -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300941
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300942The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
943thread, but the identifier of the currently executing coroutine is appended to it. This identifier
944is consecutively assigned to all created coroutines when debugging mode is turned on.
945
Roman Elizarov419a6c82017-02-09 18:36:22 +0300946You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300947
948### Jumping between threads
949
950Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
951
952```kotlin
953fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
954
955fun main(args: Array<String>) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800956 newSingleThreadContext("Ctx1").use { ctx1 ->
957 newSingleThreadContext("Ctx2").use { ctx2 ->
958 runBlocking(ctx1) {
959 log("Started in ctx1")
960 run(ctx2) {
961 log("Working in ctx2")
962 }
963 log("Back to ctx1")
964 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300965 }
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300966 }
967}
968```
969
Roman Elizarove8d79342017-08-29 15:21:21 +0300970> 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 +0300971
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800972It demonstrates several new techniques. One is using [runBlocking] with an explicitly specified context, and
973the other one is using [run] function to change a context of a coroutine while still staying in the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300974same coroutine as you can see in the output below:
975
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300976```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300977[Ctx1 @coroutine#1] Started in ctx1
978[Ctx2 @coroutine#1] Working in ctx2
979[Ctx1 @coroutine#1] Back to ctx1
980```
981
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300982<!--- TEST -->
983
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800984
985Note, that is example also uses `use` function from the Kotlin standard library to release threads that
986are created with [newSingleThreadContext] when they are no longer needed.
987
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300988### Job in the context
989
Roman Elizarov66f018c2017-09-29 21:39:03 +0300990The coroutine's [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +0300991using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300992
993```kotlin
994fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300995 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300996}
997```
998
Roman Elizarove8d79342017-08-29 15:21:21 +0300999> 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 +03001000
Roman Elizarov66f018c2017-09-29 21:39:03 +03001001It produces something like that when running in [debug mode](#debugging-coroutines-and-threads):
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001002
1003```
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001004My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001005```
1006
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001007<!--- TEST lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@") -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001008
Roman Elizarov43e3af72017-07-21 16:01:31 +03001009So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
1010`coroutineContext[Job]!!.isActive`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001011
1012### Children of a coroutine
1013
Roman Elizarov43e3af72017-07-21 16:01:31 +03001014When [coroutineContext][CoroutineScope.coroutineContext] of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +03001015the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001016a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
1017are recursively cancelled, too.
1018
1019```kotlin
1020fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001021 // launch a coroutine to process some kind of incoming request
1022 val request = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001023 // it spawns two other jobs, one with its separate context
Roman Elizarov66f018c2017-09-29 21:39:03 +03001024 val job1 = launch {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001025 println("job1: I have my own context and execute independently!")
1026 delay(1000)
1027 println("job1: I am not affected by cancellation of the request")
1028 }
1029 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +03001030 val job2 = launch(coroutineContext) {
Roman Elizarov74619c12017-11-09 10:32:15 +03001031 delay(100)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001032 println("job2: I am a child of the request coroutine")
1033 delay(1000)
1034 println("job2: I will not execute this line if my parent request is cancelled")
1035 }
1036 // request completes when both its sub-jobs complete:
1037 job1.join()
1038 job2.join()
1039 }
1040 delay(500)
1041 request.cancel() // cancel processing of the request
1042 delay(1000) // delay a second to see what happens
1043 println("main: Who has survived request cancellation?")
1044}
1045```
1046
Roman Elizarove8d79342017-08-29 15:21:21 +03001047> 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 +03001048
1049The output of this code is:
1050
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001051```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001052job1: I have my own context and execute independently!
1053job2: I am a child of the request coroutine
1054job1: I am not affected by cancellation of the request
1055main: Who has survived request cancellation?
1056```
1057
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001058<!--- TEST -->
1059
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001060### Combining contexts
1061
Roman Elizarov66f018c2017-09-29 21:39:03 +03001062Coroutine contexts can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +03001063of 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 +03001064its dispatcher replaced:
1065
1066```kotlin
1067fun main(args: Array<String>) = runBlocking<Unit> {
1068 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +03001069 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001070 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +03001071 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001072 println("job: I am a child of the request coroutine, but with a different dispatcher")
1073 delay(1000)
1074 println("job: I will not execute this line if my parent request is cancelled")
1075 }
1076 job.join() // request completes when its sub-job completes
1077 }
1078 delay(500)
1079 request.cancel() // cancel processing of the request
1080 delay(1000) // delay a second to see what happens
1081 println("main: Who has survived request cancellation?")
1082}
1083```
1084
Roman Elizarove8d79342017-08-29 15:21:21 +03001085> 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 +03001086
1087The expected outcome of this code is:
1088
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001089```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001090job: I am a child of the request coroutine, but with a different dispatcher
1091main: Who has survived request cancellation?
1092```
1093
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001094<!--- TEST -->
1095
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001096### Parental responsibilities
1097
1098A parent coroutine always waits for completion of all its children. Parent does not have to explicitly track
Roman Elizarov88396732017-09-27 21:30:47 +03001099all 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 +03001100
1101```kotlin
1102fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +03001103 // launch a coroutine to process some kind of incoming request
1104 val request = launch {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001105 repeat(3) { i -> // launch a few children jobs
1106 launch(coroutineContext) {
1107 delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
1108 println("Coroutine $i is done")
1109 }
1110 }
1111 println("request: I'm done and I don't explicitly join my children that are still active")
1112 }
1113 request.join() // wait for completion of the request, including all its children
1114 println("Now processing of the request is complete")
1115}
1116```
1117
1118> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt)
1119
1120The result is going to be:
1121
1122```text
1123request: I'm done and I don't explicitly join my children that are still active
1124Coroutine 0 is done
1125Coroutine 1 is done
1126Coroutine 2 is done
1127Now processing of the request is complete
1128```
1129
1130<!--- TEST -->
1131
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001132### Naming coroutines for debugging
1133
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001134Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001135coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1136or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov66f018c2017-09-29 21:39:03 +03001137[CoroutineName] context element serves the same function as a thread name. It'll get displayed in the thread name that
1138is executing this coroutine when [debugging mode](#debugging-coroutines-and-threads) is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001139
1140The following example demonstrates this concept:
1141
1142```kotlin
1143fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1144
1145fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1146 log("Started main coroutine")
1147 // run two background value computations
Roman Elizarov66f018c2017-09-29 21:39:03 +03001148 val v1 = async(CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001149 delay(500)
Roman Elizarov674efea2017-10-21 17:16:30 +03001150 log("Computing v1")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001151 252
1152 }
Roman Elizarov66f018c2017-09-29 21:39:03 +03001153 val v2 = async(CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001154 delay(1000)
Roman Elizarov674efea2017-10-21 17:16:30 +03001155 log("Computing v2")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001156 6
1157 }
1158 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1159}
1160```
1161
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001162> 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 +03001163
1164The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1165
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001166```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001167[main @main#1] Started main coroutine
1168[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1169[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1170[main @main#1] The answer for v1 / v2 = 42
1171```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001172
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001173<!--- TEST FLEXIBLE_THREAD -->
1174
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001175### Cancellation via explicit job
1176
1177Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1178an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1179and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1180and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1181to avoid memory leaks.
1182
1183We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
Roman Elizarov88396732017-09-27 21:30:47 +03001184the lifecycle of our activity. A job instance is created using [Job()] factory function
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001185as the following example shows. We need to make sure that all the coroutines are started
1186with this job in their context and then a single invocation of [Job.cancel] terminates them all.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001187Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1188this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001189
1190```kotlin
1191fun main(args: Array<String>) = runBlocking<Unit> {
1192 val job = Job() // create a job object to manage our lifecycle
1193 // now launch ten coroutines for a demo, each working for a different time
1194 val coroutines = List(10) { i ->
1195 // they are all children of our job object
Roman Elizarov43e3af72017-07-21 16:01:31 +03001196 launch(coroutineContext + job) { // we use the context of main runBlocking thread, but with our own job object
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001197 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001198 println("Coroutine $i is done")
1199 }
1200 }
1201 println("Launched ${coroutines.size} coroutines")
1202 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001203 println("Cancelling the job!")
1204 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001205}
1206```
1207
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001208> 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 +03001209
1210The output of this example is:
1211
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001212```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001213Launched 10 coroutines
1214Coroutine 0 is done
1215Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001216Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001217```
1218
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001219<!--- TEST -->
1220
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001221As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001222by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001223application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001224and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1225since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1226resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001227
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001228## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001229
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001230Deferred values provide a convenient way to transfer a single value between coroutines.
1231Channels provide a way to transfer a stream of values.
1232
1233<!--- INCLUDE .*/example-channel-([0-9]+).kt
1234import kotlinx.coroutines.experimental.channels.*
1235-->
1236
1237### Channel basics
1238
Roman Elizarov419a6c82017-02-09 18:36:22 +03001239A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1240instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1241a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001242
1243```kotlin
1244fun main(args: Array<String>) = runBlocking<Unit> {
1245 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001246 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001247 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1248 for (x in 1..5) channel.send(x * x)
1249 }
1250 // here we print five received integers:
1251 repeat(5) { println(channel.receive()) }
1252 println("Done!")
1253}
1254```
1255
Roman Elizarove8d79342017-08-29 15:21:21 +03001256> 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 +03001257
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001258The output of this code is:
1259
1260```text
12611
12624
12639
126416
126525
1266Done!
1267```
1268
1269<!--- TEST -->
1270
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001271### Closing and iteration over channels
1272
1273Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1274On the receiver side it is convenient to use a regular `for` loop to receive elements
1275from the channel.
1276
Roman Elizarov419a6c82017-02-09 18:36:22 +03001277Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001278The iteration stops as soon as this close token is received, so there is a guarantee
1279that all previously sent elements before the close are received:
1280
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 for (x in 1..5) channel.send(x * x)
1286 channel.close() // we're done sending
1287 }
1288 // here we print received values using `for` loop (until the channel is closed)
1289 for (y in channel) println(y)
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-02.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001295
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001296<!--- TEST
12971
12984
12999
130016
130125
1302Done!
1303-->
1304
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001305### Building channel producers
1306
Roman Elizarova5e653f2017-02-13 13:49:55 +03001307The pattern where a coroutine is producing a sequence of elements is quite common.
1308This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001309You 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 +03001310to common sense that results must be returned from functions.
1311
Roman Elizarov86349be2017-03-17 16:47:37 +03001312There 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 +03001313and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001314
1315```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001316fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001317 for (x in 1..5) send(x * x)
1318}
1319
1320fun main(args: Array<String>) = runBlocking<Unit> {
1321 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001322 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001323 println("Done!")
1324}
1325```
1326
Roman Elizarove8d79342017-08-29 15:21:21 +03001327> 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 +03001328
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001329<!--- TEST
13301
13314
13329
133316
133425
1335Done!
1336-->
1337
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001338### Pipelines
1339
Roman Elizarov66f018c2017-09-29 21:39:03 +03001340A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001341
1342```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001343fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001344 var x = 1
1345 while (true) send(x++) // infinite stream of integers starting from 1
1346}
1347```
1348
Roman Elizarova5e653f2017-02-13 13:49:55 +03001349And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001350In the below example the numbers are just squared:
1351
1352```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001353fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001354 for (x in numbers) send(x * x)
1355}
1356```
1357
Roman Elizarova5e653f2017-02-13 13:49:55 +03001358The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001359
1360```kotlin
1361fun main(args: Array<String>) = runBlocking<Unit> {
1362 val numbers = produceNumbers() // produces integers from 1 and on
1363 val squares = square(numbers) // squares integers
1364 for (i in 1..5) println(squares.receive()) // print first five
1365 println("Done!") // we are done
1366 squares.cancel() // need to cancel these coroutines in a larger app
1367 numbers.cancel()
1368}
1369```
1370
Roman Elizarove8d79342017-08-29 15:21:21 +03001371> 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 +03001372
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001373<!--- TEST
13741
13754
13769
137716
137825
1379Done!
1380-->
1381
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001382We don't have to cancel these coroutines in this example app, because
1383[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1384but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1385Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001386[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001387
1388### Prime numbers with pipeline
1389
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001390Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001391of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001392explicit `context` parameter and pass it to [produce] builder,
1393so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001394
Roman Elizarove8d79342017-08-29 15:21:21 +03001395<!--- INCLUDE core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001396import kotlin.coroutines.experimental.CoroutineContext
1397-->
1398
1399```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001400fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001401 var x = start
1402 while (true) send(x++) // infinite stream of integers from start
1403}
1404```
1405
1406The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1407that are divisible by the given prime number:
1408
1409```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001410fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001411 for (x in numbers) if (x % prime != 0) send(x)
1412}
1413```
1414
1415Now 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 +03001416and launching new pipeline stage for each prime number found:
1417
1418```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001419numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001420```
1421
1422The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001423running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
1424children of the main [runBlocking] coroutine in its [coroutineContext][CoroutineScope.coroutineContext],
Roman Elizarov66f018c2017-09-29 21:39:03 +03001425we don't have to keep an explicit list of all the coroutine we have started.
Roman Elizarov88396732017-09-27 21:30:47 +03001426We use [cancelChildren] extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001427
1428```kotlin
1429fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001430 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001431 for (i in 1..10) {
1432 val prime = cur.receive()
1433 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001434 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001435 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001436 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001437}
1438```
1439
Roman Elizarove8d79342017-08-29 15:21:21 +03001440> 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 +03001441
1442The output of this code is:
1443
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001444```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030014452
14463
14475
14487
144911
145013
145117
145219
145323
145429
1455```
1456
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001457<!--- TEST -->
1458
Roman Elizarov66f018c2017-09-29 21:39:03 +03001459Note, that you can build the same pipeline using
1460[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1461coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001462Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001463`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1464However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1465multiple CPU cores if you run it in [CommonPool] context.
1466
Roman Elizarova5e653f2017-02-13 13:49:55 +03001467Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001468other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1469built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001470`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001471
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001472### Fan-out
1473
1474Multiple coroutines may receive from the same channel, distributing work between themselves.
1475Let us start with a producer coroutine that is periodically producing integers
1476(ten numbers per second):
1477
1478```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001479fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001480 var x = 1 // start from 1
1481 while (true) {
1482 send(x++) // produce next
1483 delay(100) // wait 0.1s
1484 }
1485}
1486```
1487
1488Then we can have several processor coroutines. In this example, they just print their id and
1489received number:
1490
1491```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001492fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
Roman Elizarov86349be2017-03-17 16:47:37 +03001493 channel.consumeEach {
1494 println("Processor #$id received $it")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001495 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001496}
1497```
1498
Roman Elizarov35d2c342017-07-20 14:54:39 +03001499Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001500
1501```kotlin
1502fun main(args: Array<String>) = runBlocking<Unit> {
1503 val producer = produceNumbers()
1504 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001505 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001506 producer.cancel() // cancel producer coroutine and thus kill them all
1507}
1508```
1509
Roman Elizarove8d79342017-08-29 15:21:21 +03001510> 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 +03001511
1512The output will be similar to the the following one, albeit the processor ids that receive
1513each specific integer may be different:
1514
1515```
1516Processor #2 received 1
1517Processor #4 received 2
1518Processor #0 received 3
1519Processor #1 received 4
1520Processor #3 received 5
1521Processor #2 received 6
1522Processor #4 received 7
1523Processor #0 received 8
1524Processor #1 received 9
1525Processor #3 received 10
1526```
1527
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001528<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1529
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001530Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1531over the channel that processor coroutines are doing.
1532
1533### Fan-in
1534
1535Multiple coroutines may send to the same channel.
1536For example, let us have a channel of strings, and a suspending function that
1537repeatedly sends a specified string to this channel with a specified delay:
1538
1539```kotlin
1540suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1541 while (true) {
1542 delay(time)
1543 channel.send(s)
1544 }
1545}
1546```
1547
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001548Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001549(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 +03001550
1551```kotlin
1552fun main(args: Array<String>) = runBlocking<Unit> {
1553 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001554 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1555 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001556 repeat(6) { // receive first six
1557 println(channel.receive())
1558 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001559 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001560}
1561```
1562
Roman Elizarove8d79342017-08-29 15:21:21 +03001563> 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 +03001564
1565The output is:
1566
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001567```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001568foo
1569foo
1570BAR!
1571foo
1572foo
1573BAR!
1574```
1575
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001576<!--- TEST -->
1577
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001578### Buffered channels
1579
1580The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1581meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1582if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001583
Roman Elizarov88396732017-09-27 21:30:47 +03001584Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001585specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1586similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1587
1588Take a look at the behavior of the following code:
1589
1590```kotlin
1591fun main(args: Array<String>) = runBlocking<Unit> {
1592 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001593 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001594 repeat(10) {
1595 println("Sending $it") // print before sending each element
1596 channel.send(it) // will suspend when buffer is full
1597 }
1598 }
1599 // don't receive anything... just wait....
1600 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001601 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001602}
1603```
1604
Roman Elizarove8d79342017-08-29 15:21:21 +03001605> 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 +03001606
1607It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1608
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001609```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001610Sending 0
1611Sending 1
1612Sending 2
1613Sending 3
1614Sending 4
1615```
1616
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001617<!--- TEST -->
1618
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001619The 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 +03001620
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001621### Channels are fair
1622
1623Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1624multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1625gets the element. In the following example two coroutines "ping" and "pong" are
1626receiving the "ball" object from the shared "table" channel.
1627
1628```kotlin
1629data class Ball(var hits: Int)
1630
1631fun main(args: Array<String>) = runBlocking<Unit> {
1632 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001633 launch(coroutineContext) { player("ping", table) }
1634 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001635 table.send(Ball(0)) // serve the ball
1636 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001637 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001638}
1639
1640suspend fun player(name: String, table: Channel<Ball>) {
1641 for (ball in table) { // receive the ball in a loop
1642 ball.hits++
1643 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001644 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001645 table.send(ball) // send the ball back
1646 }
1647}
1648```
1649
Roman Elizarove8d79342017-08-29 15:21:21 +03001650> 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 +03001651
1652The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1653coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1654received by the "pong" coroutine, because it was already waiting for it:
1655
1656```text
1657ping Ball(hits=1)
1658pong Ball(hits=2)
1659ping Ball(hits=3)
1660pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001661```
1662
1663<!--- TEST -->
1664
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001665Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
1666that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
1667
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001668## Shared mutable state and concurrency
1669
Roman Elizarov66f018c2017-09-29 21:39:03 +03001670Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001671all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1672Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1673but others are unique.
1674
1675### The problem
1676
Roman Elizarov1e459602017-02-27 11:05:17 +03001677Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1678We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001679
Roman Elizarov43e90112017-05-10 11:25:20 +03001680<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
Roman Elizarov1e459602017-02-27 11:05:17 +03001681import kotlin.coroutines.experimental.CoroutineContext
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001682import kotlin.system.measureTimeMillis
1683-->
1684
Roman Elizarov1e459602017-02-27 11:05:17 +03001685<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001686import java.util.concurrent.atomic.AtomicInteger
1687-->
1688
Roman Elizarov1e459602017-02-27 11:05:17 +03001689<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001690import kotlinx.coroutines.experimental.sync.Mutex
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001691import kotlinx.coroutines.experimental.sync.withLock
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001692-->
1693
Roman Elizarov1e459602017-02-27 11:05:17 +03001694<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001695import kotlinx.coroutines.experimental.channels.*
1696-->
1697
1698```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001699suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1700 val n = 1000 // number of coroutines to launch
1701 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001702 val time = measureTimeMillis {
1703 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001704 launch(context) {
1705 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001706 }
1707 }
1708 jobs.forEach { it.join() }
1709 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001710 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001711}
1712```
1713
Roman Elizarov43e90112017-05-10 11:25:20 +03001714<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001715
Roman Elizarov1e459602017-02-27 11:05:17 +03001716We start with a very simple action that increments a shared mutable variable using
1717multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001718
1719```kotlin
1720var counter = 0
1721
1722fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001723 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001724 counter++
1725 }
1726 println("Counter = $counter")
1727}
1728```
1729
Roman Elizarove8d79342017-08-29 15:21:21 +03001730> 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 +03001731
Roman Elizarov1e459602017-02-27 11:05:17 +03001732<!--- TEST LINES_START
1733Completed 1000000 actions in
1734Counter =
1735-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001736
Roman Elizarov1e459602017-02-27 11:05:17 +03001737What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1738increment the `counter` concurrently from multiple threads without any synchronization.
1739
Roman Elizarov43e90112017-05-10 11:25:20 +03001740> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1741`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1742following change:
1743
1744```kotlin
1745val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1746var counter = 0
1747
1748fun main(args: Array<String>) = runBlocking<Unit> {
1749 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1750 counter++
1751 }
1752 println("Counter = $counter")
1753}
1754```
1755
Roman Elizarove8d79342017-08-29 15:21:21 +03001756> 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 +03001757
1758<!--- TEST LINES_START
1759Completed 1000000 actions in
1760Counter =
1761-->
1762
Roman Elizarov1e459602017-02-27 11:05:17 +03001763### Volatiles are of no help
1764
1765There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1766
1767```kotlin
1768@Volatile // in Kotlin `volatile` is an annotation
1769var counter = 0
1770
1771fun main(args: Array<String>) = runBlocking<Unit> {
1772 massiveRun(CommonPool) {
1773 counter++
1774 }
1775 println("Counter = $counter")
1776}
1777```
1778
Roman Elizarove8d79342017-08-29 15:21:21 +03001779> 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 +03001780
1781<!--- TEST LINES_START
1782Completed 1000000 actions in
1783Counter =
1784-->
1785
1786This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1787linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1788do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001789
1790### Thread-safe data structures
1791
1792The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1793linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1794operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001795In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001796
1797```kotlin
1798var counter = AtomicInteger()
1799
1800fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001801 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001802 counter.incrementAndGet()
1803 }
1804 println("Counter = ${counter.get()}")
1805}
1806```
1807
Roman Elizarove8d79342017-08-29 15:21:21 +03001808> 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 +03001809
Roman Elizarov1e459602017-02-27 11:05:17 +03001810<!--- TEST ARBITRARY_TIME
1811Completed 1000000 actions in xxx ms
1812Counter = 1000000
1813-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001814
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001815This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1816standard data structures and basic operations on them. However, it does not easily scale to complex
1817state or to complex operations that do not have ready-to-use thread-safe implementations.
1818
Roman Elizarov1e459602017-02-27 11:05:17 +03001819### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001820
Roman Elizarov1e459602017-02-27 11:05:17 +03001821_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 +03001822state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1823the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1824single-threaded context:
1825
1826```kotlin
1827val counterContext = newSingleThreadContext("CounterContext")
1828var counter = 0
1829
1830fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001831 massiveRun(CommonPool) { // run each coroutine in CommonPool
1832 run(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001833 counter++
1834 }
1835 }
1836 println("Counter = $counter")
1837}
1838```
1839
Roman Elizarove8d79342017-08-29 15:21:21 +03001840> 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 +03001841
Roman Elizarov1e459602017-02-27 11:05:17 +03001842<!--- TEST ARBITRARY_TIME
1843Completed 1000000 actions in xxx ms
1844Counter = 1000000
1845-->
1846
1847This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
1848from multi-threaded `CommonPool` context to the single-threaded context using [run] block.
1849
1850### Thread confinement coarse-grained
1851
1852In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1853are confined to the single thread. The following example does it like that, running each coroutine in
1854the single-threaded context to start with.
1855
1856```kotlin
1857val counterContext = newSingleThreadContext("CounterContext")
1858var counter = 0
1859
1860fun main(args: Array<String>) = runBlocking<Unit> {
1861 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1862 counter++
1863 }
1864 println("Counter = $counter")
1865}
1866```
1867
Roman Elizarove8d79342017-08-29 15:21:21 +03001868> 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 +03001869
1870<!--- TEST ARBITRARY_TIME
1871Completed 1000000 actions in xxx ms
1872Counter = 1000000
1873-->
1874
1875This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001876
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001877### Mutual exclusion
1878
1879Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1880that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1881Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1882delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1883
Roman Elizarov88396732017-09-27 21:30:47 +03001884There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001885`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
1886
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001887```kotlin
1888val mutex = Mutex()
1889var counter = 0
1890
1891fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001892 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001893 mutex.withLock {
1894 counter++
1895 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001896 }
1897 println("Counter = $counter")
1898}
1899```
1900
Roman Elizarove8d79342017-08-29 15:21:21 +03001901> 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 +03001902
Roman Elizarov1e459602017-02-27 11:05:17 +03001903<!--- TEST ARBITRARY_TIME
1904Completed 1000000 actions in xxx ms
1905Counter = 1000000
1906-->
1907
1908The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
1909where you absolutely must modify some shared state periodically, but there is no natural thread that this state
1910is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001911
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001912### Actors
1913
1914An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
1915and a channel to communicate with other coroutines. A simple actor can be written as a function,
1916but an actor with a complex state is better suited for a class.
1917
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001918There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
1919scope to receive messages from and combines the send channel into the resulting job object, so that a
1920single reference to the actor can be carried around as its handle.
1921
Roman Elizarov256812a2017-07-22 01:00:30 +03001922The first step of using an actor is to define a class of messages that an actor is going to process.
1923Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
1924We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
1925to get its value. The later needs to send a response. A [CompletableDeferred] communication
1926primitive, that represents a single value that will be known (communicated) in the future,
1927is used here for that purpose.
1928
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001929```kotlin
1930// Message types for counterActor
1931sealed class CounterMsg
1932object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03001933class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
1934```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001935
Roman Elizarov256812a2017-07-22 01:00:30 +03001936Then we define a function that launches an actor using an [actor] coroutine builder:
1937
1938```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001939// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03001940fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001941 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001942 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001943 when (msg) {
1944 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03001945 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001946 }
1947 }
1948}
Roman Elizarov256812a2017-07-22 01:00:30 +03001949```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001950
Roman Elizarov256812a2017-07-22 01:00:30 +03001951The main code is straightforward:
1952
1953```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001954fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001955 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03001956 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001957 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001958 }
Roman Elizarov256812a2017-07-22 01:00:30 +03001959 // send a message to get a counter value from an actor
1960 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001961 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03001962 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001963 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001964}
1965```
1966
Roman Elizarove8d79342017-08-29 15:21:21 +03001967> 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 +03001968
Roman Elizarov1e459602017-02-27 11:05:17 +03001969<!--- TEST ARBITRARY_TIME
1970Completed 1000000 actions in xxx ms
1971Counter = 1000000
1972-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001973
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001974It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001975a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
1976works as a solution to the problem of shared mutable state.
1977
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001978Actor is more efficient than locking under load, because in this case it always has work to do and it does not
1979have to switch to a different context at all.
1980
1981> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
1982 with the channel that it receives messages from, while a producer is associated with the channel that it
1983 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03001984
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001985## Select expression
1986
Roman Elizarova84730b2017-02-22 11:58:50 +03001987Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001988the first one that becomes available.
1989
1990<!--- INCLUDE .*/example-select-([0-9]+).kt
1991import kotlinx.coroutines.experimental.channels.*
1992import kotlinx.coroutines.experimental.selects.*
1993-->
1994
1995### Selecting from channels
1996
Roman Elizarov57857202017-03-02 23:17:25 +03001997Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
1998
1999<!--- INCLUDE .*/example-select-01.kt
2000import kotlin.coroutines.experimental.CoroutineContext
2001-->
2002
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002003```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002004fun fizz(context: CoroutineContext) = produce<String>(context) {
2005 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002006 delay(300)
2007 send("Fizz")
2008 }
2009}
2010```
2011
Roman Elizarov57857202017-03-02 23:17:25 +03002012And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002013
2014```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002015fun buzz(context: CoroutineContext) = produce<String>(context) {
2016 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002017 delay(500)
2018 send("Buzz!")
2019 }
2020}
2021```
2022
2023Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2024other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002025[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002026
2027```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002028suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002029 select<Unit> { // <Unit> means that this select expression does not produce any result
2030 fizz.onReceive { value -> // this is the first select clause
2031 println("fizz -> '$value'")
2032 }
2033 buzz.onReceive { value -> // this is the second select clause
2034 println("buzz -> '$value'")
2035 }
2036 }
2037}
2038```
2039
Roman Elizarov57857202017-03-02 23:17:25 +03002040Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002041
2042```kotlin
2043fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002044 val fizz = fizz(coroutineContext)
2045 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002046 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002047 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002048 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002049 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002050}
2051```
2052
Roman Elizarove8d79342017-08-29 15:21:21 +03002053> 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 +03002054
2055The result of this code is:
2056
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002057```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002058fizz -> 'Fizz'
2059buzz -> 'Buzz!'
2060fizz -> 'Fizz'
2061fizz -> 'Fizz'
2062buzz -> 'Buzz!'
2063fizz -> 'Fizz'
2064buzz -> 'Buzz!'
2065```
2066
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002067<!--- TEST -->
2068
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002069### Selecting on close
2070
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002071The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed and the corresponding
2072`select` throws an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002073specific 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 +03002074the result of its selected clause:
2075
2076```kotlin
2077suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2078 select<String> {
2079 a.onReceiveOrNull { value ->
2080 if (value == null)
2081 "Channel 'a' is closed"
2082 else
2083 "a -> '$value'"
2084 }
2085 b.onReceiveOrNull { value ->
2086 if (value == null)
2087 "Channel 'b' is closed"
2088 else
2089 "b -> '$value'"
2090 }
2091 }
2092```
2093
Roman Elizarova84730b2017-02-22 11:58:50 +03002094Let's use it with channel `a` that produces "Hello" string four times and
2095channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002096
2097```kotlin
2098fun main(args: Array<String>) = runBlocking<Unit> {
2099 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002100 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002101 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002102 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002103 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002104 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002105 }
2106 repeat(8) { // print first eight results
2107 println(selectAorB(a, b))
2108 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002109 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002110}
2111```
2112
Roman Elizarove8d79342017-08-29 15:21:21 +03002113> 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 +03002114
Roman Elizarova84730b2017-02-22 11:58:50 +03002115The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002116
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002117```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002118a -> 'Hello 0'
2119a -> 'Hello 1'
2120b -> 'World 0'
2121a -> 'Hello 2'
2122a -> 'Hello 3'
2123b -> 'World 1'
2124Channel 'a' is closed
2125Channel 'a' is closed
2126```
2127
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002128<!--- TEST -->
2129
Roman Elizarova84730b2017-02-22 11:58:50 +03002130There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002131
2132First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2133the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002134being 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 +03002135time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2136
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002137The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002138channel is already closed.
2139
2140### Selecting to send
2141
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002142Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002143with a biased nature of selection.
2144
Roman Elizarova84730b2017-02-22 11:58:50 +03002145Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002146the consumers on its primary channel cannot keep up with it:
2147
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002148<!--- INCLUDE
2149import kotlin.coroutines.experimental.CoroutineContext
2150-->
2151
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002152```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002153fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002154 for (num in 1..10) { // produce 10 numbers from 1 to 10
2155 delay(100) // every 100 ms
2156 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002157 onSend(num) {} // Send to the primary channel
2158 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002159 }
2160 }
2161}
2162```
2163
2164Consumer is going to be quite slow, taking 250 ms to process each number:
2165
2166```kotlin
2167fun main(args: Array<String>) = runBlocking<Unit> {
2168 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002169 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002170 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002171 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002172 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002173 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002174 delay(250) // let us digest the consumed number properly, do not hurry
2175 }
2176 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002177 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002178}
2179```
2180
Roman Elizarove8d79342017-08-29 15:21:21 +03002181> 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 +03002182
2183So let us see what happens:
2184
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002185```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002186Consuming 1
2187Side channel has 2
2188Side channel has 3
2189Consuming 4
2190Side channel has 5
2191Side channel has 6
2192Consuming 7
2193Side channel has 8
2194Side channel has 9
2195Consuming 10
2196Done consuming
2197```
2198
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002199<!--- TEST -->
2200
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002201### Selecting deferred values
2202
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002203Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002204Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002205a random delay:
2206
2207<!--- INCLUDE .*/example-select-04.kt
2208import java.util.*
2209-->
2210
2211```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002212fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002213 delay(time.toLong())
2214 "Waited for $time ms"
2215}
2216```
2217
Roman Elizarova84730b2017-02-22 11:58:50 +03002218Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002219
2220```kotlin
2221fun asyncStringsList(): List<Deferred<String>> {
2222 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002223 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002224}
2225```
2226
Roman Elizarova84730b2017-02-22 11:58:50 +03002227Now 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 +03002228that 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 +03002229so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2230of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002231
2232```kotlin
2233fun main(args: Array<String>) = runBlocking<Unit> {
2234 val list = asyncStringsList()
2235 val result = select<String> {
2236 list.withIndex().forEach { (index, deferred) ->
2237 deferred.onAwait { answer ->
2238 "Deferred $index produced answer '$answer'"
2239 }
2240 }
2241 }
2242 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002243 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002244 println("$countActive coroutines are still active")
2245}
2246```
2247
Roman Elizarove8d79342017-08-29 15:21:21 +03002248> 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 +03002249
2250The output is:
2251
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002252```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002253Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300225411 coroutines are still active
2255```
2256
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002257<!--- TEST -->
2258
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002259### Switch over a channel of deferred values
2260
Roman Elizarova84730b2017-02-22 11:58:50 +03002261Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2262deferred 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 +03002263[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002264
2265```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002266fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002267 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002268 while (isActive) { // loop while not cancelled/closed
2269 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2270 input.onReceiveOrNull { update ->
2271 update // replaces next value to wait
2272 }
2273 current.onAwait { value ->
2274 send(value) // send value that current deferred has produced
2275 input.receiveOrNull() // and use the next deferred from the input channel
2276 }
2277 }
2278 if (next == null) {
2279 println("Channel was closed")
2280 break // out of loop
2281 } else {
2282 current = next
2283 }
2284 }
2285}
2286```
2287
2288To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2289
2290```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002291fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002292 delay(time)
2293 str
2294}
2295```
2296
2297The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2298data to it:
2299
2300```kotlin
2301fun main(args: Array<String>) = runBlocking<Unit> {
2302 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002303 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002304 for (s in switchMapDeferreds(chan))
2305 println(s) // print each received string
2306 }
2307 chan.send(asyncString("BEGIN", 100))
2308 delay(200) // enough time for "BEGIN" to be produced
2309 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002310 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002311 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002312 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002313 chan.send(asyncString("END", 500))
2314 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002315 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002316 delay(500) // and wait some time to let it finish
2317}
2318```
2319
Roman Elizarove8d79342017-08-29 15:21:21 +03002320> 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 +03002321
2322The result of this code:
2323
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002324```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002325BEGIN
2326Replace
2327END
2328Channel was closed
2329```
2330
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002331<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002332
Roman Elizarov8db17332017-03-09 12:40:45 +03002333## Further reading
2334
2335* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002336* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002337* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2338* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2339
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002340<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002341<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002342[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2343[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2344[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002345[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002346[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002347[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2348[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002349[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception.html
2350[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002351[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 +03002352[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
2353[run]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
2354[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2355[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002356[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 +03002357[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2358[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002359[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 +03002360[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2361[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002362[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002363[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002364[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov43e3af72017-07-21 16:01:31 +03002365[CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/coroutine-context.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002366[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002367[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2368[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 +03002369[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002370[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002371[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
2372[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 +03002373[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002374[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 +03002375<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002376[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002377[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2378[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 +03002379[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002380<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002381[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002382[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2383[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2384[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 +03002385[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002386[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002387[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002388[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002389[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive.html
2390[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2391[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 +03002392<!--- INDEX kotlinx.coroutines.experimental.selects -->
2393[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002394<!--- END -->