blob: 1089fd137c7028a06ec9bcb2d327677fb6a12e82 [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 Elizarov731f0ad2017-02-22 20:48:45 +030023<!--- KNIT kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
24<!--- TEST_OUT kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt
25// 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
35This is a short guide on core features of `kotlinx.coroutines` with a series of examples.
36
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 Elizarov2a638922017-03-04 10:22:43 +030044coroutine-enabled primitives that this guide covers, including `async` and `await`.
45You 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)
79 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030080 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030081* [Channels](#channels)
82 * [Channel basics](#channel-basics)
83 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
84 * [Building channel producers](#building-channel-producers)
85 * [Pipelines](#pipelines)
86 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
87 * [Fan-out](#fan-out)
88 * [Fan-in](#fan-in)
89 * [Buffered channels](#buffered-channels)
Roman Elizarovb0517ba2017-02-27 14:03:14 +030090 * [Channels are fair](#channels-are-fair)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030091* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
92 * [The problem](#the-problem)
Roman Elizarov1e459602017-02-27 11:05:17 +030093 * [Volatiles are of no help](#volatiles-are-of-no-help)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030094 * [Thread-safe data structures](#thread-safe-data-structures)
Roman Elizarov1e459602017-02-27 11:05:17 +030095 * [Thread confinement fine-grained](#thread-confinement-fine-grained)
96 * [Thread confinement coarse-grained](#thread-confinement-coarse-grained)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030097 * [Mutual exclusion](#mutual-exclusion)
98 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +030099* [Select expression](#select-expression)
100 * [Selecting from channels](#selecting-from-channels)
101 * [Selecting on close](#selecting-on-close)
102 * [Selecting to send](#selecting-to-send)
103 * [Selecting deferred values](#selecting-deferred-values)
104 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarov8db17332017-03-09 12:40:45 +0300105* [Further reading](#further-reading)
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300106
Roman Elizarova5e653f2017-02-13 13:49:55 +0300107<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300108
109## Coroutine basics
110
111This section covers basic coroutine concepts.
112
113### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +0300114
115Run the following code:
116
117```kotlin
118fun main(args: Array<String>) {
119 launch(CommonPool) { // create new coroutine in common thread pool
120 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
121 println("World!") // print after delay
122 }
123 println("Hello,") // main function continues while coroutine is delayed
124 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
125}
126```
127
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300128> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300129
130Run this code:
131
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300132```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300133Hello,
134World!
135```
136
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300137<!--- TEST -->
138
Roman Elizarov419a6c82017-02-09 18:36:22 +0300139Essentially, coroutines are light-weight threads.
140They are launched with [launch] _coroutine builder_.
141You can achieve the same result replacing
Roman Elizarov7deefb82017-01-31 10:33:17 +0300142`launch(CommonPool) { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
143
144If you start by replacing `launch(CommonPool)` by `thread`, the compiler produces the following error:
145
146```
147Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
148```
149
Roman Elizarov419a6c82017-02-09 18:36:22 +0300150That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300151coroutine and it can be only used from a coroutine.
152
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300153### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300154
155The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same
156code of `main` function. It is easy to get lost. Let's cleanly separate blocking and non-blocking
Roman Elizarov419a6c82017-02-09 18:36:22 +0300157worlds by using [runBlocking]:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300158
159```kotlin
160fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
161 launch(CommonPool) { // create new coroutine in common thread pool
162 delay(1000L)
163 println("World!")
164 }
165 println("Hello,") // main coroutine continues while child is delayed
166 delay(2000L) // non-blocking delay for 2 seconds to keep JVM alive
167}
168```
169
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300170> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300171
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300172<!--- TEST
173Hello,
174World!
175-->
176
Roman Elizarov419a6c82017-02-09 18:36:22 +0300177The result is the same, but this code uses only non-blocking [delay].
Roman Elizarov7deefb82017-01-31 10:33:17 +0300178
179`runBlocking { ... }` works as an adaptor that is used here to start the top-level main coroutine.
180The regular code outside of `runBlocking` _blocks_, until the coroutine inside `runBlocking` is active.
181
182This is also a way to write unit-tests for suspending functions:
183
184```kotlin
185class MyTest {
186 @Test
187 fun testMySuspendingFunction() = runBlocking<Unit> {
188 // here we can use suspending functions using any assertion style that we like
189 }
190}
191```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300192
193<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300194
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300195### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300196
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300197Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300198wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300199
200```kotlin
201fun main(args: Array<String>) = runBlocking<Unit> {
202 val job = launch(CommonPool) { // create new coroutine and keep a reference to its Job
203 delay(1000L)
204 println("World!")
205 }
206 println("Hello,")
207 job.join() // wait until child coroutine completes
208}
209```
210
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300211> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300212
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300213<!--- TEST
214Hello,
215World!
216-->
217
Roman Elizarov7deefb82017-01-31 10:33:17 +0300218Now 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 +0300219the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300220
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300221### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300222
Kafji48fd6282017-05-28 08:25:10 +0700223Let's extract the block of code inside `launch(CommonPool) { ... }` into a separate function. When you
Roman Elizarov7deefb82017-01-31 10:33:17 +0300224perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
225That is your first _suspending function_. Suspending functions can be used inside coroutines
226just like regular functions, but their additional feature is that they can, in turn,
227use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
228
229```kotlin
230fun main(args: Array<String>) = runBlocking<Unit> {
231 val job = launch(CommonPool) { doWorld() }
232 println("Hello,")
233 job.join()
234}
235
236// this is your first suspending function
237suspend fun doWorld() {
238 delay(1000L)
239 println("World!")
240}
241```
242
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300243> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300244
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300245<!--- TEST
246Hello,
247World!
248-->
249
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300250### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300251
252Run the following code:
253
254```kotlin
255fun main(args: Array<String>) = runBlocking<Unit> {
256 val jobs = List(100_000) { // create a lot of coroutines and list their jobs
257 launch(CommonPool) {
258 delay(1000L)
259 print(".")
260 }
261 }
262 jobs.forEach { it.join() } // wait for all jobs to complete
263}
264```
265
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300266> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300267
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300268<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
269
Roman Elizarov7deefb82017-01-31 10:33:17 +0300270It starts 100K coroutines and, after a second, each coroutine prints a dot.
271Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
272
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300273### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300274
275The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300276returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300277
278```kotlin
279fun main(args: Array<String>) = runBlocking<Unit> {
280 launch(CommonPool) {
281 repeat(1000) { i ->
282 println("I'm sleeping $i ...")
283 delay(500L)
284 }
285 }
286 delay(1300L) // just quit after delay
287}
288```
289
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300290> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300291
292You can run and see that it prints three lines and terminates:
293
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300294```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300295I'm sleeping 0 ...
296I'm sleeping 1 ...
297I'm sleeping 2 ...
298```
299
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300300<!--- TEST -->
301
Roman Elizarov7deefb82017-01-31 10:33:17 +0300302Active coroutines do not keep the process alive. They are like daemon threads.
303
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300304## Cancellation and timeouts
305
306This section covers coroutine cancellation and timeouts.
307
308### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300309
310In small application the return from "main" method might sound like a good idea to get all coroutines
311implicitly terminated. In a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300312The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300313
314```kotlin
315fun main(args: Array<String>) = runBlocking<Unit> {
316 val job = launch(CommonPool) {
317 repeat(1000) { i ->
318 println("I'm sleeping $i ...")
319 delay(500L)
320 }
321 }
322 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300323 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300324 job.cancel() // cancels the job
325 delay(1300L) // delay a bit to ensure it was cancelled indeed
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300326 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300327}
328```
329
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300330> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300331
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300332It produces the following output:
333
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300334```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300335I'm sleeping 0 ...
336I'm sleeping 1 ...
337I'm sleeping 2 ...
338main: I'm tired of waiting!
339main: Now I can quit.
340```
341
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300342<!--- TEST -->
343
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300344As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
345
346### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300347
Tair Rzayevaf734622017-02-01 22:30:16 +0200348Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300349All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300350coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300351a computation and does not check for cancellation, then it cannot be cancelled, like the following
352example shows:
353
354```kotlin
355fun main(args: Array<String>) = runBlocking<Unit> {
356 val job = launch(CommonPool) {
Roman Elizarov35d2c342017-07-20 14:54:39 +0300357 var nextPrintTime = System.currentTimeMillis()
Roman Elizarov7deefb82017-01-31 10:33:17 +0300358 var i = 0
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300359 while (i < 10) { // computation loop
Roman Elizarov7deefb82017-01-31 10:33:17 +0300360 val currentTime = System.currentTimeMillis()
361 if (currentTime >= nextPrintTime) {
362 println("I'm sleeping ${i++} ...")
Roman Elizarov35d2c342017-07-20 14:54:39 +0300363 nextPrintTime += 500L
Roman Elizarov7deefb82017-01-31 10:33:17 +0300364 }
365 }
366 }
367 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300368 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300369 job.cancel() // cancels the job
370 delay(1300L) // delay a bit to see if it was cancelled....
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300371 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300372}
373```
374
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300375> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300376
377Run it to see that it continues to print "I'm sleeping" even after cancellation.
378
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300379<!--- TEST
380I'm sleeping 0 ...
381I'm sleeping 1 ...
382I'm sleeping 2 ...
383main: I'm tired of waiting!
384I'm sleeping 3 ...
385I'm sleeping 4 ...
386I'm sleeping 5 ...
387main: Now I can quit.
388-->
389
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300390### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300391
392There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov419a6c82017-02-09 18:36:22 +0300393invoke a suspending function. There is a [yield] function that is a good choice for that purpose.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300394The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300395
396Replace `while (true)` in the previous example with `while (isActive)` and rerun it.
397
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300398```kotlin
399fun main(args: Array<String>) = runBlocking<Unit> {
400 val job = launch(CommonPool) {
401 var nextPrintTime = 0L
402 var i = 0
403 while (isActive) { // cancellable computation loop
404 val currentTime = System.currentTimeMillis()
405 if (currentTime >= nextPrintTime) {
406 println("I'm sleeping ${i++} ...")
407 nextPrintTime = currentTime + 500L
408 }
409 }
410 }
411 delay(1300L) // delay a bit
412 println("main: I'm tired of waiting!")
413 job.cancel() // cancels the job
414 delay(1300L) // delay a bit to see if it was cancelled....
415 println("main: Now I can quit.")
416}
417```
418
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300419> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300420
Roman Elizarov419a6c82017-02-09 18:36:22 +0300421As you can see, now this loop can be cancelled. [isActive][CoroutineScope.isActive] is a property that is available inside
422the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300423
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300424<!--- TEST
425I'm sleeping 0 ...
426I'm sleeping 1 ...
427I'm sleeping 2 ...
428main: I'm tired of waiting!
429main: Now I can quit.
430-->
431
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300432### Closing resources with finally
433
Roman Elizarov419a6c82017-02-09 18:36:22 +0300434Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300435all the usual way. For example, the `try {...} finally {...}` and Kotlin `use` function execute their
436finalization actions normally when coroutine is cancelled:
437
438```kotlin
439fun main(args: Array<String>) = runBlocking<Unit> {
440 val job = launch(CommonPool) {
441 try {
442 repeat(1000) { i ->
443 println("I'm sleeping $i ...")
444 delay(500L)
445 }
446 } finally {
447 println("I'm running finally")
448 }
449 }
450 delay(1300L) // delay a bit
451 println("main: I'm tired of waiting!")
452 job.cancel() // cancels the job
453 delay(1300L) // delay a bit to ensure it was cancelled indeed
454 println("main: Now I can quit.")
455}
456```
457
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300458> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300459
460The example above produces the following output:
461
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300462```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300463I'm sleeping 0 ...
464I'm sleeping 1 ...
465I'm sleeping 2 ...
466main: I'm tired of waiting!
467I'm running finally
468main: Now I can quit.
469```
470
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300471<!--- TEST -->
472
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300473### Run non-cancellable block
474
475Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300476[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300477problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
478communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
479rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarov419a6c82017-02-09 18:36:22 +0300480`run(NonCancellable) {...}` using [run] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300481
482```kotlin
483fun main(args: Array<String>) = runBlocking<Unit> {
484 val job = launch(CommonPool) {
485 try {
486 repeat(1000) { i ->
487 println("I'm sleeping $i ...")
488 delay(500L)
489 }
490 } finally {
491 run(NonCancellable) {
492 println("I'm running finally")
493 delay(1000L)
494 println("And I've just delayed for 1 sec because I'm non-cancellable")
495 }
496 }
497 }
498 delay(1300L) // delay a bit
499 println("main: I'm tired of waiting!")
500 job.cancel() // cancels the job
501 delay(1300L) // delay a bit to ensure it was cancelled indeed
502 println("main: Now I can quit.")
503}
504```
505
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300506> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300507
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300508<!--- TEST
509I'm sleeping 0 ...
510I'm sleeping 1 ...
511I'm sleeping 2 ...
512main: I'm tired of waiting!
513I'm running finally
514And I've just delayed for 1 sec because I'm non-cancellable
515main: Now I can quit.
516-->
517
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300518### Timeout
519
520The most obvious reason to cancel coroutine execution in practice,
521is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300522While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
523the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300524Look at the following example:
525
526```kotlin
527fun main(args: Array<String>) = runBlocking<Unit> {
528 withTimeout(1300L) {
529 repeat(1000) { i ->
530 println("I'm sleeping $i ...")
531 delay(500L)
532 }
533 }
534}
535```
536
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300537> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300538
539It produces the following output:
540
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300541```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300542I'm sleeping 0 ...
543I'm sleeping 1 ...
544I'm sleeping 2 ...
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300545Exception in thread "main" kotlinx.coroutines.experimental.TimeoutException: Timed out waiting for 1300 MILLISECONDS
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300546```
547
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300548<!--- TEST STARTS_WITH -->
549
Roman Elizarovca9d5be2017-04-20 19:23:18 +0300550The `TimeoutException` that is thrown by [withTimeout] is a private subclass of [CancellationException].
551We have not seen its stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300552inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300553However, in this example we have used `withTimeout` right inside the `main` function.
554
555Because cancellation is just an exception, all the resources will be closed in a usual way.
556You can wrap the code with timeout in `try {...} catch (e: CancellationException) {...}` block if
557you need to do some additional action specifically on timeout.
558
559## Composing suspending functions
560
561This section covers various approaches to composition of suspending functions.
562
563### Sequential by default
564
565Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300566remote service call or computation. We just pretend they are useful, but actually each one just
567delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300568
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300569<!--- INCLUDE .*/example-compose-([0-9]+).kt
570import kotlin.system.measureTimeMillis
571-->
572
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300573```kotlin
574suspend fun doSomethingUsefulOne(): Int {
575 delay(1000L) // pretend we are doing something useful here
576 return 13
577}
578
579suspend fun doSomethingUsefulTwo(): Int {
580 delay(1000L) // pretend we are doing something useful here, too
581 return 29
582}
583```
584
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300585<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
586
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300587What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
588`doSomethingUsefulTwo` and compute the sum of their results?
589In practise we do this if we use the results of the first function to make a decision on whether we need
590to invoke the second one or to decide on how to invoke it.
591
592We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300593code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300594time it takes to execute both suspending functions:
595
596```kotlin
597fun main(args: Array<String>) = runBlocking<Unit> {
598 val time = measureTimeMillis {
599 val one = doSomethingUsefulOne()
600 val two = doSomethingUsefulTwo()
601 println("The answer is ${one + two}")
602 }
603 println("Completed in $time ms")
604}
605```
606
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300607> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300608
609It produces something like this:
610
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300611```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300612The answer is 42
613Completed in 2017 ms
614```
615
Roman Elizarov35d2c342017-07-20 14:54:39 +0300616<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300617
Roman Elizarov32d95322017-02-09 15:57:31 +0300618### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300619
620What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300621we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300622
Roman Elizarov419a6c82017-02-09 18:36:22 +0300623Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
624that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
625does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300626that 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 +0300627but `Deferred` is also a `Job`, so you can cancel it if needed.
628
629```kotlin
630fun main(args: Array<String>) = runBlocking<Unit> {
631 val time = measureTimeMillis {
Roman Elizarov32d95322017-02-09 15:57:31 +0300632 val one = async(CommonPool) { doSomethingUsefulOne() }
633 val two = async(CommonPool) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300634 println("The answer is ${one.await() + two.await()}")
635 }
636 println("Completed in $time ms")
637}
638```
639
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300640> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300641
642It produces something like this:
643
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300644```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300645The answer is 42
646Completed in 1017 ms
647```
648
Roman Elizarov35d2c342017-07-20 14:54:39 +0300649<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300650
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300651This is twice as fast, because we have concurrent execution of two coroutines.
652Note, that concurrency with coroutines is always explicit.
653
Roman Elizarov32d95322017-02-09 15:57:31 +0300654### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300655
Roman Elizarovecda27f2017-04-06 23:06:26 +0300656There is a laziness option to [async] with [CoroutineStart.LAZY] parameter.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300657It starts coroutine only when its result is needed by some
658[await][Deferred.await] or if a [start][Job.start] function
Roman Elizarov32d95322017-02-09 15:57:31 +0300659is invoked. Run the following example that differs from the previous one only by this option:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300660
661```kotlin
662fun main(args: Array<String>) = runBlocking<Unit> {
663 val time = measureTimeMillis {
Roman Elizarovecda27f2017-04-06 23:06:26 +0300664 val one = async(CommonPool, CoroutineStart.LAZY) { doSomethingUsefulOne() }
665 val two = async(CommonPool, CoroutineStart.LAZY) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300666 println("The answer is ${one.await() + two.await()}")
667 }
668 println("Completed in $time ms")
669}
670```
671
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300672> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300673
674It produces something like this:
675
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300676```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300677The answer is 42
678Completed in 2017 ms
679```
680
Roman Elizarov35d2c342017-07-20 14:54:39 +0300681<!--- TEST ARBITRARY_TIME -->
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300682
Roman Elizarov32d95322017-02-09 15:57:31 +0300683So, we are back to sequential execution, because we _first_ start and await for `one`, _and then_ start and await
684for `two`. It is not the intended use-case for laziness. It is designed as a replacement for
685the standard `lazy` function in cases when computation of the value involves suspending functions.
686
687### Async-style functions
688
689We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300690_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Roman Elizarov32d95322017-02-09 15:57:31 +0300691either "async" prefix of "Async" suffix to highlight the fact that they only start asynchronous
692computation and one needs to use the resulting deferred value to get the result.
693
694```kotlin
695// The result type of asyncSomethingUsefulOne is Deferred<Int>
696fun asyncSomethingUsefulOne() = async(CommonPool) {
697 doSomethingUsefulOne()
698}
699
700// The result type of asyncSomethingUsefulTwo is Deferred<Int>
701fun asyncSomethingUsefulTwo() = async(CommonPool) {
702 doSomethingUsefulTwo()
703}
704```
705
706Note, that these `asyncXXX` function are **not** _suspending_ functions. They can be used from anywhere.
707However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
708with the invoking code.
709
710The following example shows their use outside of coroutine:
711
712```kotlin
713// note, that we don't have `runBlocking` to the right of `main` in this example
714fun main(args: Array<String>) {
715 val time = measureTimeMillis {
716 // we can initiate async actions outside of a coroutine
717 val one = asyncSomethingUsefulOne()
718 val two = asyncSomethingUsefulTwo()
719 // but waiting for a result must involve either suspending or blocking.
720 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
721 runBlocking {
722 println("The answer is ${one.await() + two.await()}")
723 }
724 }
725 println("Completed in $time ms")
726}
727```
728
729> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300730
Roman Elizarov35d2c342017-07-20 14:54:39 +0300731<!--- TEST ARBITRARY_TIME
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300732The answer is 42
733Completed in 1085 ms
734-->
735
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300736## Coroutine context and dispatchers
737
Roman Elizarov32d95322017-02-09 15:57:31 +0300738We've already seen `launch(CommonPool) {...}`, `async(CommonPool) {...}`, `run(NonCancellable) {...}`, etc.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300739In these code snippets [CommonPool] and [NonCancellable] are _coroutine contexts_.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300740This section covers other available choices.
741
742### Dispatchers and threads
743
Roman Elizarov419a6c82017-02-09 18:36:22 +0300744Coroutine context includes a [_coroutine dispatcher_][CoroutineDispatcher] which determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300745the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
746to a specific thread, dispatch it to a thread pool, or let it run unconfined. Try the following example:
747
748```kotlin
749fun main(args: Array<String>) = runBlocking<Unit> {
750 val jobs = arrayListOf<Job>()
751 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300752 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300753 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300754 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
755 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300756 }
757 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300758 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300759 }
760 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300761 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300762 }
763 jobs.forEach { it.join() }
764}
765```
766
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300767> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300768
769It produces the following output (maybe in different order):
770
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300771```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300772 'Unconfined': I'm working in thread main
773 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
774 'newSTC': I'm working in thread MyOwnThread
775'coroutineContext': I'm working in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300776```
777
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300778<!--- TEST LINES_START_UNORDERED -->
779
Roman Elizarov43e3af72017-07-21 16:01:31 +0300780The difference between parent [coroutineContext][CoroutineScope.coroutineContext] and
781[Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300782
783### Unconfined vs confined dispatcher
784
Roman Elizarov419a6c82017-02-09 18:36:22 +0300785The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300786first suspension point. After suspension it resumes in the thread that is fully determined by the
787suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
788consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
789
Roman Elizarov43e3af72017-07-21 16:01:31 +0300790On the other side, [coroutineContext][CoroutineScope.coroutineContext] property that is available inside the block of any coroutine
Roman Elizarov419a6c82017-02-09 18:36:22 +0300791via [CoroutineScope] interface, is a reference to a context of this particular coroutine.
792This way, a parent context can be inherited. The default context of [runBlocking], in particular,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300793is confined to be invoker thread, so inheriting it has the effect of confining execution to
794this thread with a predictable FIFO scheduling.
795
796```kotlin
797fun main(args: Array<String>) = runBlocking<Unit> {
798 val jobs = arrayListOf<Job>()
799 jobs += launch(Unconfined) { // not confined -- will work with main thread
Roman Elizarov43e3af72017-07-21 16:01:31 +0300800 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarovd0021622017-03-10 15:43:38 +0300801 delay(500)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300802 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300803 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300804 jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
805 println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300806 delay(1000)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300807 println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300808 }
809 jobs.forEach { it.join() }
810}
811```
812
Roman Elizarovd0021622017-03-10 15:43:38 +0300813> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300814
815Produces the output:
816
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300817```text
Roman Elizarov43e3af72017-07-21 16:01:31 +0300818 'Unconfined': I'm working in thread main
819'coroutineContext': I'm working in thread main
820 'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
821'coroutineContext': After delay in thread main
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300822```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300823
824<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300825
Roman Elizarov43e3af72017-07-21 16:01:31 +0300826So, the coroutine that had inherited `coroutineContext` of `runBlocking {...}` continues to execute
827in the `main` thread, while the unconfined one had resumed in the default executor thread that [delay]
828function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300829
830### Debugging coroutines and threads
831
Roman Elizarov419a6c82017-02-09 18:36:22 +0300832Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
833with a multi-threaded dispatcher like [CommonPool]. Even with a single-threaded dispatcher it might be hard to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300834figure out what coroutine was doing what, where, and when. The common approach to debugging applications with
835threads is to print the thread name in the log file on each log statement. This feature is universally supported
836by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
837`kotlinx.coroutines` includes debugging facilities to make it easier.
838
839Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
840
841```kotlin
842fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
843
844fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300845 val a = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300846 log("I'm computing a piece of the answer")
847 6
848 }
Roman Elizarov43e3af72017-07-21 16:01:31 +0300849 val b = async(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300850 log("I'm computing another piece of the answer")
851 7
852 }
853 log("The answer is ${a.await() * b.await()}")
854}
855```
856
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300857> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300858
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300859There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300860and two coroutines computing deferred values `a` (#2) and `b` (#3).
861They are all executing in the context of `runBlocking` and are confined to the main thread.
862The output of this code is:
863
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300864```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300865[main @coroutine#2] I'm computing a piece of the answer
866[main @coroutine#3] I'm computing another piece of the answer
867[main @coroutine#1] The answer is 42
868```
869
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300870<!--- TEST -->
871
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300872The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
873thread, but the identifier of the currently executing coroutine is appended to it. This identifier
874is consecutively assigned to all created coroutines when debugging mode is turned on.
875
Roman Elizarov419a6c82017-02-09 18:36:22 +0300876You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300877
878### Jumping between threads
879
880Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
881
882```kotlin
883fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
884
885fun main(args: Array<String>) {
886 val ctx1 = newSingleThreadContext("Ctx1")
887 val ctx2 = newSingleThreadContext("Ctx2")
888 runBlocking(ctx1) {
889 log("Started in ctx1")
890 run(ctx2) {
891 log("Working in ctx2")
892 }
893 log("Back to ctx1")
894 }
895}
896```
897
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300898> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300899
Roman Elizarov419a6c82017-02-09 18:36:22 +0300900It demonstrates two new techniques. One is using [runBlocking] with an explicitly specified context, and
901the second one is using [run] function to change a context of a coroutine while still staying in the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300902same coroutine as you can see in the output below:
903
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300904```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300905[Ctx1 @coroutine#1] Started in ctx1
906[Ctx2 @coroutine#1] Working in ctx2
907[Ctx1 @coroutine#1] Back to ctx1
908```
909
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300910<!--- TEST -->
911
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300912### Job in the context
913
Roman Elizarov419a6c82017-02-09 18:36:22 +0300914The coroutine [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov43e3af72017-07-21 16:01:31 +0300915using `coroutineContext[Job]` expression:
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300916
917```kotlin
918fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +0300919 println("My job is ${coroutineContext[Job]}")
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300920}
921```
922
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300923> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300924
shifujun81a6f232017-06-18 15:37:59 +0800925It produces something like
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300926
927```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300928My job is BlockingCoroutine{Active}@65ae6ba4
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300929```
930
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300931<!--- TEST lines.size == 1 && lines[0].startsWith("My job is BlockingCoroutine{Active}@") -->
932
Roman Elizarov43e3af72017-07-21 16:01:31 +0300933So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for
934`coroutineContext[Job]!!.isActive`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300935
936### Children of a coroutine
937
Roman Elizarov43e3af72017-07-21 16:01:31 +0300938When [coroutineContext][CoroutineScope.coroutineContext] of a coroutine is used to launch another coroutine,
Roman Elizarov419a6c82017-02-09 18:36:22 +0300939the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300940a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
941are recursively cancelled, too.
942
943```kotlin
944fun main(args: Array<String>) = runBlocking<Unit> {
945 // start a coroutine to process some kind of incoming request
946 val request = launch(CommonPool) {
947 // it spawns two other jobs, one with its separate context
948 val job1 = launch(CommonPool) {
949 println("job1: I have my own context and execute independently!")
950 delay(1000)
951 println("job1: I am not affected by cancellation of the request")
952 }
953 // and the other inherits the parent context
Roman Elizarov43e3af72017-07-21 16:01:31 +0300954 val job2 = launch(coroutineContext) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300955 println("job2: I am a child of the request coroutine")
956 delay(1000)
957 println("job2: I will not execute this line if my parent request is cancelled")
958 }
959 // request completes when both its sub-jobs complete:
960 job1.join()
961 job2.join()
962 }
963 delay(500)
964 request.cancel() // cancel processing of the request
965 delay(1000) // delay a second to see what happens
966 println("main: Who has survived request cancellation?")
967}
968```
969
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300970> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300971
972The output of this code is:
973
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300974```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300975job1: I have my own context and execute independently!
976job2: I am a child of the request coroutine
977job1: I am not affected by cancellation of the request
978main: Who has survived request cancellation?
979```
980
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300981<!--- TEST -->
982
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300983### Combining contexts
984
985Coroutine context can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +0300986of 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 +0300987its dispatcher replaced:
988
989```kotlin
990fun main(args: Array<String>) = runBlocking<Unit> {
991 // start a coroutine to process some kind of incoming request
Roman Elizarov43e3af72017-07-21 16:01:31 +0300992 val request = launch(coroutineContext) { // use the context of `runBlocking`
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300993 // spawns CPU-intensive child job in CommonPool !!!
Roman Elizarov43e3af72017-07-21 16:01:31 +0300994 val job = launch(coroutineContext + CommonPool) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300995 println("job: I am a child of the request coroutine, but with a different dispatcher")
996 delay(1000)
997 println("job: I will not execute this line if my parent request is cancelled")
998 }
999 job.join() // request completes when its sub-job completes
1000 }
1001 delay(500)
1002 request.cancel() // cancel processing of the request
1003 delay(1000) // delay a second to see what happens
1004 println("main: Who has survived request cancellation?")
1005}
1006```
1007
Roman Elizarovfa7723e2017-02-06 11:17:51 +03001008> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001009
1010The expected outcome of this code is:
1011
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001012```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001013job: I am a child of the request coroutine, but with a different dispatcher
1014main: Who has survived request cancellation?
1015```
1016
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001017<!--- TEST -->
1018
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001019### Naming coroutines for debugging
1020
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001021Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001022coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1023or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001024[CoroutineName] serves the same function as a thread name. It'll get displayed in the thread name that
Victor Osolovskiyed5ed492017-06-25 00:03:35 +03001025is executing this coroutine when debugging mode is turned on.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001026
1027The following example demonstrates this concept:
1028
1029```kotlin
1030fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1031
1032fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1033 log("Started main coroutine")
1034 // run two background value computations
Roman Elizarov32d95322017-02-09 15:57:31 +03001035 val v1 = async(CommonPool + CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001036 log("Computing v1")
1037 delay(500)
1038 252
1039 }
Roman Elizarov32d95322017-02-09 15:57:31 +03001040 val v2 = async(CommonPool + CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001041 log("Computing v2")
1042 delay(1000)
1043 6
1044 }
1045 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1046}
1047```
1048
Roman Elizarovfa7723e2017-02-06 11:17:51 +03001049> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001050
1051The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1052
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001053```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001054[main @main#1] Started main coroutine
1055[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1056[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1057[main @main#1] The answer for v1 / v2 = 42
1058```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001059
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001060<!--- TEST FLEXIBLE_THREAD -->
1061
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001062### Cancellation via explicit job
1063
1064Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1065an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1066and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1067and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1068to avoid memory leaks.
1069
1070We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
1071the lifecycle of our activity. A job instance is created using [Job()][Job.invoke] factory function
1072as the following example shows. We need to make sure that all the coroutines are started
1073with this job in their context and then a single invocation of [Job.cancel] terminates them all.
1074
1075```kotlin
1076fun main(args: Array<String>) = runBlocking<Unit> {
1077 val job = Job() // create a job object to manage our lifecycle
1078 // now launch ten coroutines for a demo, each working for a different time
1079 val coroutines = List(10) { i ->
1080 // they are all children of our job object
Roman Elizarov43e3af72017-07-21 16:01:31 +03001081 launch(coroutineContext + job) { // we use the context of main runBlocking thread, but with our own job object
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001082 delay(i * 200L) // variable delay 0ms, 200ms, 400ms, ... etc
1083 println("Coroutine $i is done")
1084 }
1085 }
1086 println("Launched ${coroutines.size} coroutines")
1087 delay(500L) // delay for half a second
1088 println("Cancelling job!")
1089 job.cancel() // cancel our job.. !!!
1090 delay(1000L) // delay for more to see if our coroutines are still working
1091}
1092```
1093
1094> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-09.kt)
1095
1096The output of this example is:
1097
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001098```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001099Launched 10 coroutines
1100Coroutine 0 is done
1101Coroutine 1 is done
1102Coroutine 2 is done
1103Cancelling job!
1104```
1105
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001106<!--- TEST -->
1107
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001108As you can see, only the first three coroutines had printed a message and the others were cancelled
1109by a single invocation of `job.cancel()`. So all we need to do in our hypothetical Android
1110application is to create a parent job object when activity is created, use it for child coroutines,
1111and cancel it when activity is destroyed.
1112
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001113## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001114
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001115Deferred values provide a convenient way to transfer a single value between coroutines.
1116Channels provide a way to transfer a stream of values.
1117
1118<!--- INCLUDE .*/example-channel-([0-9]+).kt
1119import kotlinx.coroutines.experimental.channels.*
1120-->
1121
1122### Channel basics
1123
Roman Elizarov419a6c82017-02-09 18:36:22 +03001124A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1125instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1126a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001127
1128```kotlin
1129fun main(args: Array<String>) = runBlocking<Unit> {
1130 val channel = Channel<Int>()
1131 launch(CommonPool) {
1132 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1133 for (x in 1..5) channel.send(x * x)
1134 }
1135 // here we print five received integers:
1136 repeat(5) { println(channel.receive()) }
1137 println("Done!")
1138}
1139```
1140
1141> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-01.kt)
1142
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001143The output of this code is:
1144
1145```text
11461
11474
11489
114916
115025
1151Done!
1152```
1153
1154<!--- TEST -->
1155
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001156### Closing and iteration over channels
1157
1158Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1159On the receiver side it is convenient to use a regular `for` loop to receive elements
1160from the channel.
1161
Roman Elizarov419a6c82017-02-09 18:36:22 +03001162Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001163The iteration stops as soon as this close token is received, so there is a guarantee
1164that all previously sent elements before the close are received:
1165
1166```kotlin
1167fun main(args: Array<String>) = runBlocking<Unit> {
1168 val channel = Channel<Int>()
1169 launch(CommonPool) {
1170 for (x in 1..5) channel.send(x * x)
1171 channel.close() // we're done sending
1172 }
1173 // here we print received values using `for` loop (until the channel is closed)
1174 for (y in channel) println(y)
1175 println("Done!")
1176}
1177```
1178
1179> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-02.kt)
1180
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001181<!--- TEST
11821
11834
11849
118516
118625
1187Done!
1188-->
1189
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001190### Building channel producers
1191
Roman Elizarova5e653f2017-02-13 13:49:55 +03001192The pattern where a coroutine is producing a sequence of elements is quite common.
1193This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001194You 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 +03001195to common sense that results must be returned from functions.
1196
Roman Elizarov86349be2017-03-17 16:47:37 +03001197There is a convenience coroutine builder named [produce] that makes it easy to do it right on producer side,
1198and an extension function [consumeEach], that can replace a `for` loop on the consumer side:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001199
1200```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001201fun produceSquares() = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001202 for (x in 1..5) send(x * x)
1203}
1204
1205fun main(args: Array<String>) = runBlocking<Unit> {
1206 val squares = produceSquares()
Roman Elizarov86349be2017-03-17 16:47:37 +03001207 squares.consumeEach { println(it) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001208 println("Done!")
1209}
1210```
1211
1212> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-03.kt)
1213
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001214<!--- TEST
12151
12164
12179
121816
121925
1220Done!
1221-->
1222
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001223### Pipelines
1224
1225Pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
1226
1227```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001228fun produceNumbers() = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001229 var x = 1
1230 while (true) send(x++) // infinite stream of integers starting from 1
1231}
1232```
1233
Roman Elizarova5e653f2017-02-13 13:49:55 +03001234And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001235In the below example the numbers are just squared:
1236
1237```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001238fun square(numbers: ReceiveChannel<Int>) = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001239 for (x in numbers) send(x * x)
1240}
1241```
1242
Roman Elizarova5e653f2017-02-13 13:49:55 +03001243The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001244
1245```kotlin
1246fun main(args: Array<String>) = runBlocking<Unit> {
1247 val numbers = produceNumbers() // produces integers from 1 and on
1248 val squares = square(numbers) // squares integers
1249 for (i in 1..5) println(squares.receive()) // print first five
1250 println("Done!") // we are done
1251 squares.cancel() // need to cancel these coroutines in a larger app
1252 numbers.cancel()
1253}
1254```
1255
1256> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-04.kt)
1257
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001258<!--- TEST
12591
12604
12619
126216
126325
1264Done!
1265-->
1266
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001267We don't have to cancel these coroutines in this example app, because
1268[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1269but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1270Alternatively, we could have run pipeline coroutines as
1271[children of a coroutine](#children-of-a-coroutine).
1272
1273### Prime numbers with pipeline
1274
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001275Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001276of coroutines. We start with an infinite sequence of numbers. This time we introduce an
1277explicit context parameter, so that caller can control where our coroutines run:
1278
1279<!--- INCLUDE kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
1280import kotlin.coroutines.experimental.CoroutineContext
1281-->
1282
1283```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001284fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001285 var x = start
1286 while (true) send(x++) // infinite stream of integers from start
1287}
1288```
1289
1290The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1291that are divisible by the given prime number:
1292
1293```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001294fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001295 for (x in numbers) if (x % prime != 0) send(x)
1296}
1297```
1298
1299Now 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 +03001300and launching new pipeline stage for each prime number found:
1301
1302```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001303numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001304```
1305
1306The following example prints the first ten prime numbers,
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001307running the whole pipeline in the context of the main thread:
1308
1309```kotlin
1310fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001311 var cur = numbersFrom(coroutineContext, 2)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001312 for (i in 1..10) {
1313 val prime = cur.receive()
1314 println(prime)
Roman Elizarov43e3af72017-07-21 16:01:31 +03001315 cur = filter(coroutineContext, cur, prime)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001316 }
1317}
1318```
1319
1320> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt)
1321
1322The output of this code is:
1323
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001324```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030013252
13263
13275
13287
132911
133013
133117
133219
133323
133429
1335```
1336
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001337<!--- TEST -->
1338
Roman Elizarova5e653f2017-02-13 13:49:55 +03001339Note, that you can build the same pipeline using `buildIterator` coroutine builder from the standard library.
1340Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001341`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1342However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1343multiple CPU cores if you run it in [CommonPool] context.
1344
Roman Elizarova5e653f2017-02-13 13:49:55 +03001345Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001346other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1347built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarova5e653f2017-02-13 13:49:55 +03001348`produce` which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001349
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001350### Fan-out
1351
1352Multiple coroutines may receive from the same channel, distributing work between themselves.
1353Let us start with a producer coroutine that is periodically producing integers
1354(ten numbers per second):
1355
1356```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001357fun produceNumbers() = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001358 var x = 1 // start from 1
1359 while (true) {
1360 send(x++) // produce next
1361 delay(100) // wait 0.1s
1362 }
1363}
1364```
1365
1366Then we can have several processor coroutines. In this example, they just print their id and
1367received number:
1368
1369```kotlin
1370fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch(CommonPool) {
Roman Elizarov86349be2017-03-17 16:47:37 +03001371 channel.consumeEach {
1372 println("Processor #$id received $it")
Roman Elizarovec9384c2017-03-02 22:09:08 +03001373 }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001374}
1375```
1376
Roman Elizarov35d2c342017-07-20 14:54:39 +03001377Now let us launch five processors and let them work for almost a second. See what happens:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001378
1379```kotlin
1380fun main(args: Array<String>) = runBlocking<Unit> {
1381 val producer = produceNumbers()
1382 repeat(5) { launchProcessor(it, producer) }
Roman Elizarov35d2c342017-07-20 14:54:39 +03001383 delay(950)
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001384 producer.cancel() // cancel producer coroutine and thus kill them all
1385}
1386```
1387
1388> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-06.kt)
1389
1390The output will be similar to the the following one, albeit the processor ids that receive
1391each specific integer may be different:
1392
1393```
1394Processor #2 received 1
1395Processor #4 received 2
1396Processor #0 received 3
1397Processor #1 received 4
1398Processor #3 received 5
1399Processor #2 received 6
1400Processor #4 received 7
1401Processor #0 received 8
1402Processor #1 received 9
1403Processor #3 received 10
1404```
1405
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001406<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1407
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001408Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1409over the channel that processor coroutines are doing.
1410
1411### Fan-in
1412
1413Multiple coroutines may send to the same channel.
1414For example, let us have a channel of strings, and a suspending function that
1415repeatedly sends a specified string to this channel with a specified delay:
1416
1417```kotlin
1418suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1419 while (true) {
1420 delay(time)
1421 channel.send(s)
1422 }
1423}
1424```
1425
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001426Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001427(in this example we launch them in the context of the main thread):
1428
1429```kotlin
1430fun main(args: Array<String>) = runBlocking<Unit> {
1431 val channel = Channel<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +03001432 launch(coroutineContext) { sendString(channel, "foo", 200L) }
1433 launch(coroutineContext) { sendString(channel, "BAR!", 500L) }
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001434 repeat(6) { // receive first six
1435 println(channel.receive())
1436 }
1437}
1438```
1439
1440> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt)
1441
1442The output is:
1443
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001444```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001445foo
1446foo
1447BAR!
1448foo
1449foo
1450BAR!
1451```
1452
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001453<!--- TEST -->
1454
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001455### Buffered channels
1456
1457The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1458meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1459if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001460
Roman Elizarova5e653f2017-02-13 13:49:55 +03001461Both [Channel()][Channel.invoke] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001462specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1463similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1464
1465Take a look at the behavior of the following code:
1466
1467```kotlin
1468fun main(args: Array<String>) = runBlocking<Unit> {
1469 val channel = Channel<Int>(4) // create buffered channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03001470 launch(coroutineContext) { // launch sender coroutine
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001471 repeat(10) {
1472 println("Sending $it") // print before sending each element
1473 channel.send(it) // will suspend when buffer is full
1474 }
1475 }
1476 // don't receive anything... just wait....
1477 delay(1000)
1478}
1479```
1480
1481> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt)
1482
1483It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1484
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001485```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001486Sending 0
1487Sending 1
1488Sending 2
1489Sending 3
1490Sending 4
1491```
1492
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001493<!--- TEST -->
1494
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001495The 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 +03001496
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001497
1498### Channels are fair
1499
1500Send and receive operations to channels are _fair_ with respect to the order of their invocation from
1501multiple coroutines. They are served in first-in first-out order, e.g. the first coroutine to invoke `receive`
1502gets the element. In the following example two coroutines "ping" and "pong" are
1503receiving the "ball" object from the shared "table" channel.
1504
1505```kotlin
1506data class Ball(var hits: Int)
1507
1508fun main(args: Array<String>) = runBlocking<Unit> {
1509 val table = Channel<Ball>() // a shared table
Roman Elizarov43e3af72017-07-21 16:01:31 +03001510 launch(coroutineContext) { player("ping", table) }
1511 launch(coroutineContext) { player("pong", table) }
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001512 table.send(Ball(0)) // serve the ball
1513 delay(1000) // delay 1 second
1514 table.receive() // game over, grab the ball
1515}
1516
1517suspend fun player(name: String, table: Channel<Ball>) {
1518 for (ball in table) { // receive the ball in a loop
1519 ball.hits++
1520 println("$name $ball")
Roman Elizarovf526b132017-03-10 16:07:14 +03001521 delay(300) // wait a bit
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001522 table.send(ball) // send the ball back
1523 }
1524}
1525```
1526
1527> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-09.kt)
1528
1529The "ping" coroutine is started first, so it is the first one to receive the ball. Even though "ping"
1530coroutine immediately starts receiving the ball again after sending it back to the table, the ball gets
1531received by the "pong" coroutine, because it was already waiting for it:
1532
1533```text
1534ping Ball(hits=1)
1535pong Ball(hits=2)
1536ping Ball(hits=3)
1537pong Ball(hits=4)
1538ping Ball(hits=5)
Roman Elizarovb0517ba2017-02-27 14:03:14 +03001539```
1540
1541<!--- TEST -->
1542
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001543## Shared mutable state and concurrency
1544
1545Coroutines can be executed concurrently using a multi-threaded dispatcher like [CommonPool]. It presents
1546all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1547Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1548but others are unique.
1549
1550### The problem
1551
Roman Elizarov1e459602017-02-27 11:05:17 +03001552Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
1553We'll also measure their completion time for further comparisons:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001554
Roman Elizarov43e90112017-05-10 11:25:20 +03001555<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
Roman Elizarov1e459602017-02-27 11:05:17 +03001556import kotlin.coroutines.experimental.CoroutineContext
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001557import kotlin.system.measureTimeMillis
1558-->
1559
Roman Elizarov1e459602017-02-27 11:05:17 +03001560<!--- INCLUDE .*/example-sync-03.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001561import java.util.concurrent.atomic.AtomicInteger
1562-->
1563
Roman Elizarov1e459602017-02-27 11:05:17 +03001564<!--- INCLUDE .*/example-sync-06.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001565import kotlinx.coroutines.experimental.sync.Mutex
1566-->
1567
Roman Elizarov1e459602017-02-27 11:05:17 +03001568<!--- INCLUDE .*/example-sync-07.kt
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001569import kotlinx.coroutines.experimental.channels.*
1570-->
1571
1572```kotlin
Roman Elizarov1e459602017-02-27 11:05:17 +03001573suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
1574 val n = 1000 // number of coroutines to launch
1575 val k = 1000 // times an action is repeated by each coroutine
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001576 val time = measureTimeMillis {
1577 val jobs = List(n) {
Roman Elizarov1e459602017-02-27 11:05:17 +03001578 launch(context) {
1579 repeat(k) { action() }
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001580 }
1581 }
1582 jobs.forEach { it.join() }
1583 }
Roman Elizarov1e459602017-02-27 11:05:17 +03001584 println("Completed ${n * k} actions in $time ms")
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001585}
1586```
1587
Roman Elizarov43e90112017-05-10 11:25:20 +03001588<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001589
Roman Elizarov1e459602017-02-27 11:05:17 +03001590We start with a very simple action that increments a shared mutable variable using
1591multi-threaded [CommonPool] context.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001592
1593```kotlin
1594var counter = 0
1595
1596fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001597 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001598 counter++
1599 }
1600 println("Counter = $counter")
1601}
1602```
1603
1604> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt)
1605
Roman Elizarov1e459602017-02-27 11:05:17 +03001606<!--- TEST LINES_START
1607Completed 1000000 actions in
1608Counter =
1609-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001610
Roman Elizarov1e459602017-02-27 11:05:17 +03001611What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
1612increment the `counter` concurrently from multiple threads without any synchronization.
1613
Roman Elizarov43e90112017-05-10 11:25:20 +03001614> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
1615`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
1616following change:
1617
1618```kotlin
1619val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
1620var counter = 0
1621
1622fun main(args: Array<String>) = runBlocking<Unit> {
1623 massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
1624 counter++
1625 }
1626 println("Counter = $counter")
1627}
1628```
1629
1630> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt)
1631
1632<!--- TEST LINES_START
1633Completed 1000000 actions in
1634Counter =
1635-->
1636
Roman Elizarov1e459602017-02-27 11:05:17 +03001637### Volatiles are of no help
1638
1639There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
1640
1641```kotlin
1642@Volatile // in Kotlin `volatile` is an annotation
1643var counter = 0
1644
1645fun main(args: Array<String>) = runBlocking<Unit> {
1646 massiveRun(CommonPool) {
1647 counter++
1648 }
1649 println("Counter = $counter")
1650}
1651```
1652
1653> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt)
1654
1655<!--- TEST LINES_START
1656Completed 1000000 actions in
1657Counter =
1658-->
1659
1660This code works slower, but we still don't get "Counter = 1000000" at the end, because volatile variables guarantee
1661linearizable (this is a technical term for "atomic") reads and writes to the corresponding variable, but
1662do not provide atomicity of larger actions (increment in our case).
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001663
1664### Thread-safe data structures
1665
1666The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1667linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1668operations that needs to be performed on a shared state.
Roman Elizarov1e459602017-02-27 11:05:17 +03001669In the case of a simple counter we can use `AtomicInteger` class which has atomic `incrementAndGet` operations:
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001670
1671```kotlin
1672var counter = AtomicInteger()
1673
1674fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001675 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001676 counter.incrementAndGet()
1677 }
1678 println("Counter = ${counter.get()}")
1679}
1680```
1681
Roman Elizarov1e459602017-02-27 11:05:17 +03001682> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001683
Roman Elizarov1e459602017-02-27 11:05:17 +03001684<!--- TEST ARBITRARY_TIME
1685Completed 1000000 actions in xxx ms
1686Counter = 1000000
1687-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001688
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001689This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1690standard data structures and basic operations on them. However, it does not easily scale to complex
1691state or to complex operations that do not have ready-to-use thread-safe implementations.
1692
Roman Elizarov1e459602017-02-27 11:05:17 +03001693### Thread confinement fine-grained
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001694
Roman Elizarov1e459602017-02-27 11:05:17 +03001695_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 +03001696state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1697the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1698single-threaded context:
1699
1700```kotlin
1701val counterContext = newSingleThreadContext("CounterContext")
1702var counter = 0
1703
1704fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001705 massiveRun(CommonPool) { // run each coroutine in CommonPool
1706 run(counterContext) { // but confine each increment to the single-threaded context
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001707 counter++
1708 }
1709 }
1710 println("Counter = $counter")
1711}
1712```
1713
Roman Elizarov1e459602017-02-27 11:05:17 +03001714> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001715
Roman Elizarov1e459602017-02-27 11:05:17 +03001716<!--- TEST ARBITRARY_TIME
1717Completed 1000000 actions in xxx ms
1718Counter = 1000000
1719-->
1720
1721This code works very slowly, because it does _fine-grained_ thread-confinement. Each individual increment switches
1722from multi-threaded `CommonPool` context to the single-threaded context using [run] block.
1723
1724### Thread confinement coarse-grained
1725
1726In practice, thread confinement is performed in large chunks, e.g. big pieces of state-updating business logic
1727are confined to the single thread. The following example does it like that, running each coroutine in
1728the single-threaded context to start with.
1729
1730```kotlin
1731val counterContext = newSingleThreadContext("CounterContext")
1732var counter = 0
1733
1734fun main(args: Array<String>) = runBlocking<Unit> {
1735 massiveRun(counterContext) { // run each coroutine in the single-threaded context
1736 counter++
1737 }
1738 println("Counter = $counter")
1739}
1740```
1741
1742> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt)
1743
1744<!--- TEST ARBITRARY_TIME
1745Completed 1000000 actions in xxx ms
1746Counter = 1000000
1747-->
1748
1749This now works much faster and produces correct result.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001750
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001751### Mutual exclusion
1752
1753Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1754that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1755Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1756delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1757
1758```kotlin
1759val mutex = Mutex()
1760var counter = 0
1761
1762fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov1e459602017-02-27 11:05:17 +03001763 massiveRun(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001764 mutex.lock()
1765 try { counter++ }
1766 finally { mutex.unlock() }
1767 }
1768 println("Counter = $counter")
1769}
1770```
1771
Roman Elizarov1e459602017-02-27 11:05:17 +03001772> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-06.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001773
Roman Elizarov1e459602017-02-27 11:05:17 +03001774<!--- TEST ARBITRARY_TIME
1775Completed 1000000 actions in xxx ms
1776Counter = 1000000
1777-->
1778
1779The locking in this example is fine-grained, so it pays the price. However, it is a good choice for some situations
1780where you absolutely must modify some shared state periodically, but there is no natural thread that this state
1781is confined to.
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001782
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001783### Actors
1784
1785An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
1786and a channel to communicate with other coroutines. A simple actor can be written as a function,
1787but an actor with a complex state is better suited for a class.
1788
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001789There is an [actor] coroutine builder that conveniently combines actor's mailbox channel into its
1790scope to receive messages from and combines the send channel into the resulting job object, so that a
1791single reference to the actor can be carried around as its handle.
1792
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001793```kotlin
1794// Message types for counterActor
1795sealed class CounterMsg
1796object IncCounter : CounterMsg() // one-way message to increment counter
1797class GetCounter(val response: SendChannel<Int>) : CounterMsg() // a request with reply
1798
1799// This function launches a new counter actor
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001800fun counterActor() = actor<CounterMsg>(CommonPool) {
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001801 var counter = 0 // actor state
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001802 for (msg in channel) { // iterate over incoming messages
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001803 when (msg) {
1804 is IncCounter -> counter++
1805 is GetCounter -> msg.response.send(counter)
1806 }
1807 }
1808}
1809
1810fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001811 val counter = counterActor() // create the actor
Roman Elizarov1e459602017-02-27 11:05:17 +03001812 massiveRun(CommonPool) {
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001813 counter.send(IncCounter)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001814 }
1815 val response = Channel<Int>()
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001816 counter.send(GetCounter(response))
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001817 println("Counter = ${response.receive()}")
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001818 counter.close() // shutdown the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001819}
1820```
1821
Roman Elizarov1e459602017-02-27 11:05:17 +03001822> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-07.kt)
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001823
Roman Elizarov1e459602017-02-27 11:05:17 +03001824<!--- TEST ARBITRARY_TIME
1825Completed 1000000 actions in xxx ms
1826Counter = 1000000
1827-->
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001828
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001829It does not matter (for correctness) what context the actor itself is executed in. An actor is
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001830a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
1831works as a solution to the problem of shared mutable state.
1832
Roman Elizarovc0e19f82017-02-27 11:59:14 +03001833Actor is more efficient than locking under load, because in this case it always has work to do and it does not
1834have to switch to a different context at all.
1835
1836> Note, that an [actor] coroutine builder is a dual of [produce] coroutine builder. An actor is associated
1837 with the channel that it receives messages from, while a producer is associated with the channel that it
1838 sends elements to.
Roman Elizarov1e459602017-02-27 11:05:17 +03001839
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001840## Select expression
1841
Roman Elizarova84730b2017-02-22 11:58:50 +03001842Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001843the first one that becomes available.
1844
1845<!--- INCLUDE .*/example-select-([0-9]+).kt
1846import kotlinx.coroutines.experimental.channels.*
1847import kotlinx.coroutines.experimental.selects.*
1848-->
1849
1850### Selecting from channels
1851
Roman Elizarov57857202017-03-02 23:17:25 +03001852Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
1853
1854<!--- INCLUDE .*/example-select-01.kt
1855import kotlin.coroutines.experimental.CoroutineContext
1856-->
1857
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001858```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03001859fun fizz(context: CoroutineContext) = produce<String>(context) {
1860 while (true) { // sends "Fizz" every 300 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001861 delay(300)
1862 send("Fizz")
1863 }
1864}
1865```
1866
Roman Elizarov57857202017-03-02 23:17:25 +03001867And the `buzz` produces "Buzz!" string every 500 ms:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001868
1869```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03001870fun buzz(context: CoroutineContext) = produce<String>(context) {
1871 while (true) { // sends "Buzz!" every 500 ms
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001872 delay(500)
1873 send("Buzz!")
1874 }
1875}
1876```
1877
1878Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
1879other. But [select] expression allows us to receive from _both_ simultaneously using its
1880[onReceive][SelectBuilder.onReceive] clauses:
1881
1882```kotlin
Roman Elizarov57857202017-03-02 23:17:25 +03001883suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001884 select<Unit> { // <Unit> means that this select expression does not produce any result
1885 fizz.onReceive { value -> // this is the first select clause
1886 println("fizz -> '$value'")
1887 }
1888 buzz.onReceive { value -> // this is the second select clause
1889 println("buzz -> '$value'")
1890 }
1891 }
1892}
1893```
1894
Roman Elizarov57857202017-03-02 23:17:25 +03001895Let us run it all seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001896
1897```kotlin
1898fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov43e3af72017-07-21 16:01:31 +03001899 val fizz = fizz(coroutineContext)
1900 val buzz = buzz(coroutineContext)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001901 repeat(7) {
Roman Elizarov57857202017-03-02 23:17:25 +03001902 selectFizzBuzz(fizz, buzz)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001903 }
1904}
1905```
1906
1907> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt)
1908
1909The result of this code is:
1910
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001911```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001912fizz -> 'Fizz'
1913buzz -> 'Buzz!'
1914fizz -> 'Fizz'
1915fizz -> 'Fizz'
1916buzz -> 'Buzz!'
1917fizz -> 'Fizz'
1918buzz -> 'Buzz!'
1919```
1920
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001921<!--- TEST -->
1922
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001923### Selecting on close
1924
1925The [onReceive][SelectBuilder.onReceive] clause in `select` fails when the channel is closed and the corresponding
1926`select` throws an exception. We can use [onReceiveOrNull][SelectBuilder.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03001927specific 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 +03001928the result of its selected clause:
1929
1930```kotlin
1931suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
1932 select<String> {
1933 a.onReceiveOrNull { value ->
1934 if (value == null)
1935 "Channel 'a' is closed"
1936 else
1937 "a -> '$value'"
1938 }
1939 b.onReceiveOrNull { value ->
1940 if (value == null)
1941 "Channel 'b' is closed"
1942 else
1943 "b -> '$value'"
1944 }
1945 }
1946```
1947
Roman Elizarova84730b2017-02-22 11:58:50 +03001948Let's use it with channel `a` that produces "Hello" string four times and
1949channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001950
1951```kotlin
1952fun main(args: Array<String>) = runBlocking<Unit> {
1953 // we are using the context of the main thread in this example for predictability ...
Roman Elizarov43e3af72017-07-21 16:01:31 +03001954 val a = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03001955 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001956 }
Roman Elizarov43e3af72017-07-21 16:01:31 +03001957 val b = produce<String>(coroutineContext) {
Roman Elizarova84730b2017-02-22 11:58:50 +03001958 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001959 }
1960 repeat(8) { // print first eight results
1961 println(selectAorB(a, b))
1962 }
1963}
1964```
1965
1966> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt)
1967
Roman Elizarova84730b2017-02-22 11:58:50 +03001968The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001969
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001970```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001971a -> 'Hello 0'
1972a -> 'Hello 1'
1973b -> 'World 0'
1974a -> 'Hello 2'
1975a -> 'Hello 3'
1976b -> 'World 1'
1977Channel 'a' is closed
1978Channel 'a' is closed
1979```
1980
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001981<!--- TEST -->
1982
Roman Elizarova84730b2017-02-22 11:58:50 +03001983There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001984
1985First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
1986the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03001987being 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 +03001988time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
1989
1990The second observation, is that [onReceiveOrNull][SelectBuilder.onReceiveOrNull] gets immediately selected when the
1991channel is already closed.
1992
1993### Selecting to send
1994
1995Select expression has [onSend][SelectBuilder.onSend] clause that can be used for a great good in combination
1996with a biased nature of selection.
1997
Roman Elizarova84730b2017-02-22 11:58:50 +03001998Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001999the consumers on its primary channel cannot keep up with it:
2000
2001```kotlin
2002fun produceNumbers(side: SendChannel<Int>) = produce<Int>(CommonPool) {
2003 for (num in 1..10) { // produce 10 numbers from 1 to 10
2004 delay(100) // every 100 ms
2005 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03002006 onSend(num) {} // Send to the primary channel
2007 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002008 }
2009 }
2010}
2011```
2012
2013Consumer is going to be quite slow, taking 250 ms to process each number:
2014
2015```kotlin
2016fun main(args: Array<String>) = runBlocking<Unit> {
2017 val side = Channel<Int>() // allocate side channel
Roman Elizarov43e3af72017-07-21 16:01:31 +03002018 launch(coroutineContext) { // this is a very fast consumer for the side channel
Roman Elizarov86349be2017-03-17 16:47:37 +03002019 side.consumeEach { println("Side channel has $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002020 }
Roman Elizarov86349be2017-03-17 16:47:37 +03002021 produceNumbers(side).consumeEach {
2022 println("Consuming $it")
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002023 delay(250) // let us digest the consumed number properly, do not hurry
2024 }
2025 println("Done consuming")
2026}
2027```
2028
2029> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt)
2030
2031So let us see what happens:
2032
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002033```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002034Consuming 1
2035Side channel has 2
2036Side channel has 3
2037Consuming 4
2038Side channel has 5
2039Side channel has 6
2040Consuming 7
2041Side channel has 8
2042Side channel has 9
2043Consuming 10
2044Done consuming
2045```
2046
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002047<!--- TEST -->
2048
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002049### Selecting deferred values
2050
Roman Elizarova84730b2017-02-22 11:58:50 +03002051Deferred values can be selected using [onAwait][SelectBuilder.onAwait] clause.
2052Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002053a random delay:
2054
2055<!--- INCLUDE .*/example-select-04.kt
2056import java.util.*
2057-->
2058
2059```kotlin
2060fun asyncString(time: Int) = async(CommonPool) {
2061 delay(time.toLong())
2062 "Waited for $time ms"
2063}
2064```
2065
Roman Elizarova84730b2017-02-22 11:58:50 +03002066Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002067
2068```kotlin
2069fun asyncStringsList(): List<Deferred<String>> {
2070 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03002071 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002072}
2073```
2074
Roman Elizarova84730b2017-02-22 11:58:50 +03002075Now 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 +03002076that 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 +03002077so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
2078of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002079
2080```kotlin
2081fun main(args: Array<String>) = runBlocking<Unit> {
2082 val list = asyncStringsList()
2083 val result = select<String> {
2084 list.withIndex().forEach { (index, deferred) ->
2085 deferred.onAwait { answer ->
2086 "Deferred $index produced answer '$answer'"
2087 }
2088 }
2089 }
2090 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03002091 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002092 println("$countActive coroutines are still active")
2093}
2094```
2095
2096> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-04.kt)
2097
2098The output is:
2099
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002100```text
Roman Elizarova84730b2017-02-22 11:58:50 +03002101Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300210211 coroutines are still active
2103```
2104
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002105<!--- TEST -->
2106
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002107### Switch over a channel of deferred values
2108
Roman Elizarova84730b2017-02-22 11:58:50 +03002109Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
2110deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002111[onReceiveOrNull][SelectBuilder.onReceiveOrNull] and [onAwait][SelectBuilder.onAwait] clauses in the same `select`:
2112
2113```kotlin
2114fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String>(CommonPool) {
Roman Elizarova84730b2017-02-22 11:58:50 +03002115 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002116 while (isActive) { // loop while not cancelled/closed
2117 val next = select<Deferred<String>?> { // return next deferred value from this select or null
2118 input.onReceiveOrNull { update ->
2119 update // replaces next value to wait
2120 }
2121 current.onAwait { value ->
2122 send(value) // send value that current deferred has produced
2123 input.receiveOrNull() // and use the next deferred from the input channel
2124 }
2125 }
2126 if (next == null) {
2127 println("Channel was closed")
2128 break // out of loop
2129 } else {
2130 current = next
2131 }
2132 }
2133}
2134```
2135
2136To test it, we'll use a simple async function that resolves to a specified string after a specified time:
2137
2138```kotlin
2139fun asyncString(str: String, time: Long) = async(CommonPool) {
2140 delay(time)
2141 str
2142}
2143```
2144
2145The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
2146data to it:
2147
2148```kotlin
2149fun main(args: Array<String>) = runBlocking<Unit> {
2150 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarov43e3af72017-07-21 16:01:31 +03002151 launch(coroutineContext) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002152 for (s in switchMapDeferreds(chan))
2153 println(s) // print each received string
2154 }
2155 chan.send(asyncString("BEGIN", 100))
2156 delay(200) // enough time for "BEGIN" to be produced
2157 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03002158 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002159 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03002160 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002161 chan.send(asyncString("END", 500))
2162 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03002163 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002164 delay(500) // and wait some time to let it finish
2165}
2166```
2167
2168> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt)
2169
2170The result of this code:
2171
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002172```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002173BEGIN
2174Replace
2175END
2176Channel was closed
2177```
2178
Roman Elizarov731f0ad2017-02-22 20:48:45 +03002179<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002180
Roman Elizarov8db17332017-03-09 12:40:45 +03002181## Further reading
2182
2183* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
Roman Elizarov8a4a8e12017-03-09 19:52:58 +03002184* [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md)
Roman Elizarov8db17332017-03-09 12:40:45 +03002185* [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md)
2186* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines)
2187
Roman Elizarove7e2ad12017-05-17 14:47:31 +03002188<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarove0c817d2017-02-10 10:22:01 +03002189<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002190[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2191[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2192[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
2193[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
2194[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception.html
2195[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002196[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 +03002197[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
2198[run]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
2199[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2200[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
2201[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2202[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarovecda27f2017-04-06 23:06:26 +03002203[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 +03002204[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
2205[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002206[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
2207[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarov43e3af72017-07-21 16:01:31 +03002208[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 +03002209[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002210[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002211[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002212[Job.invoke]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/invoke.html
2213[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002214<!--- INDEX kotlinx.coroutines.experimental.sync -->
2215[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002216[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/lock.html
2217[Mutex.unlock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/unlock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002218<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarov419a6c82017-02-09 18:36:22 +03002219[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002220[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
2221[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
2222[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 +03002223[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarov86349be2017-03-17 16:47:37 +03002224[consumeEach]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/consume-each.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002225[Channel.invoke]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/invoke.html
Roman Elizarovc0e19f82017-02-27 11:59:14 +03002226[actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002227<!--- INDEX kotlinx.coroutines.experimental.selects -->
2228[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
Roman Elizarovbff3f372017-03-01 18:12:27 +03002229[SelectBuilder.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/-select-builder/on-receive.html
2230[SelectBuilder.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/-select-builder/on-receive-or-null.html
2231[SelectBuilder.onSend]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/-select-builder/on-send.html
2232[SelectBuilder.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/-select-builder/on-await.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002233<!--- END -->