blob: 59b86b81eb600ad0a1bd66c58b9c9d2dc96b84e1 [file] [log] [blame] [view]
Roman Elizarov43e90112017-05-10 11:25:20 +03001<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
Roman Elizarova5e653f2017-02-13 13:49:55 +03002/*
3 * Copyright 2016-2017 JetBrains s.r.o.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Roman Elizarovf16fd272017-02-07 11:26:00 +030017
Roman Elizarova5e653f2017-02-13 13:49:55 +030018// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
19package guide.$$1.example$$2
Roman Elizarovf16fd272017-02-07 11:26:00 +030020
Roman Elizarova5e653f2017-02-13 13:49:55 +030021import kotlinx.coroutines.experimental.*
Roman Elizarovf16fd272017-02-07 11:26:00 +030022-->
Roman Elizarove8d79342017-08-29 15:21:21 +030023<!--- KNIT core/kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
24<!--- TEST_OUT core/kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt
Roman Elizarov731f0ad2017-02-22 20:48:45 +030025// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
26package guide.test
27
28import org.junit.Test
29
30class GuideTest {
31-->
Roman Elizarovf16fd272017-02-07 11:26:00 +030032
Roman Elizarov7deefb82017-01-31 10:33:17 +030033# Guide to kotlinx.coroutines by example
34
Roman Elizarova4d45d22017-11-20 16:47:09 +030035This is a guide on core features of `kotlinx.coroutines` with a series of examples.
Roman Elizarov7deefb82017-01-31 10:33:17 +030036
Roman Elizarov2a638922017-03-04 10:22:43 +030037## Introduction and setup
38
39Kotlin, as a language, provides only minimal low-level APIs in its standard library to enable various other
40libraries to utilize coroutines. Unlike many other languages with similar capabilities, `async` and `await`
41are not keywords in Kotlin and are not even part of its standard library.
42
Robert Hencke497d3432017-04-11 00:14:29 -040043`kotlinx.coroutines` is one such rich library. It contains a number of high-level
Roman Elizarova4d45d22017-11-20 16:47:09 +030044coroutine-enabled primitives that this guide covers, including `launch`, `async` and others.
Roman Elizarov2a638922017-03-04 10:22:43 +030045You need to add a dependency on `kotlinx-coroutines-core` module as explained
46[here](README.md#using-in-your-projects) to use primitives from this guide in your projects.
47
Roman Elizarov1293ccd2017-02-01 18:49:54 +030048## Table of contents
49
Roman Elizarovfa7723e2017-02-06 11:17:51 +030050<!--- TOC -->
51
Roman Elizarov1293ccd2017-02-01 18:49:54 +030052* [Coroutine basics](#coroutine-basics)
53 * [Your first coroutine](#your-first-coroutine)
54 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
55 * [Waiting for a job](#waiting-for-a-job)
56 * [Extract function refactoring](#extract-function-refactoring)
57 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
58 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
59* [Cancellation and timeouts](#cancellation-and-timeouts)
60 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
61 * [Cancellation is cooperative](#cancellation-is-cooperative)
62 * [Making computation code cancellable](#making-computation-code-cancellable)
63 * [Closing resources with finally](#closing-resources-with-finally)
64 * [Run non-cancellable block](#run-non-cancellable-block)
65 * [Timeout](#timeout)
66* [Composing suspending functions](#composing-suspending-functions)
67 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030068 * [Concurrent using async](#concurrent-using-async)
69 * [Lazily started async](#lazily-started-async)
70 * [Async-style functions](#async-style-functions)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030071* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030072 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030073 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
74 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
75 * [Jumping between threads](#jumping-between-threads)
76 * [Job in the context](#job-in-the-context)
77 * [Children of a coroutine](#children-of-a-coroutine)
78 * [Combining contexts](#combining-contexts)
Roman Elizarov8b38fa22017-09-27 17:44:31 +030079 * [Parental responsibilities](#parental-responsibilities)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030080 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030081 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030082* [Channels](#channels)
83 * [Channel basics](#channel-basics)
84 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
85 * [Building channel producers](#building-channel-producers)
86 * [Pipelines](#pipelines)
87 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
88 * [Fan-out](#fan-out)
89 * [Fan-in](#fan-in)
90 * [Buffered channels](#buffered-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030091 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030092* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
93 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030094 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030095 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030096 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
97 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030098 * [Mutual exclusion](#mutual-exclusion)
99 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300100* [Select expression](#select-expression)
101 * [Selecting from channels](#selecting-from-channels)
102 * [Selecting on close](#selecting-on-close)
103 * [Selecting to send](#selecting-to-send)
104 * [Selecting deferred values](#selecting-deferred-values)
105 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +0300106* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300107
Roman Elizarova5e653f2017-02-13 13:49:55 +0300108<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300109
110## Coroutine basics
111
112This section covers basic coroutine concepts.
113
114### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300115
116Run the following code:
117
118```kotlin
119fun main(args: Array<String>) {
Roman Elizarova4d45d22017-11-20 16:47:09 +0300120 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300121 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
122 println("World!") // print after delay
123 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300124 println("Hello,") // main thread continues while coroutine is delayed
Roman Elizarov7deefb82017-01-31 10:33:17 +0300125 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
126}
127```
128
Roman Elizarove8d79342017-08-29 15:21:21 +0300129> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300130
131Run this code:
132
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300133```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300134Hello,
135World!
136```
137
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300138<!--- TEST -->
139
Roman Elizarov419a6c82017-02-09 18:36:22 +0300140Essentially, coroutines are light-weight threads.
141They are launched with [launch] _coroutine builder_.
142You can achieve the same result replacing
Roman Elizarov66f018c2017-09-29 21:39:03 +0300143`launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300144
Roman Elizarov66f018c2017-09-29 21:39:03 +0300145If you start by replacing `launch` by `thread`, the compiler produces the following error:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300146
147```
148Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
149```
150
Roman Elizarov419a6c82017-02-09 18:36:22 +0300151That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300152coroutine and it can be only used from a coroutine.
153
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300154### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300155
Roman Elizarova4d45d22017-11-20 16:47:09 +0300156The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
157It is easy to get lost which one is blocking and which one is not.
158Let's be explicit about blocking using [runBlocking] coroutine builder:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300159
160```kotlin
Roman Elizarova4d45d22017-11-20 16:47:09 +0300161fun main(args: Array<String>) {
162 launch { // launch new coroutine in background and continue
Roman Elizarov7deefb82017-01-31 10:33:17 +0300163 delay(1000L)
164 println("World!")
165 }
Roman Elizarova4d45d22017-11-20 16:47:09 +0300166 println("Hello,") // main thread continues here immediately
167 runBlocking { // but this expression blocks the main thread
168 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
169 }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300170}
171```
172
Roman Elizarove8d79342017-08-29 15:21:21 +0300173> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300174
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300175<!--- TEST
176Hello,
177World!
178-->
179
Roman Elizarov419a6c82017-02-09 18:36:22 +0300180The result is the same, but this code uses only non-blocking [delay].
Tylos81451de2017-12-17 21:33:17 +0100181The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300182
Roman Elizarova4d45d22017-11-20 16:47:09 +0300183This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
184the execution of the main function:
185
186```kotlin
187fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
188 launch { // launch new coroutine in background and continue
189 delay(1000L)
190 println("World!")
191 }
192 println("Hello,") // main coroutine continues here immediately
193 delay(2000L) // delaying for 2 seconds to keep JVM alive
194}
195```
196
197> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02b.kt)
198
199<!--- TEST
200Hello,
201World!
202-->
203
204Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
205We explicitly specify its `Unit` return type, because a well-formed `main` function in Kotlin has to return `Unit`.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300206
207This is also a way to write unit-tests for suspending functions:
208
209```kotlin
210class MyTest {
211 @Test
212 fun testMySuspendingFunction() = runBlocking<Unit> {
213 // here we can use suspending functions using any assertion style that we like
214 }
215}
216```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300217
218<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300219
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300220### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300221
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300222Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300223wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300224
225```kotlin
226fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300227 val job = launch { // launch new coroutine and keep a reference to its Job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300228 delay(1000L)
229 println("World!")
230 }
231 println("Hello,")
232 job.join() // wait until child coroutine completes
233}
234```
235
Roman Elizarove8d79342017-08-29 15:21:21 +0300236> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300237
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300238<!--- TEST
239Hello,
240World!
241-->
242
Roman Elizarov7deefb82017-01-31 10:33:17 +0300243Now the result is still the same, but the code of the main coroutine is not tied to the duration of
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300244the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300245
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300246### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300247
Roman Elizarov66f018c2017-09-29 21:39:03 +0300248Let's extract the block of code inside `launch { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300249perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
250That is your first _suspending function_. Suspending functions can be used inside coroutines
251just like regular functions, but their additional feature is that they can, in turn,
252use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
253
254```kotlin
255fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300256 val job = launch { doWorld() }
Roman Elizarov7deefb82017-01-31 10:33:17 +0300257 println("Hello,")
258 job.join()
259}
260
261// this is your first suspending function
262suspend fun doWorld() {
263 delay(1000L)
264 println("World!")
265}
266```
267
Roman Elizarove8d79342017-08-29 15:21:21 +0300268> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300269
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300270<!--- TEST
271Hello,
272World!
273-->
274
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300275### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300276
277Run the following code:
278
279```kotlin
280fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300281 val jobs = List(100_000) { // launch a lot of coroutines and list their jobs
282 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300283 delay(1000L)
284 print(".")
285 }
286 }
287 jobs.forEach { it.join() } // wait for all jobs to complete
288}
289```
290
Roman Elizarove8d79342017-08-29 15:21:21 +0300291> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300292
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300293<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
294
Roman Elizarov66f018c2017-09-29 21:39:03 +0300295It launches 100K coroutines and, after a second, each coroutine prints a dot.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300296Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
297
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300298### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300299
300The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300301returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300302
303```kotlin
304fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300305 launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300306 repeat(1000) { i ->
307 println("I'm sleeping $i ...")
308 delay(500L)
309 }
310 }
311 delay(1300L) // just quit after delay
312}
313```
314
Roman Elizarove8d79342017-08-29 15:21:21 +0300315> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300316
317You can run and see that it prints three lines and terminates:
318
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300319```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300320I'm sleeping 0 ...
321I'm sleeping 1 ...
322I'm sleeping 2 ...
323```
324
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300325<!--- TEST -->
326
Roman Elizarov7deefb82017-01-31 10:33:17 +0300327Active coroutines do not keep the process alive. They are like daemon threads.
328
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300329## Cancellation and timeouts
330
331This section covers coroutine cancellation and timeouts.
332
333### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300334
335In small application the return from "main" method might sound like a good idea to get all coroutines
336implicitly terminated. In a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300337The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300338
339```kotlin
340fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300341 val job = launch {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300342 repeat(1000) { i ->
343 println("I'm sleeping $i ...")
344 delay(500L)
345 }
346 }
347 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300348 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300349 job.cancel() // cancels the job
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300350 job.join() // waits for job's completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300351 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300352}
353```
354
Roman Elizarove8d79342017-08-29 15:21:21 +0300355> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300356
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300357It produces the following output:
358
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300359```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300360I'm sleeping 0 ...
361I'm sleeping 1 ...
362I'm sleeping 2 ...
363main: I'm tired of waiting!
364main: Now I can quit.
365```
366
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300367<!--- TEST -->
368
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300369As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
Roman Elizarov88396732017-09-27 21:30:47 +0300370There is also a [Job] extension function [cancelAndJoin]
371that combines [cancel][Job.cancel] and [join][Job.join] invocations.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300372
373### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300374
Tair Rzayevaf734622017-02-01 22:30:16 +0200375Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300376All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300377coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300378a computation and does not check for cancellation, then it cannot be cancelled, like the following
379example shows:
380
381```kotlin
382fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700383 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300384 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700385 var nextPrintTime = startTime
Roman Elizarov7deefb82017-01-31 10:33:17 +0300386 var i = 0
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300387 while (i < 5) { // computation loop, just wastes CPU
Roman Elizarov24cd6542017-08-03 21:20:04 -0700388 // print a message twice a second
389 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarov7deefb82017-01-31 10:33:17 +0300390 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300391 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300392 }
393 }
394 }
395 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300396 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300397 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300398 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300399}
400```
401
Roman Elizarove8d79342017-08-29 15:21:21 +0300402> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300403
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300404Run it to see that it continues to print "I'm sleeping" even after cancellation
405until the job completes by itself after five iterations.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300406
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300407<!--- TEST
408I'm sleeping 0 ...
409I'm sleeping 1 ...
410I'm sleeping 2 ...
411main: I'm tired of waiting!
412I'm sleeping 3 ...
413I'm sleeping 4 ...
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300414main: Now I can quit.
415-->
416
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300417### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300418
419There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov66f018c2017-09-29 21:39:03 +0300420invoke a suspending function that checks for cancellation. There is a [yield] function that is a good choice for that purpose.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300421The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300422
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300423Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300424
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300425```kotlin
426fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700427 val startTime = System.currentTimeMillis()
Roman Elizarov66f018c2017-09-29 21:39:03 +0300428 val job = launch {
Roman Elizarov24cd6542017-08-03 21:20:04 -0700429 var nextPrintTime = startTime
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300430 var i = 0
431 while (isActive) { // cancellable computation loop
Roman Elizarov24cd6542017-08-03 21:20:04 -0700432 // print a message twice a second
433 if (System.currentTimeMillis() >= nextPrintTime) {
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300434 println("I'm sleeping ${i++} ...")
Roman Elizarov24cd6542017-08-03 21:20:04 -0700435 nextPrintTime += 500L
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300436 }
437 }
438 }
439 delay(1300L) // delay a bit
440 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300441 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300442 println("main: Now I can quit.")
443}
444```
445
Roman Elizarove8d79342017-08-29 15:21:21 +0300446> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300447
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300448As you can see, now this loop is cancelled. [isActive][CoroutineScope.isActive] is a property that is available inside
Roman Elizarov419a6c82017-02-09 18:36:22 +0300449the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300450
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300451<!--- TEST
452I'm sleeping 0 ...
453I'm sleeping 1 ...
454I'm sleeping 2 ...
455main: I'm tired of waiting!
456main: Now I can quit.
457-->
458
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300459### Closing resources with finally
460
Roman Elizarov419a6c82017-02-09 18:36:22 +0300461Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarov66f018c2017-09-29 21:39:03 +0300462all the usual way. For example, `try {...} finally {...}` expression and Kotlin `use` function execute their
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300463finalization actions normally when coroutine is cancelled:
464
465```kotlin
466fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300467 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300468 try {
469 repeat(1000) { i ->
470 println("I'm sleeping $i ...")
471 delay(500L)
472 }
473 } finally {
474 println("I'm running finally")
475 }
476 }
477 delay(1300L) // delay a bit
478 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300479 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300480 println("main: Now I can quit.")
481}
482```
483
Roman Elizarove8d79342017-08-29 15:21:21 +0300484> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300485
Roman Elizarov88396732017-09-27 21:30:47 +0300486Both [join][Job.join] and [cancelAndJoin] wait for all the finalization actions to complete,
487so the example above produces the following output:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300488
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300489```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300490I'm sleeping 0 ...
491I'm sleeping 1 ...
492I'm sleeping 2 ...
493main: I'm tired of waiting!
494I'm running finally
495main: Now I can quit.
496```
497
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300498<!--- TEST -->
499
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300500### Run non-cancellable block
501
502Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300503[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300504problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
505communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
506rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300507`withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300508
509```kotlin
510fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300511 val job = launch {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300512 try {
513 repeat(1000) { i ->
514 println("I'm sleeping $i ...")
515 delay(500L)
516 }
517 } finally {
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300518 withContext(NonCancellable) {
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300519 println("I'm running finally")
520 delay(1000L)
521 println("And I've just delayed for 1 sec because I'm non-cancellable")
522 }
523 }
524 }
525 delay(1300L) // delay a bit
526 println("main: I'm tired of waiting!")
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300527 job.cancelAndJoin() // cancels the job and waits for its completion
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300528 println("main: Now I can quit.")
529}
530```
531
Roman Elizarove8d79342017-08-29 15:21:21 +0300532> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300533
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300534<!--- TEST
535I'm sleeping 0 ...
536I'm sleeping 1 ...
537I'm sleeping 2 ...
538main: I'm tired of waiting!
539I'm running finally
540And I've just delayed for 1 sec because I'm non-cancellable
541main: Now I can quit.
542-->
543
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300544### Timeout
545
546The most obvious reason to cancel coroutine execution in practice,
547is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300548While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
549the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300550Look at the following example:
551
552```kotlin
553fun main(args: Array<String>) = runBlocking<Unit> {
554 withTimeout(1300L) {
555 repeat(1000) { i ->
556 println("I'm sleeping $i ...")
557 delay(500L)
558 }
559 }
560}
561```
562
Roman Elizarove8d79342017-08-29 15:21:21 +0300563> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300564
565It produces the following output:
566
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300567```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300568I'm sleeping 0 ...
569I'm sleeping 1 ...
570I'm sleeping 2 ...
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300571Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300572```
573
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300574<!--- TEST STARTS_WITH -->
575
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300576The `TimeoutCancellationException` that is thrown by [withTimeout] is a subclass of [CancellationException].
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300577We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300578inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300579However, in this example we have used `withTimeout` right inside the `main` function.
580
581Because cancellation is just an exception, all the resources will be closed in a usual way.
Roman Elizarov63f6ea22017-09-06 18:42:34 +0300582You can wrap the code with timeout in `try {...} catch (e: TimeoutCancellationException) {...}` block if
583you need to do some additional action specifically on any kind of timeout or use [withTimeoutOrNull] function
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300584that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
585
586```kotlin
587fun main(args: Array<String>) = runBlocking<Unit> {
588 val result = withTimeoutOrNull(1300L) {
589 repeat(1000) { i ->
590 println("I'm sleeping $i ...")
591 delay(500L)
592 }
593 "Done" // will get cancelled before it produces this result
594 }
595 println("Result is $result")
596}
597```
598
599> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-07.kt)
600
601There is no longer an exception when running this code:
602
603```text
604I'm sleeping 0 ...
605I'm sleeping 1 ...
606I'm sleeping 2 ...
607Result is null
608```
609
610<!--- TEST -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300611
612## Composing suspending functions
613
614This section covers various approaches to composition of suspending functions.
615
616### Sequential by default
617
618Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300619remote service call or computation. We just pretend they are useful, but actually each one just
620delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300621
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300622<!--- INCLUDE .*/example-compose-([0-9]+).kt
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?
Ronen Sabagd2d42ea2017-12-24 21:55:06 +0200642In practice we do this if we use the results of the first function to make a decision on whether we need
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300643to invoke the second one or to decide on how to invoke it.
644
645We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300646code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300647time it takes to execute both suspending functions:
648
649```kotlin
650fun main(args: Array<String>) = runBlocking<Unit> {
651 val time = measureTimeMillis {
652 val one = doSomethingUsefulOne()
653 val two = doSomethingUsefulTwo()
654 println("The answer is ${one + two}")
655 }
656 println("Completed in $time ms")
657}
658```
659
Roman Elizarove8d79342017-08-29 15:21:21 +0300660> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300661
662It produces something like this:
663
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300664```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300665The answer is 42
666Completed in 2017 ms
667```
668
Roman Elizarov35d2c342017-07-20 14:54:39 +0300669<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300670
Roman Elizarov32d95322017-02-09 15:57:31 +0300671### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300672
673What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300674we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300675
Roman Elizarov419a6c82017-02-09 18:36:22 +0300676Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
677that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
678does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300679that represents a promise to provide a result later. You can use `.await()` on a deferred value to get its eventual result,
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300680but `Deferred` is also a `Job`, so you can cancel it if needed.
681
682```kotlin
683fun main(args: Array<String>) = runBlocking<Unit> {
684 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300685 val one = async { doSomethingUsefulOne() }
686 val two = async { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300687 println("The answer is ${one.await() + two.await()}")
688 }
689 println("Completed in $time ms")
690}
691```
692
Roman Elizarove8d79342017-08-29 15:21:21 +0300693> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300694
695It produces something like this:
696
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300697```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300698The answer is 42
699Completed in 1017 ms
700```
701
Roman Elizarov35d2c342017-07-20 14:54:39 +0300702<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300703
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300704This is twice as fast, because we have concurrent execution of two coroutines.
705Note, that concurrency with coroutines is always explicit.
706
Roman Elizarov32d95322017-02-09 15:57:31 +0300707### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300708
Roman Elizarov66f018c2017-09-29 21:39:03 +0300709There is a laziness option to [async] using an optional `start` parameter with a value of [CoroutineStart.LAZY].
Roman Elizarov419a6c82017-02-09 18:36:22 +0300710It starts coroutine only when its result is needed by some
711[await][Deferred.await] or if a [start][Job.start] function
Roman Elizarov32d95322017-02-09 15:57:31 +0300712is invoked. Run the following example that differs from the previous one only by this option:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300713
714```kotlin
715fun main(args: Array<String>) = runBlocking<Unit> {
716 val time = measureTimeMillis {
Roman Elizarov66f018c2017-09-29 21:39:03 +0300717 val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
718 val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300719 println("The answer is ${one.await() + two.await()}")
720 }
721 println("Completed in $time ms")
722}
723```
724
Roman Elizarove8d79342017-08-29 15:21:21 +0300725> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300726
727It produces something like this:
728
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300729```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300730The answer is 42
731Completed in 2017 ms
732```
733
Roman Elizarov35d2c342017-07-20 14:54:39 +0300734<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300735
Roman Elizarov32d95322017-02-09 15:57:31 +0300736So, we are back to sequential execution, because we _first_ start and await for `one`, _and then_ start and await
737for `two`. It is not the intended use-case for laziness. It is designed as a replacement for
738the standard `lazy` function in cases when computation of the value involves suspending functions.
739
740### Async-style functions
741
742We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300743_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Marcin Moskała7e94e702018-01-29 18:39:02 +0100744"Async" suffix to highlight the fact that they only start asynchronous computation and one needs
745to use the resulting deferred value to get the result.
Roman Elizarov32d95322017-02-09 15:57:31 +0300746
747```kotlin
Marcin Moskała7e94e702018-01-29 18:39:02 +0100748// The result type of somethingUsefulOneAsync is Deferred<Int>
749fun somethingUsefulOneAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300750 doSomethingUsefulOne()
751}
752
Marcin Moskała7e94e702018-01-29 18:39:02 +0100753// The result type of somethingUsefulTwoAsync is Deferred<Int>
754fun somethingUsefulTwoAsync() = async {
Roman Elizarov32d95322017-02-09 15:57:31 +0300755 doSomethingUsefulTwo()
756}
757```
758
Marcin Moskała7e94e702018-01-29 18:39:02 +0100759Note, that these `xxxAsync` functions are **not** _suspending_ functions. They can be used from anywhere.
Roman Elizarov32d95322017-02-09 15:57:31 +0300760However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
761with the invoking code.
762
763The following example shows their use outside of coroutine:
764
765```kotlin
766// note, that we don't have `runBlocking` to the right of `main` in this example
767fun main(args: Array<String>) {
768 val time = measureTimeMillis {
769 // we can initiate async actions outside of a coroutine
Marcin Moskała7e94e702018-01-29 18:39:02 +0100770 val one = somethingUsefulOneAsync()
771 val two = somethingUsefulTwoAsync()
Roman Elizarov32d95322017-02-09 15:57:31 +0300772 // but waiting for a result must involve either suspending or blocking.
773 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
774 runBlocking {
775 println("The answer is ${one.await() + two.await()}")
776 }
777 }
778 println("Completed in $time ms")
779}
780```
781
Roman Elizarove8d79342017-08-29 15:21:21 +0300782> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300783
Roman Elizarov35d2c342017-07-20 14:54:39 +0300784<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300785The answer is 42
786Completed in 1085 ms
787-->
788
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300789## Coroutine context and dispatchers
790
Roman Elizarov66f018c2017-09-29 21:39:03 +0300791Coroutines always execute in some context which is represented by the value of
792[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
793type, defined in the Kotlin standard library.
794
795The coroutine context is a set of various elements. The main elements are the [Job] of the coroutine,
796which we've seen before, and its dispatcher, which is covered in this section.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300797
798### Dispatchers and threads
799
Roman Elizarov66f018c2017-09-29 21:39:03 +0300800Coroutine context includes a _coroutine dispatcher_ (see [CoroutineDispatcher]) that determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300801the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
Roman Elizarov66f018c2017-09-29 21:39:03 +0300802to a specific thread, dispatch it to a thread pool, or let it run unconfined.
803
804All coroutines builders like [launch] and [async] accept an optional
805[CoroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/-coroutine-context/)
806parameter that can be used to explicitly specify the dispatcher for new coroutine and other context elements.
807
808Try the following example:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300809
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
Charles Muchenefa13beb2018-01-08 16:56:54 +0300844as `launch(DefaultDispatcher) { ... }`, which is the same as `launch(CommonPool) { ... }`.
Roman Elizarov66f018c2017-09-29 21:39:03 +0300845
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")
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300960 withContext(ctx2) {
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +0800961 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
Roman Elizarovf9e13f52017-12-21 12:23:15 +0300973the other one is using [withContext] function to change a context of a coroutine while still staying in the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +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 Elizarov3e387b82017-12-04 13:49:11 +03001428We use [cancelChildren][kotlin.coroutines.experimental.CoroutineContext.cancelChildren]
1429extension function to cancel all the children coroutines.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001430
1431```kotlin
1432fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001433 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001434 for (i in 1..10) {
1435 val prime = cur.receive()
1436 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001437 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001438 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001439 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001440}
1441```
1442
Roman Elizarove8d79342017-08-29 15:21:21 +03001443> 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 +03001444
1445The output of this code is:
1446
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001447```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030014482
14493
14505
14517
145211
145313
145417
145519
145623
145729
1458```
1459
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001460<!--- TEST -->
1461
Roman Elizarov66f018c2017-09-29 21:39:03 +03001462Note, that you can build the same pipeline using
1463[`buildIterator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/build-iterator.html)
1464coroutine builder from the standard library.
Roman Elizarova5e653f2017-02-13 13:49:55 +03001465Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001466`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1467However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1468multiple CPU cores if you run it in [CommonPool] context.
1469
Roman Elizarova5e653f2017-02-13 13:49:55 +03001470Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001471other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1472built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarov66f018c2017-09-29 21:39:03 +03001473`produce`, which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001474
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001475### Fan-out
1476
1477Multiple coroutines may receive from the same channel, distributing work between themselves.
1478Let us start with a producer coroutine that is periodically producing integers
1479(ten numbers per second):
1480
1481```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001482fun produceNumbers() = produce<Int> {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001483 var x = 1 // start from 1
1484 while (true) {
1485 send(x++) // produce next
1486 delay(100) // wait 0.1s
1487 }
1488}
1489```
1490
1491Then we can have several processor coroutines. In this example, they just print their id and
1492received number:
1493
1494```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03001495fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
Roman Elizarov86349be2017-03-17 16:47:37 +03001496 channel.consumeEach {
1497 println("Processor #$id received $it")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001498 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001499}
1500```
1501
Roman Elizarov35d2c342017-07-20 14:54:39 +03001502Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001503
1504```kotlin
1505fun main(args: Array<String>) = runBlocking<Unit> {
1506 val producer = produceNumbers()
1507 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001508 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001509 producer.cancel() // cancel producer coroutine and thus kill them all
1510}
1511```
1512
Roman Elizarove8d79342017-08-29 15:21:21 +03001513> 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 +03001514
1515The output will be similar to the the following one, albeit the processor ids that receive
1516each specific integer may be different:
1517
1518```
1519Processor #2 received 1
1520Processor #4 received 2
1521Processor #0 received 3
1522Processor #1 received 4
1523Processor #3 received 5
1524Processor #2 received 6
1525Processor #4 received 7
1526Processor #0 received 8
1527Processor #1 received 9
1528Processor #3 received 10
1529```
1530
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001531<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1532
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001533Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1534over the channel that processor coroutines are doing.
1535
1536### Fan-in
1537
1538Multiple coroutines may send to the same channel.
1539For example, let us have a channel of strings, and a suspending function that
1540repeatedly sends a specified string to this channel with a specified delay:
1541
1542```kotlin
1543suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1544 while (true) {
1545 delay(time)
1546 channel.send(s)
1547 }
1548}
1549```
1550
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001551Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001552(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 +03001553
1554```kotlin
1555fun main(args: Array<String>) = runBlocking<Unit> {
1556 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001557 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1558 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001559 repeat(6) { // receive first six
1560 println(channel.receive())
1561 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001562 coroutineContext.cancelChildren() // cancel all children to let main finish
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001563}
1564```
1565
Roman Elizarove8d79342017-08-29 15:21:21 +03001566> 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 +03001567
1568The output is:
1569
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001570```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001571foo
1572foo
1573BAR!
1574foo
1575foo
1576BAR!
1577```
1578
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001579<!--- TEST -->
1580
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001581### Buffered channels
1582
1583The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1584meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1585if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001586
Roman Elizarov88396732017-09-27 21:30:47 +03001587Both [Channel()] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001588specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1589similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1590
1591Take a look at the behavior of the following code:
1592
1593```kotlin
1594fun main(args: Array<String>) = runBlocking<Unit> {
1595 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001596 val sender = launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001597 repeat(10) {
1598 println("Sending $it") // print before sending each element
1599 channel.send(it) // will suspend when buffer is full
1600 }
1601 }
1602 // don't receive anything... just wait....
1603 delay(1000)
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001604 sender.cancel() // cancel sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001605}
1606```
1607
Roman Elizarove8d79342017-08-29 15:21:21 +03001608> 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 +03001609
1610It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1611
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001612```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001613Sending 0
1614Sending 1
1615Sending 2
1616Sending 3
1617Sending 4
1618```
1619
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001620<!--- TEST -->
1621
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001622The 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 +03001623
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001624### Channels are fair
1625
1626Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1627multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1628gets the element. In the following example two coroutines "ping" and "pong" are
1629receiving the "ball" object from the shared "table" channel.
1630
1631```kotlin
1632data class Ball(var hits: Int)
1633
1634fun main(args: Array<String>) = runBlocking<Unit> {
1635 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001636 launch(coroutineContext) { player("ping", table) }
1637 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001638 table.send(Ball(0)) // serve the ball
1639 delay(1000) // delay 1 second
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001640 coroutineContext.cancelChildren() // game over, cancel them
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001641}
1642
1643suspend fun player(name: String, table: Channel<Ball>) {
1644 for (ball in table) { // receive the ball in a loop
1645 ball.hits++
1646 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001647 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001648 table.send(ball) // send the ball back
1649 }
1650}
1651```
1652
Roman Elizarove8d79342017-08-29 15:21:21 +03001653> You can get full code [here](core/kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001654
1655The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1656coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1657received by the "pong" coroutine, because it was already waiting for it:
1658
1659```text
1660ping Ball(hits=1)
1661pong Ball(hits=2)
1662ping Ball(hits=3)
1663pong Ball(hits=4)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001664```
1665
1666<!--- TEST -->
1667
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001668Note, that sometimes channels may produce executions that look unfair due to the nature of the executor
1669that is being used. See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/111) for details.
1670
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001671## Shared mutable state and concurrency
1672
Roman Elizarov66f018c2017-09-29 21:39:03 +03001673Coroutines can be executed concurrently using a multi-threaded dispatcher like the default [CommonPool]. It presents
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001674all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1675Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1676but others are unique.
1677
1678### The problem
1679
Roman Elizarov1e459602017-02-27 11:05:17 +03001680Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1681We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001682
Roman Elizarov43e90112017-05-10 11:25:20 +03001683<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
Roman Elizarov1e459602017-02-27 11:05:17 +03001684import kotlin.coroutines.experimental.CoroutineContext
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001685import kotlin.system.measureTimeMillis
1686-->
1687
Roman Elizarov1e459602017-02-27 11:05:17 +03001688<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001689import java.util.concurrent.atomic.AtomicInteger
1690-->
1691
Roman Elizarov1e459602017-02-27 11:05:17 +03001692<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001693import kotlinx.coroutines.experimental.sync.Mutex
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001694import kotlinx.coroutines.experimental.sync.withLock
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001695-->
1696
Roman Elizarov1e459602017-02-27 11:05:17 +03001697<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001698import kotlinx.coroutines.experimental.channels.*
1699-->
1700
1701```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001702suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1703 val n = 1000 // number of coroutines to launch
1704 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001705 val time = measureTimeMillis {
1706 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001707 launch(context) {
1708 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001709 }
1710 }
1711 jobs.forEach { it.join() }
1712 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001713 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001714}
1715```
1716
Roman Elizarov43e90112017-05-10 11:25:20 +03001717<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001718
Roman Elizarov1e459602017-02-27 11:05:17 +03001719We start with a very simple action that increments a shared mutable variable using
1720multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001721
1722```kotlin
1723var counter = 0
1724
1725fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001726 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001727 counter++
1728 }
1729 println("Counter = $counter")
1730}
1731```
1732
Roman Elizarove8d79342017-08-29 15:21:21 +03001733> 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 +03001734
Roman Elizarov1e459602017-02-27 11:05:17 +03001735<!--- TEST LINES_START
1736Completed 1000000 actions in
1737Counter =
1738-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001739
Roman Elizarov1e459602017-02-27 11:05:17 +03001740What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1741increment the `counter` concurrently from multiple threads without any synchronization.
1742
Roman Elizarov43e90112017-05-10 11:25:20 +03001743> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1744`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1745following change:
1746
1747```kotlin
1748val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1749var counter = 0
1750
1751fun main(args: Array<String>) = runBlocking<Unit> {
1752 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1753 counter++
1754 }
1755 println("Counter = $counter")
1756}
1757```
1758
Roman Elizarove8d79342017-08-29 15:21:21 +03001759> 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 +03001760
1761<!--- TEST LINES_START
1762Completed 1000000 actions in
1763Counter =
1764-->
1765
Roman Elizarov1e459602017-02-27 11:05:17 +03001766### Volatiles are of no help
1767
1768There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1769
1770```kotlin
1771@Volatile // in Kotlin `volatile` is an annotation
1772var counter = 0
1773
1774fun main(args: Array<String>) = runBlocking<Unit> {
1775 massiveRun(CommonPool) {
1776 counter++
1777 }
1778 println("Counter = $counter")
1779}
1780```
1781
Roman Elizarove8d79342017-08-29 15:21:21 +03001782> 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 +03001783
1784<!--- TEST LINES_START
1785Completed 1000000 actions in
1786Counter =
1787-->
1788
1789This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1790linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1791do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001792
1793### Thread-safe data structures
1794
1795The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1796linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1797operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001798In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001799
1800```kotlin
1801var counter = AtomicInteger()
1802
1803fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001804 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001805 counter.incrementAndGet()
1806 }
1807 println("Counter = ${counter.get()}")
1808}
1809```
1810
Roman Elizarove8d79342017-08-29 15:21:21 +03001811> 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 +03001812
Roman Elizarov1e459602017-02-27 11:05:17 +03001813<!--- TEST ARBITRARY_TIME
1814Completed 1000000 actions in xxx ms
1815Counter = 1000000
1816-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001817
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001818This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1819standard data structures and basic operations on them. However, it does not easily scale to complex
1820state or to complex operations that do not have ready-to-use thread-safe implementations.
1821
Roman Elizarov1e459602017-02-27 11:05:17 +03001822### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001823
Roman Elizarov1e459602017-02-27 11:05:17 +03001824_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 +03001825state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1826the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1827single-threaded context:
1828
1829```kotlin
1830val counterContext = newSingleThreadContext("CounterContext")
1831var counter = 0
1832
1833fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001834 massiveRun(CommonPool) { // run each coroutine in CommonPool
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001835 withContext(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001836 counter++
1837 }
1838 }
1839 println("Counter = $counter")
1840}
1841```
1842
Roman Elizarove8d79342017-08-29 15:21:21 +03001843> 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 +03001844
Roman Elizarov1e459602017-02-27 11:05:17 +03001845<!--- TEST ARBITRARY_TIME
1846Completed 1000000 actions in xxx ms
1847Counter = 1000000
1848-->
1849
1850This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
Roman Elizarovf9e13f52017-12-21 12:23:15 +03001851from multi-threaded `CommonPool` context to the single-threaded context using [withContext] block.
Roman Elizarov1e459602017-02-27 11:05:17 +03001852
1853### Thread confinement coarse-grained
1854
1855In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1856are confined to the single thread. The following example does it like that, running each coroutine in
1857the single-threaded context to start with.
1858
1859```kotlin
1860val counterContext = newSingleThreadContext("CounterContext")
1861var counter = 0
1862
1863fun main(args: Array<String>) = runBlocking<Unit> {
1864 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1865 counter++
1866 }
1867 println("Counter = $counter")
1868}
1869```
1870
Roman Elizarove8d79342017-08-29 15:21:21 +03001871> 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 +03001872
1873<!--- TEST ARBITRARY_TIME
1874Completed 1000000 actions in xxx ms
1875Counter = 1000000
1876-->
1877
1878This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001879
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001880### Mutual exclusion
1881
1882Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1883that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1884Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1885delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1886
Roman Elizarov88396732017-09-27 21:30:47 +03001887There is also [withLock] extension function that conveniently represents
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001888`mutex.lock(); try { ... } finally { mutex.unlock() }` pattern:
1889
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001890```kotlin
1891val mutex = Mutex()
1892var counter = 0
1893
1894fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001895 massiveRun(CommonPool) {
Roman Elizarov8b38fa22017-09-27 17:44:31 +03001896 mutex.withLock {
1897 counter++
1898 }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001899 }
1900 println("Counter = $counter")
1901}
1902```
1903
Roman Elizarove8d79342017-08-29 15:21:21 +03001904> 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 +03001905
Roman Elizarov1e459602017-02-27 11:05:17 +03001906<!--- TEST ARBITRARY_TIME
1907Completed 1000000 actions in xxx ms
1908Counter = 1000000
1909-->
1910
1911The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
1912where you absolutely must modify some shared state periodically, but there is no natural thread that this state
1913is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001914
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001915### Actors
1916
1917An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
1918and a channel to communicate with other coroutines. A simple actor can be written as a function,
1919but an actor with a complex state is better suited for a class.
1920
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001921There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
1922scope to receive messages from and combines the send channel into the resulting job object, so that a
1923single reference to the actor can be carried around as its handle.
1924
Roman Elizarov256812a2017-07-22 01:00:30 +03001925The first step of using an actor is to define a class of messages that an actor is going to process.
1926Kotlin's [sealed classes](https://kotlinlang.org/docs/reference/sealed-classes.html) are well suited for that purpose.
1927We define `CounterMsg` sealed class with `IncCounter` message to increment a counter and `GetCounter` message
1928to get its value. The later needs to send a response. A [CompletableDeferred] communication
1929primitive, that represents a single value that will be known (communicated) in the future,
1930is used here for that purpose.
1931
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001932```kotlin
1933// Message types for counterActor
1934sealed class CounterMsg
1935object IncCounter : CounterMsg() // one-way message to increment counter
Roman Elizarov256812a2017-07-22 01:00:30 +03001936class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a request with reply
1937```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001938
Roman Elizarov256812a2017-07-22 01:00:30 +03001939Then we define a function that launches an actor using an [actor] coroutine builder:
1940
1941```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001942// This function launches a new counter actor
Roman Elizarov66f018c2017-09-29 21:39:03 +03001943fun counterActor() = actor<CounterMsg> {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001944 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001945 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001946 when (msg) {
1947 is IncCounter -> counter++
Roman Elizarov256812a2017-07-22 01:00:30 +03001948 is GetCounter -> msg.response.complete(counter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001949 }
1950 }
1951}
Roman Elizarov256812a2017-07-22 01:00:30 +03001952```
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001953
Roman Elizarov256812a2017-07-22 01:00:30 +03001954The main code is straightforward:
1955
1956```kotlin
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001957fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001958 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03001959 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001960 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001961 }
Roman Elizarov256812a2017-07-22 01:00:30 +03001962 // send a message to get a counter value from an actor
1963 val response = CompletableDeferred<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001964 counter.send(GetCounter(response))
Roman Elizarov256812a2017-07-22 01:00:30 +03001965 println("Counter = ${response.await()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001966 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001967}
1968```
1969
Roman Elizarove8d79342017-08-29 15:21:21 +03001970> 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 +03001971
Roman Elizarov1e459602017-02-27 11:05:17 +03001972<!--- TEST ARBITRARY_TIME
1973Completed 1000000 actions in xxx ms
1974Counter = 1000000
1975-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001976
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001977It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001978a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
1979works as a solution to the problem of shared mutable state.
1980
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001981Actor is more efficient than locking under load, because in this case it always has work to do and it does not
1982have to switch to a different context at all.
1983
1984> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
1985 with the channel that it receives messages from, while a producer is associated with the channel that it
1986 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03001987
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001988## Select expression
1989
Roman Elizarova84730b2017-02-22 11:58:50 +03001990Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001991the first one that becomes available.
1992
1993<!--- INCLUDE .*/example-select-([0-9]+).kt
1994import kotlinx.coroutines.experimental.channels.*
1995import kotlinx.coroutines.experimental.selects.*
1996-->
1997
1998### Selecting from channels
1999
Roman Elizarov57857202017-03-02 23:17:25 +03002000Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
2001
2002<!--- INCLUDE .*/example-select-01.kt
2003import kotlin.coroutines.experimental.CoroutineContext
2004-->
2005
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002006```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002007fun fizz(context: CoroutineContext) = produce<String>(context) {
2008 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002009 delay(300)
2010 send("Fizz")
2011 }
2012}
2013```
2014
Roman Elizarov57857202017-03-02 23:17:25 +03002015And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002016
2017```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002018fun buzz(context: CoroutineContext) = produce<String>(context) {
2019 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002020 delay(500)
2021 send("Buzz!")
2022 }
2023}
2024```
2025
2026Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
2027other. But [select] expression allows us to receive from _both_ simultaneously using its
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002028[onReceive][ReceiveChannel.onReceive] clauses:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002029
2030```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03002031suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002032 select<Unit> { // <Unit> means that this select expression does not produce any result
2033 fizz.onReceive { value -> // this is the first select clause
2034 println("fizz -> '$value'")
2035 }
2036 buzz.onReceive { value -> // this is the second select clause
2037 println("buzz -> '$value'")
2038 }
2039 }
2040}
2041```
2042
Roman Elizarov57857202017-03-02 23:17:25 +03002043Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002044
2045```kotlin
2046fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03002047 val fizz = fizz(coroutineContext)
2048 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002049 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03002050 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002051 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002052 coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002053}
2054```
2055
Roman Elizarove8d79342017-08-29 15:21:21 +03002056> 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 +03002057
2058The result of this code is:
2059
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002060```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002061fizz -> 'Fizz'
2062buzz -> 'Buzz!'
2063fizz -> 'Fizz'
2064fizz -> 'Fizz'
2065buzz -> 'Buzz!'
2066fizz -> 'Fizz'
2067buzz -> 'Buzz!'
2068```
2069
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002070<!--- TEST -->
2071
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002072### Selecting on close
2073
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002074The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed and the corresponding
2075`select` throws an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03002076specific 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 +03002077the result of its selected clause:
2078
2079```kotlin
2080suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
2081 select<String> {
2082 a.onReceiveOrNull { value ->
2083 if (value == null)
2084 "Channel 'a' is closed"
2085 else
2086 "a -> '$value'"
2087 }
2088 b.onReceiveOrNull { value ->
2089 if (value == null)
2090 "Channel 'b' is closed"
2091 else
2092 "b -> '$value'"
2093 }
2094 }
2095```
2096
Roman Elizarova84730b2017-02-22 11:58:50 +03002097Let's use it with channel `a` that produces "Hello" string four times and
2098channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002099
2100```kotlin
2101fun main(args: Array<String>) = runBlocking<Unit> {
2102 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03002103 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002104 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002105 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03002106 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002107 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002108 }
2109 repeat(8) { // print first eight results
2110 println(selectAorB(a, b))
2111 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002112 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002113}
2114```
2115
Roman Elizarove8d79342017-08-29 15:21:21 +03002116> 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 +03002117
Roman Elizarova84730b2017-02-22 11:58:50 +03002118The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002119
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002120```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002121a -> 'Hello 0'
2122a -> 'Hello 1'
2123b -> 'World 0'
2124a -> 'Hello 2'
2125a -> 'Hello 3'
2126b -> 'World 1'
2127Channel 'a' is closed
2128Channel 'a' is closed
2129```
2130
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002131<!--- TEST -->
2132
Roman Elizarova84730b2017-02-22 11:58:50 +03002133There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002134
2135First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
2136the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03002137being 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 +03002138time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
2139
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002140The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002141channel is already closed.
2142
2143### Selecting to send
2144
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002145Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002146with a biased nature of selection.
2147
Roman Elizarova84730b2017-02-22 11:58:50 +03002148Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002149the consumers on its primary channel cannot keep up with it:
2150
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002151<!--- INCLUDE
2152import kotlin.coroutines.experimental.CoroutineContext
2153-->
2154
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002155```kotlin
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002156fun produceNumbers(context: CoroutineContext, side: SendChannel<Int>) = produce<Int>(context) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002157 for (num in 1..10) { // produce 10 numbers from 1 to 10
2158 delay(100) // every 100 ms
2159 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002160 onSend(num) {} // Send to the primary channel
2161 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002162 }
2163 }
2164}
2165```
2166
2167Consumer is going to be quite slow, taking 250 ms to process each number:
2168
2169```kotlin
2170fun main(args: Array<String>) = runBlocking<Unit> {
2171 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002172 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002173 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002174 }
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002175 produceNumbers(coroutineContext, side).consumeEach {
Roman Elizarov86349be2017-03-17 16:47:37 +03002176 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002177 delay(250) // let us digest the consumed number properly, do not hurry
2178 }
2179 println("Done consuming")
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002180 coroutineContext.cancelChildren()
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002181}
2182```
2183
Roman Elizarove8d79342017-08-29 15:21:21 +03002184> 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 +03002185
2186So let us see what happens:
2187
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002188```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002189Consuming 1
2190Side channel has 2
2191Side channel has 3
2192Consuming 4
2193Side channel has 5
2194Side channel has 6
2195Consuming 7
2196Side channel has 8
2197Side channel has 9
2198Consuming 10
2199Done consuming
2200```
2201
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002202<!--- TEST -->
2203
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002204### Selecting deferred values
2205
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002206Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
Roman Elizarova84730b2017-02-22 11:58:50 +03002207Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002208a random delay:
2209
2210<!--- INCLUDE .*/example-select-04.kt
2211import java.util.*
2212-->
2213
2214```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002215fun asyncString(time: Int) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002216 delay(time.toLong())
2217 "Waited for $time ms"
2218}
2219```
2220
Roman Elizarova84730b2017-02-22 11:58:50 +03002221Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002222
2223```kotlin
2224fun asyncStringsList(): List<Deferred<String>> {
2225 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002226 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002227}
2228```
2229
Roman Elizarova84730b2017-02-22 11:58:50 +03002230Now 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 +03002231that 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 +03002232so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2233of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002234
2235```kotlin
2236fun main(args: Array<String>) = runBlocking<Unit> {
2237 val list = asyncStringsList()
2238 val result = select<String> {
2239 list.withIndex().forEach { (index, deferred) ->
2240 deferred.onAwait { answer ->
2241 "Deferred $index produced answer '$answer'"
2242 }
2243 }
2244 }
2245 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002246 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002247 println("$countActive coroutines are still active")
2248}
2249```
2250
Roman Elizarove8d79342017-08-29 15:21:21 +03002251> 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 +03002252
2253The output is:
2254
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002255```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002256Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300225711 coroutines are still active
2258```
2259
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002260<!--- TEST -->
2261
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002262### Switch over a channel of deferred values
2263
Roman Elizarova84730b2017-02-22 11:58:50 +03002264Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2265deferred 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 +03002266[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002267
2268```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002269fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002270 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002271 while (isActive) { // loop while not cancelled/closed
2272 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2273 input.onReceiveOrNull { update ->
2274 update // replaces next value to wait
2275 }
2276 current.onAwait { value ->
2277 send(value) // send value that current deferred has produced
2278 input.receiveOrNull() // and use the next deferred from the input channel
2279 }
2280 }
2281 if (next == null) {
2282 println("Channel was closed")
2283 break // out of loop
2284 } else {
2285 current = next
2286 }
2287 }
2288}
2289```
2290
2291To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2292
2293```kotlin
Roman Elizarov66f018c2017-09-29 21:39:03 +03002294fun asyncString(str: String, time: Long) = async {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002295 delay(time)
2296 str
2297}
2298```
2299
2300The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2301data to it:
2302
2303```kotlin
2304fun main(args: Array<String>) = runBlocking<Unit> {
2305 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002306 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002307 for (s in switchMapDeferreds(chan))
2308 println(s) // print each received string
2309 }
2310 chan.send(asyncString("BEGIN", 100))
2311 delay(200) // enough time for "BEGIN" to be produced
2312 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002313 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002314 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002315 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002316 chan.send(asyncString("END", 500))
2317 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002318 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002319 delay(500) // and wait some time to let it finish
2320}
2321```
2322
Roman Elizarove8d79342017-08-29 15:21:21 +03002323> 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 +03002324
2325The result of this code:
2326
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002327```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002328BEGIN
2329Replace
2330END
2331Channel was closed
2332```
2333
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002334<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002335
Roman Elizarov8db17332017-03-09 12:40:45 +03002336## Further reading
2337
2338* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002339* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002340* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2341* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2342
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002343<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002344<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002345[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2346[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2347[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002348[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov8b38fa22017-09-27 17:44:31 +03002349[cancelAndJoin]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel-and-join.html
Roman Elizarov88396732017-09-27 21:30:47 +03002350[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
2351[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/join.html
Roman Elizarovcbb602d2017-12-23 14:24:26 +03002352[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002353[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002354[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 +03002355[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarovf9e13f52017-12-21 12:23:15 +03002356[withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002357[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2358[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
Roman Elizarov63f6ea22017-09-06 18:42:34 +03002359[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 +03002360[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2361[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002362[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 +03002363[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2364[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002365[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002366[DefaultDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-default-dispatcher.html
Roman Elizarov66f018c2017-09-29 21:39:03 +03002367[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
Roman Elizarov43e3af72017-07-21 16:01:31 +03002368[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 +03002369[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarovd9ae2bc2017-10-20 17:36:56 +08002370[newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
2371[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 +03002372[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002373[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarov88396732017-09-27 21:30:47 +03002374[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job.html
Roman Elizarov3e387b82017-12-04 13:49:11 +03002375[kotlin.coroutines.experimental.CoroutineContext.cancelChildren]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/kotlin.coroutines.experimental.-coroutine-context/cancel-children.html
Roman Elizarove82dee72017-08-18 16:49:09 +03002376[CompletableDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-completable-deferred/index.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002377[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 +03002378<!--- INDEX kotlinx.coroutines.experimental.sync -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002379[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002380[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2381[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 +03002382[withLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/with-lock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002383<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarove82dee72017-08-18 16:49:09 +03002384[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002385[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2386[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2387[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 +03002388[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002389[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarov88396732017-09-27 21:30:47 +03002390[Channel()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel.html
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002391[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarov8a5564d2017-09-06 18:48:22 +03002392[ReceiveChannel.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive.html
2393[ReceiveChannel.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/on-receive-or-null.html
2394[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 +03002395<!--- INDEX kotlinx.coroutines.experimental.selects -->
2396[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002397<!--- END -->