blob: 359347c031d9281ed98e1a9eaa1faa55336870be [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 Elizarove8f694e2017-11-28 10:12:00 +03001185as the following example shows. For convenience, rather than using `launch(coroutineContext + job)` expression,
1186we can write `launch(coroutineContext, parent = job)` to make explicit the fact that the parent job is being used.
1187
1188Now, a single invocation of [Job.cancel] cancels all the children we've launched.
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001189Moreover, [Job.join] waits for all of them to complete, so we can also use [cancelAndJoin] here in
1190this example:
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001191
1192```kotlin
1193fun main(args: Array<String>) = runBlocking<Unit> {
1194 val job = Job() // create a job object to manage our lifecycle
1195 // now launch ten coroutines for a demo, each working for a different time
1196 val coroutines = List(10) { i ->
1197 // they are all children of our job object
Roman Elizarove8f694e2017-11-28 10:12:00 +03001198 launch(coroutineContext, parent = job) { // we use the context of main runBlocking thread, but with our parent job
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001199 delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001200 println("Coroutine $i is done")
1201 }
1202 }
1203 println("Launched ${coroutines.size} coroutines")
1204 delay(500L) // delay for half a second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001205 println("Cancelling the job!")
1206 job.cancelAndJoin() // cancel all our coroutines and wait for all of them to complete
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001207}
1208```
1209
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001210> 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 +03001211
1212The output of this example is:
1213
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001214```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001215Launched 10 coroutines
1216Coroutine 0 is done
1217Coroutine 1 is done
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001218Cancelling the job!
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001219```
1220
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001221<!--- TEST -->
1222
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001223As you can see, only the first three coroutines had printed a message and the others were cancelled
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001224by a single invocation of `job.cancelAndJoin()`. So all we need to do in our hypothetical Android
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001225application is to create a parent job object when activity is created, use it for child coroutines,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001226and cancel it when activity is destroyed. We cannot `join` them in the case of Android lifecycle,
1227since it is synchronous, but this joining ability is useful when building backend services to ensure bounded
1228resource usage.
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001229
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001230## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001231
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001232Deferred values provide a convenient way to transfer a single value between coroutines.
1233Channels provide a way to transfer a stream of values.
1234
1235<!--- INCLUDE .*/example-channel-([0-9]+).kt
1236import kotlinx.coroutines.experimental.channels.*
1237-->
1238
1239### Channel basics
1240
Roman Elizarov419a6c82017-02-09 18:36:22 +03001241A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1242instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1243a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001244
1245```kotlin
1246fun main(args: Array<String>) = runBlocking<Unit> {
1247 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001248 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001249 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1250 for (x in 1..5) channel.send(x * x)
1251 }
1252 // here we print five received integers:
1253 repeat(5) { println(channel.receive()) }
1254 println("Done!")
1255}
1256```
1257
Roman Elizarove8d79342017-08-29 15:21:21 +03001258> 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 +03001259
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001260The output of this code is:
1261
1262```text
12631
12644
12659
126616
126725
1268Done!
1269```
1270
1271<!--- TEST -->
1272
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001273### Closing and iteration over channels
1274
1275Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1276On the receiver side it is convenient to use a regular `for` loop to receive elements
1277from the channel.
1278
Roman Elizarov419a6c82017-02-09 18:36:22 +03001279Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001280The iteration stops as soon as this close token is received, so there is a guarantee
1281that all previously sent elements before the close are received:
1282
1283```kotlin
1284fun main(args: Array<String>) = runBlocking<Unit> {
1285 val channel = Channel<Int>()
Roman Elizarov66f018c2017-09-29 21:39:03 +03001286 launch {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001287 for (x in 1..5) channel.send(x * x)
1288 channel.close() // we're done sending
1289 }
1290 // here we print received values using `for` loop (until the channel is closed)
1291 for (y in channel) println(y)
1292 println("Done!")
1293}
1294```
1295
Roman Elizarove8d79342017-08-29 15:21:21 +03001296> 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 +03001297
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001298<!--- TEST
12991
13004
13019
130216
130325
1304Done!
1305-->
1306
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001307### Building channel producers
1308
Roman Elizarova5e653f2017-02-13 13:49:55 +03001309The pattern where a coroutine is producing a sequence of elements is quite common.
1310This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001311You 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 +03001312to common sense that results must be returned from functions.
1313
Roman Elizarov86349be2017-03-17 16:47:37 +03001314There 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 +03001315and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001316
1317```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001318fun produceSquares() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001319 for (x in 1..5) send(x * x)
1320}
1321
1322fun main(args: Array<String>) = runBlocking<Unit> {
1323 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001324 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001325 println("Done!")
1326}
1327```
1328
Roman Elizarove8d79342017-08-29 15:21:21 +03001329> 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 +03001330
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001331<!--- TEST
13321
13334
13349
133516
133625
1337Done!
1338-->
1339
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001340### Pipelines
1341
Roman Elizarov66f018c2017-09-29 21:39:03 +03001342A pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001343
1344```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001345fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001346 var x = 1
1347 while (true) send(x++) // infinite stream of integers starting from 1
1348}
1349```
1350
Roman Elizarova5e653f2017-02-13 13:49:55 +03001351And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001352In the below example the numbers are just squared:
1353
1354```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001355fun square(numbers: ReceiveChannel<Int>) = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001356 for (x in numbers) send(x * x)
1357}
1358```
1359
Roman Elizarova5e653f2017-02-13 13:49:55 +03001360The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001361
1362```kotlin
1363fun main(args: Array<String>) = runBlocking<Unit> {
1364 val numbers = produceNumbers() // produces integers from 1 and on
1365 val squares = square(numbers) // squares integers
1366 for (i in 1..5) println(squares.receive()) // print first five
1367 println("Done!") // we are done
1368 squares.cancel() // need to cancel these coroutines in a larger app
1369 numbers.cancel()
1370}
1371```
1372
Roman Elizarove8d79342017-08-29 15:21:21 +03001373> 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 +03001374
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001375<!--- TEST
13761
13774
13789
137916
138025
1381Done!
1382-->
1383
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001384We don't have to cancel these coroutines in this example app, because
1385[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1386but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1387Alternatively, we could have run pipeline coroutines as
Roman Elizarov66f018c2017-09-29 21:39:03 +03001388[children of a main coroutine](#children-of-a-coroutine) as is demonstrated in the following example.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001389
1390### Prime numbers with pipeline
1391
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001392Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001393of coroutines. We start with an infinite sequence of numbers. This time we introduce an
Roman Elizarov66f018c2017-09-29 21:39:03 +03001394explicit `context` parameter and pass it to [produce] builder,
1395so that caller can control where our coroutines run:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001396
Roman Elizarove8d79342017-08-29 15:21:21 +03001397<!--- INCLUDE core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001398import kotlin.coroutines.experimental.CoroutineContext
1399-->
1400
1401```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001402fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001403 var x = start
1404 while (true) send(x++) // infinite stream of integers from start
1405}
1406```
1407
1408The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1409that are divisible by the given prime number:
1410
1411```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001412fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001413 for (x in numbers) if (x % prime != 0) send(x)
1414}
1415```
1416
1417Now 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 +03001418and launching new pipeline stage for each prime number found:
1419
1420```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001421numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001422```
1423
1424The following example prints the first ten prime numbers,
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001425running the whole pipeline in the context of the main thread. Since all the coroutines are launched as
1426children of the main [runBlocking] coroutine in its [coroutineContext][CoroutineScope.coroutineContext],
Roman Elizarov66f018c2017-09-29 21:39:03 +03001427we don't have to keep an explicit list of all the coroutine we have started.
Roman Elizarov88396732017-09-27 21:30:47 +03001428We use [cancelChildren] extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001429
1430```kotlin
1431fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001432 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001433 for (i in 1..10) {
1434 val prime = cur.receive()
1435 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001436 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001437 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001438 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001439}
1440```
1441
Roman Elizarove8d79342017-08-29 15:21:21 +03001442> 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 +03001443
1444The output of this code is:
1445
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001446```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030014472
14483
14495
14507
145111
145213
145317
145419
145523
145629
1457```
1458
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001459<!--- TEST -->
1460
Roman Elizarov66f018c2017-09-29 21:39:03 +03001461Note, that you can build the same pipeline using
1462[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1463coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001464Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001465`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1466However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1467multiple CPU cores if you run it in [CommonPool] context.
1468
Roman Elizarova5e653f2017-02-13 13:49:55 +03001469Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001470other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1471built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001472`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001473
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001474### Fan-out
1475
1476Multiple coroutines may receive from the same channel, distributing work between themselves.
1477Let us start with a producer coroutine that is periodically producing integers
1478(ten numbers per second):
1479
1480```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001481fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001482 var x = 1 // start from 1
1483 while (true) {
1484 send(x++) // produce next
1485 delay(100) // wait 0.1s
1486 }
1487}
1488```
1489
1490Then we can have several processor coroutines. In this example, they just print their id and
1491received number:
1492
1493```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001494fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
Roman Elizarov86349be2017-03-17 16:47:37 +03001495 channel.consumeEach {
1496 println("Processor #$id received $it")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001497 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001498}
1499```
1500
Roman Elizarov35d2c342017-07-20 14:54:39 +03001501Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001502
1503```kotlin
1504fun main(args: Array<String>) = runBlocking<Unit> {
1505 val producer = produceNumbers()
1506 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001507 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001508 producer.cancel() // cancel producer coroutine and thus kill them all
1509}
1510```
1511
Roman Elizarove8d79342017-08-29 15:21:21 +03001512> 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 +03001513
1514The output will be similar to the the following one, albeit the processor ids that receive
1515each specific integer may be different:
1516
1517```
1518Processor #2 received 1
1519Processor #4 received 2
1520Processor #0 received 3
1521Processor #1 received 4
1522Processor #3 received 5
1523Processor #2 received 6
1524Processor #4 received 7
1525Processor #0 received 8
1526Processor #1 received 9
1527Processor #3 received 10
1528```
1529
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001530<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1531
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001532Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1533over the channel that processor coroutines are doing.
1534
1535### Fan-in
1536
1537Multiple coroutines may send to the same channel.
1538For example, let us have a channel of strings, and a suspending function that
1539repeatedly sends a specified string to this channel with a specified delay:
1540
1541```kotlin
1542suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1543 while (true) {
1544 delay(time)
1545 channel.send(s)
1546 }
1547}
1548```
1549
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001550Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001551(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 +03001552
1553```kotlin
1554fun main(args: Array<String>) = runBlocking<Unit> {
1555 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001556 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1557 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001558 repeat(6) { // receive first six
1559 println(channel.receive())
1560 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001561 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001562}
1563```
1564
Roman Elizarove8d79342017-08-29 15:21:21 +03001565> 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 +03001566
1567The output is:
1568
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001569```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001570foo
1571foo
1572BAR!
1573foo
1574foo
1575BAR!
1576```
1577
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001578<!--- TEST -->
1579
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001580### Buffered channels
1581
1582The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1583meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1584if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001585
Roman Elizarov88396732017-09-27 21:30:47 +03001586Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001587specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1588similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1589
1590Take a look at the behavior of the following code:
1591
1592```kotlin
1593fun main(args: Array<String>) = runBlocking<Unit> {
1594 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001595 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001596 repeat(10) {
1597 println("Sending $it") // print before sending each element
1598 channel.send(it) // will suspend when buffer is full
1599 }
1600 }
1601 // don't receive anything... just wait....
1602 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001603 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001604}
1605```
1606
Roman Elizarove8d79342017-08-29 15:21:21 +03001607> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001608
1609It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1610
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001611```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001612Sending 0
1613Sending 1
1614Sending 2
1615Sending 3
1616Sending 4
1617```
1618
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001619<!--- TEST -->
1620
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001621The 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 +03001622
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001623### Channels are fair
1624
1625Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1626multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1627gets the element. In the following example two coroutines "ping" and "pong" are
1628receiving the "ball" object from the shared "table" channel.
1629
1630```kotlin
1631data class Ball(var hits: Int)
1632
1633fun main(args: Array<String>) = runBlocking<Unit> {
1634 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001635 launch(coroutineContext) { player("ping", table) }
1636 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001637 table.send(Ball(0)) // serve the ball
1638 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001639 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001640}
1641
1642suspend fun player(name: String, table: Channel<Ball>) {
1643 for (ball in table) { // receive the ball in a loop
1644 ball.hits++
1645 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001646 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001647 table.send(ball) // send the ball back
1648 }
1649}
1650```
1651
Roman Elizarove8d79342017-08-29 15:21:21 +03001652> 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 +03001653
1654The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1655coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1656received by the "pong" coroutine, because it was already waiting for it:
1657
1658```text
1659ping Ball(hits=1)
1660pong Ball(hits=2)
1661ping Ball(hits=3)
1662pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001663```
1664
1665<!--- TEST -->
1666
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001667Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
1668that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
1669
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001670## Shared mutable state and concurrency
1671
Roman Elizarov66f018c2017-09-29 21:39:03 +03001672Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001673all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1674Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1675but others are unique.
1676
1677### The problem
1678
Roman Elizarov1e459602017-02-27 11:05:17 +03001679Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1680We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001681
Roman Elizarov43e90112017-05-10 11:25:20 +03001682<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
Roman Elizarov1e459602017-02-27 11:05:17 +03001683import kotlin.coroutines.experimental.CoroutineContext
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001684import kotlin.system.measureTimeMillis
1685-->
1686
Roman Elizarov1e459602017-02-27 11:05:17 +03001687<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001688import java.util.concurrent.atomic.AtomicInteger
1689-->
1690
Roman Elizarov1e459602017-02-27 11:05:17 +03001691<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001692import kotlinx.coroutines.experimental.sync.Mutex
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001693import kotlinx.coroutines.experimental.sync.withLock
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001694-->
1695
Roman Elizarov1e459602017-02-27 11:05:17 +03001696<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001697import kotlinx.coroutines.experimental.channels.*
1698-->
1699
1700```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001701suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1702 val n = 1000 // number of coroutines to launch
1703 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001704 val time = measureTimeMillis {
1705 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001706 launch(context) {
1707 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001708 }
1709 }
1710 jobs.forEach { it.join() }
1711 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001712 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001713}
1714```
1715
Roman Elizarov43e90112017-05-10 11:25:20 +03001716<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001717
Roman Elizarov1e459602017-02-27 11:05:17 +03001718We start with a very simple action that increments a shared mutable variable using
1719multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001720
1721```kotlin
1722var counter = 0
1723
1724fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001725 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001726 counter++
1727 }
1728 println("Counter = $counter")
1729}
1730```
1731
Roman Elizarove8d79342017-08-29 15:21:21 +03001732> 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 +03001733
Roman Elizarov1e459602017-02-27 11:05:17 +03001734<!--- TEST LINES_START
1735Completed 1000000 actions in
1736Counter =
1737-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001738
Roman Elizarov1e459602017-02-27 11:05:17 +03001739What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1740increment the `counter` concurrently from multiple threads without any synchronization.
1741
Roman Elizarov43e90112017-05-10 11:25:20 +03001742> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1743`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1744following change:
1745
1746```kotlin
1747val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1748var counter = 0
1749
1750fun main(args: Array<String>) = runBlocking<Unit> {
1751 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1752 counter++
1753 }
1754 println("Counter = $counter")
1755}
1756```
1757
Roman Elizarove8d79342017-08-29 15:21:21 +03001758> 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 +03001759
1760<!--- TEST LINES_START
1761Completed 1000000 actions in
1762Counter =
1763-->
1764
Roman Elizarov1e459602017-02-27 11:05:17 +03001765### Volatiles are of no help
1766
1767There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1768
1769```kotlin
1770@Volatile // in Kotlin `volatile` is an annotation
1771var counter = 0
1772
1773fun main(args: Array<String>) = runBlocking<Unit> {
1774 massiveRun(CommonPool) {
1775 counter++
1776 }
1777 println("Counter = $counter")
1778}
1779```
1780
Roman Elizarove8d79342017-08-29 15:21:21 +03001781> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt)
Roman Elizarov1e459602017-02-27 11:05:17 +03001782
1783<!--- TEST LINES_START
1784Completed 1000000 actions in
1785Counter =
1786-->
1787
1788This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1789linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1790do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001791
1792### Thread-safe data structures
1793
1794The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1795linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1796operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001797In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001798
1799```kotlin
1800var counter = AtomicInteger()
1801
1802fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001803 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001804 counter.incrementAndGet()
1805 }
1806 println("Counter = ${counter.get()}")
1807}
1808```
1809
Roman Elizarove8d79342017-08-29 15:21:21 +03001810> 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 +03001811
Roman Elizarov1e459602017-02-27 11:05:17 +03001812<!--- TEST ARBITRARY_TIME
1813Completed 1000000 actions in xxx ms
1814Counter = 1000000
1815-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001816
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001817This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1818standard data structures and basic operations on them. However, it does not easily scale to complex
1819state or to complex operations that do not have ready-to-use thread-safe implementations.
1820
Roman Elizarov1e459602017-02-27 11:05:17 +03001821### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001822
Roman Elizarov1e459602017-02-27 11:05:17 +03001823_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 +03001824state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1825the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1826single-threaded context:
1827
1828```kotlin
1829val counterContext = newSingleThreadContext("CounterContext")
1830var counter = 0
1831
1832fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001833 massiveRun(CommonPool) { // run each coroutine in CommonPool
1834 run(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001835 counter++
1836 }
1837 }
1838 println("Counter = $counter")
1839}
1840```
1841
Roman Elizarove8d79342017-08-29 15:21:21 +03001842> 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 +03001843
Roman Elizarov1e459602017-02-27 11:05:17 +03001844<!--- TEST ARBITRARY_TIME
1845Completed 1000000 actions in xxx ms
1846Counter = 1000000
1847-->
1848
1849This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
1850from multi-threaded `CommonPool` context to the single-threaded context using [run] block.
1851
1852### Thread confinement coarse-grained
1853
1854In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1855are confined to the single thread. The following example does it like that, running each coroutine in
1856the single-threaded context to start with.
1857
1858```kotlin
1859val counterContext = newSingleThreadContext("CounterContext")
1860var counter = 0
1861
1862fun main(args: Array<String>) = runBlocking<Unit> {
1863 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1864 counter++
1865 }
1866 println("Counter = $counter")
1867}
1868```
1869
Roman Elizarove8d79342017-08-29 15:21:21 +03001870> 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 +03001871
1872<!--- TEST ARBITRARY_TIME
1873Completed 1000000 actions in xxx ms
1874Counter = 1000000
1875-->
1876
1877This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001878
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001879### Mutual exclusion
1880
1881Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1882that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1883Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1884delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1885
Roman Elizarov88396732017-09-27 21:30:47 +03001886There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001887`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
1888
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001889```kotlin
1890val mutex = Mutex()
1891var counter = 0
1892
1893fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001894 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001895 mutex.withLock {
1896 counter++
1897 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001898 }
1899 println("Counter = $counter")
1900}
1901```
1902
Roman Elizarove8d79342017-08-29 15:21:21 +03001903> 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 +03001904
Roman Elizarov1e459602017-02-27 11:05:17 +03001905<!--- TEST ARBITRARY_TIME
1906Completed 1000000 actions in xxx ms
1907Counter = 1000000
1908-->
1909
1910The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
1911where you absolutely must modify some shared state periodically, but there is no natural thread that this state
1912is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001913
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001914### Actors
1915
1916An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
1917and a channel to communicate with other coroutines. A simple actor can be written as a function,
1918but an actor with a complex state is better suited for a class.
1919
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001920There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
1921scope to receive messages from and combines the send channel into the resulting job object, so that a
1922single reference to the actor can be carried around as its handle.
1923
Roman Elizarov256812a2017-07-22 01:00:30 +03001924The first step of using an actor is to define a class of messages that an actor is going to process.
1925Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
1926We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
1927to get its value. The later needs to send a response. A [CompletableDeferred] communication
1928primitive, that represents a single value that will be known (communicated) in the future,
1929is used here for that purpose.
1930
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001931```kotlin
1932// Message types for counterActor
1933sealed class CounterMsg
1934object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03001935class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
1936```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001937
Roman Elizarov256812a2017-07-22 01:00:30 +03001938Then we define a function that launches an actor using an [actor] coroutine builder:
1939
1940```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001941// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03001942fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001943 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001944 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001945 when (msg) {
1946 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03001947 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001948 }
1949 }
1950}
Roman Elizarov256812a2017-07-22 01:00:30 +03001951```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001952
Roman Elizarov256812a2017-07-22 01:00:30 +03001953The main code is straightforward:
1954
1955```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001956fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001957 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03001958 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001959 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001960 }
Roman Elizarov256812a2017-07-22 01:00:30 +03001961 // send a message to get a counter value from an actor
1962 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001963 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03001964 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001965 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001966}
1967```
1968
Roman Elizarove8d79342017-08-29 15:21:21 +03001969> 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 +03001970
Roman Elizarov1e459602017-02-27 11:05:17 +03001971<!--- TEST ARBITRARY_TIME
1972Completed 1000000 actions in xxx ms
1973Counter = 1000000
1974-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001975
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001976It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001977a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
1978works as a solution to the problem of shared mutable state.
1979
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001980Actor is more efficient than locking under load, because in this case it always has work to do and it does not
1981have to switch to a different context at all.
1982
1983> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
1984 with the channel that it receives messages from, while a producer is associated with the channel that it
1985 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03001986
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001987## Select expression
1988
Roman Elizarova84730b2017-02-22 11:58:50 +03001989Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001990the first one that becomes available.
1991
1992<!--- INCLUDE .*/example-select-([0-9]+).kt
1993import kotlinx.coroutines.experimental.channels.*
1994import kotlinx.coroutines.experimental.selects.*
1995-->
1996
1997### Selecting from channels
1998
Roman Elizarov57857202017-03-02 23:17:25 +03001999Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2000
2001<!--- INCLUDE .*/example-select-01.kt
2002import kotlin.coroutines.experimental.CoroutineContext
2003-->
2004
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002005```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002006fun fizz(context: CoroutineContext) = produce<String>(context) {
2007 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002008 delay(300)
2009 send("Fizz")
2010 }
2011}
2012```
2013
Roman Elizarov57857202017-03-02 23:17:25 +03002014And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002015
2016```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002017fun buzz(context: CoroutineContext) = produce<String>(context) {
2018 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002019 delay(500)
2020 send("Buzz!")
2021 }
2022}
2023```
2024
2025Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2026other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002027[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002028
2029```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002030suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002031 select<Unit> { // <Unit> means that this select expression does not produce any result
2032 fizz.onReceive { value -> // this is the first select clause
2033 println("fizz -> '$value'")
2034 }
2035 buzz.onReceive { value -> // this is the second select clause
2036 println("buzz -> '$value'")
2037 }
2038 }
2039}
2040```
2041
Roman Elizarov57857202017-03-02 23:17:25 +03002042Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002043
2044```kotlin
2045fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002046 val fizz = fizz(coroutineContext)
2047 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002048 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002049 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002050 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002051 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002052}
2053```
2054
Roman Elizarove8d79342017-08-29 15:21:21 +03002055> 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 +03002056
2057The result of this code is:
2058
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002059```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002060fizz -> 'Fizz'
2061buzz -> 'Buzz!'
2062fizz -> 'Fizz'
2063fizz -> 'Fizz'
2064buzz -> 'Buzz!'
2065fizz -> 'Fizz'
2066buzz -> 'Buzz!'
2067```
2068
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002069<!--- TEST -->
2070
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002071### Selecting on close
2072
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002073The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed and the corresponding
2074`select` throws an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002075specific 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 +03002076the result of its selected clause:
2077
2078```kotlin
2079suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2080 select<String> {
2081 a.onReceiveOrNull { value ->
2082 if (value == null)
2083 "Channel 'a' is closed"
2084 else
2085 "a -> '$value'"
2086 }
2087 b.onReceiveOrNull { value ->
2088 if (value == null)
2089 "Channel 'b' is closed"
2090 else
2091 "b -> '$value'"
2092 }
2093 }
2094```
2095
Roman Elizarova84730b2017-02-22 11:58:50 +03002096Let's use it with channel `a` that produces "Hello" string four times and
2097channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002098
2099```kotlin
2100fun main(args: Array<String>) = runBlocking<Unit> {
2101 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002102 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002103 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002104 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002105 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002106 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002107 }
2108 repeat(8) { // print first eight results
2109 println(selectAorB(a, b))
2110 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002111 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002112}
2113```
2114
Roman Elizarove8d79342017-08-29 15:21:21 +03002115> 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 +03002116
Roman Elizarova84730b2017-02-22 11:58:50 +03002117The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002118
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002119```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002120a -> 'Hello 0'
2121a -> 'Hello 1'
2122b -> 'World 0'
2123a -> 'Hello 2'
2124a -> 'Hello 3'
2125b -> 'World 1'
2126Channel 'a' is closed
2127Channel 'a' is closed
2128```
2129
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002130<!--- TEST -->
2131
Roman Elizarova84730b2017-02-22 11:58:50 +03002132There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002133
2134First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2135the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002136being 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 +03002137time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2138
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002139The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002140channel is already closed.
2141
2142### Selecting to send
2143
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002144Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002145with a biased nature of selection.
2146
Roman Elizarova84730b2017-02-22 11:58:50 +03002147Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002148the consumers on its primary channel cannot keep up with it:
2149
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002150<!--- INCLUDE
2151import kotlin.coroutines.experimental.CoroutineContext
2152-->
2153
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002154```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002155fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002156 for (num in 1..10) { // produce 10 numbers from 1 to 10
2157 delay(100) // every 100 ms
2158 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002159 onSend(num) {} // Send to the primary channel
2160 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002161 }
2162 }
2163}
2164```
2165
2166Consumer is going to be quite slow, taking 250 ms to process each number:
2167
2168```kotlin
2169fun main(args: Array<String>) = runBlocking<Unit> {
2170 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002171 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002172 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002173 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002174 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002175 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002176 delay(250) // let us digest the consumed number properly, do not hurry
2177 }
2178 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002179 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002180}
2181```
2182
Roman Elizarove8d79342017-08-29 15:21:21 +03002183> 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 +03002184
2185So let us see what happens:
2186
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002187```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002188Consuming 1
2189Side channel has 2
2190Side channel has 3
2191Consuming 4
2192Side channel has 5
2193Side channel has 6
2194Consuming 7
2195Side channel has 8
2196Side channel has 9
2197Consuming 10
2198Done consuming
2199```
2200
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002201<!--- TEST -->
2202
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002203### Selecting deferred values
2204
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002205Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002206Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002207a random delay:
2208
2209<!--- INCLUDE .*/example-select-04.kt
2210import java.util.*
2211-->
2212
2213```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002214fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002215 delay(time.toLong())
2216 "Waited for $time ms"
2217}
2218```
2219
Roman Elizarova84730b2017-02-22 11:58:50 +03002220Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002221
2222```kotlin
2223fun asyncStringsList(): List<Deferred<String>> {
2224 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002225 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002226}
2227```
2228
Roman Elizarova84730b2017-02-22 11:58:50 +03002229Now 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 +03002230that 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 +03002231so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2232of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002233
2234```kotlin
2235fun main(args: Array<String>) = runBlocking<Unit> {
2236 val list = asyncStringsList()
2237 val result = select<String> {
2238 list.withIndex().forEach { (index, deferred) ->
2239 deferred.onAwait { answer ->
2240 "Deferred $index produced answer '$answer'"
2241 }
2242 }
2243 }
2244 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002245 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002246 println("$countActive coroutines are still active")
2247}
2248```
2249
Roman Elizarove8d79342017-08-29 15:21:21 +03002250> 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 +03002251
2252The output is:
2253
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002254```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002255Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300225611 coroutines are still active
2257```
2258
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002259<!--- TEST -->
2260
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002261### Switch over a channel of deferred values
2262
Roman Elizarova84730b2017-02-22 11:58:50 +03002263Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2264deferred 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 +03002265[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002266
2267```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002268fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002269 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002270 while (isActive) { // loop while not cancelled/closed
2271 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2272 input.onReceiveOrNull { update ->
2273 update // replaces next value to wait
2274 }
2275 current.onAwait { value ->
2276 send(value) // send value that current deferred has produced
2277 input.receiveOrNull() // and use the next deferred from the input channel
2278 }
2279 }
2280 if (next == null) {
2281 println("Channel was closed")
2282 break // out of loop
2283 } else {
2284 current = next
2285 }
2286 }
2287}
2288```
2289
2290To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2291
2292```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002293fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002294 delay(time)
2295 str
2296}
2297```
2298
2299The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2300data to it:
2301
2302```kotlin
2303fun main(args: Array<String>) = runBlocking<Unit> {
2304 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002305 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002306 for (s in switchMapDeferreds(chan))
2307 println(s) // print each received string
2308 }
2309 chan.send(asyncString("BEGIN", 100))
2310 delay(200) // enough time for "BEGIN" to be produced
2311 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002312 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002313 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002314 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002315 chan.send(asyncString("END", 500))
2316 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002317 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002318 delay(500) // and wait some time to let it finish
2319}
2320```
2321
Roman Elizarove8d79342017-08-29 15:21:21 +03002322> 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 +03002323
2324The result of this code:
2325
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002326```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002327BEGIN
2328Replace
2329END
2330Channel was closed
2331```
2332
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002333<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002334
Roman Elizarov8db17332017-03-09 12:40:45 +03002335## Further reading
2336
2337* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002338* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002339* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2340* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2341
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002342<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002343<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002344[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2345[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2346[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002347[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002348[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002349[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2350[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002351[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception.html
2352[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002353[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 +03002354[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
2355[run]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
2356[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2357[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002358[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 +03002359[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2360[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002361[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 +03002362[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2363[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002364[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002365[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002366[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov43e3af72017-07-21 16:01:31 +03002367[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 +03002368[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002369[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2370[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 +03002371[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002372[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002373[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
2374[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 +03002375[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002376[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 +03002377<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002378[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002379[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2380[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 +03002381[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002382<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002383[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002384[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2385[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2386[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 +03002387[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002388[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002389[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002390[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002391[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive.html
2392[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2393[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 +03002394<!--- INDEX kotlinx.coroutines.experimental.selects -->
2395[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002396<!--- END -->