blob: fe3fcb9a64f3c1d121600b806c33f70a60ec854a [file] [log] [blame] [view]
Roman Elizarova5e653f2017-02-13 13:49:55 +03001<!--- INCLUDE .*/example-([a-z]+)-([0-9]+)\.kt
2/*
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 Elizarov1293ccd2017-02-01 18:49:54 +030037## Table of contents
38
Roman Elizarovfa7723e2017-02-06 11:17:51 +030039<!--- TOC -->
40
Roman Elizarov1293ccd2017-02-01 18:49:54 +030041* [Coroutine basics](#coroutine-basics)
42 * [Your first coroutine](#your-first-coroutine)
43 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
44 * [Waiting for a job](#waiting-for-a-job)
45 * [Extract function refactoring](#extract-function-refactoring)
46 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
47 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
48* [Cancellation and timeouts](#cancellation-and-timeouts)
49 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
50 * [Cancellation is cooperative](#cancellation-is-cooperative)
51 * [Making computation code cancellable](#making-computation-code-cancellable)
52 * [Closing resources with finally](#closing-resources-with-finally)
53 * [Run non-cancellable block](#run-non-cancellable-block)
54 * [Timeout](#timeout)
55* [Composing suspending functions](#composing-suspending-functions)
56 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030057 * [Concurrent using async](#concurrent-using-async)
58 * [Lazily started async](#lazily-started-async)
59 * [Async-style functions](#async-style-functions)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030060* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030061 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030062 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
63 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
64 * [Jumping between threads](#jumping-between-threads)
65 * [Job in the context](#job-in-the-context)
66 * [Children of a coroutine](#children-of-a-coroutine)
67 * [Combining contexts](#combining-contexts)
68 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030069 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030070* [Channels](#channels)
71 * [Channel basics](#channel-basics)
72 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
73 * [Building channel producers](#building-channel-producers)
74 * [Pipelines](#pipelines)
75 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
76 * [Fan-out](#fan-out)
77 * [Fan-in](#fan-in)
78 * [Buffered channels](#buffered-channels)
Roman Elizarovf5bc0472017-02-22 11:38:13 +030079* [Shared mutable state and concurrency](#shared-mutable-state-and-concurrency)
80 * [The problem](#the-problem)
81 * [Thread-safe data structures](#thread-safe-data-structures)
82 * [Thread confinement](#thread-confinement)
83 * [Mutual exclusion](#mutual-exclusion)
84 * [Actors](#actors)
Roman Elizarovd4dcbe22017-02-22 09:57:46 +030085* [Select expression](#select-expression)
86 * [Selecting from channels](#selecting-from-channels)
87 * [Selecting on close](#selecting-on-close)
88 * [Selecting to send](#selecting-to-send)
89 * [Selecting deferred values](#selecting-deferred-values)
90 * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030091
Roman Elizarova5e653f2017-02-13 13:49:55 +030092<!--- END_TOC -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +030093
94## Coroutine basics
95
96This section covers basic coroutine concepts.
97
98### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +030099
100Run the following code:
101
102```kotlin
103fun main(args: Array<String>) {
104 launch(CommonPool) { // create new coroutine in common thread pool
105 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
106 println("World!") // print after delay
107 }
108 println("Hello,") // main function continues while coroutine is delayed
109 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
110}
111```
112
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300113> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300114
115Run this code:
116
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300117```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300118Hello,
119World!
120```
121
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300122<!--- TEST -->
123
Roman Elizarov419a6c82017-02-09 18:36:22 +0300124Essentially, coroutines are light-weight threads.
125They are launched with [launch] _coroutine builder_.
126You can achieve the same result replacing
Roman Elizarov7deefb82017-01-31 10:33:17 +0300127`launch(CommonPool) { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
128
129If you start by replacing `launch(CommonPool)` by `thread`, the compiler produces the following error:
130
131```
132Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
133```
134
Roman Elizarov419a6c82017-02-09 18:36:22 +0300135That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300136coroutine and it can be only used from a coroutine.
137
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300138### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300139
140The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same
141code of `main` function. It is easy to get lost. Let's cleanly separate blocking and non-blocking
Roman Elizarov419a6c82017-02-09 18:36:22 +0300142worlds by using [runBlocking]:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300143
144```kotlin
145fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
146 launch(CommonPool) { // create new coroutine in common thread pool
147 delay(1000L)
148 println("World!")
149 }
150 println("Hello,") // main coroutine continues while child is delayed
151 delay(2000L) // non-blocking delay for 2 seconds to keep JVM alive
152}
153```
154
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300155> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300156
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300157<!--- TEST
158Hello,
159World!
160-->
161
Roman Elizarov419a6c82017-02-09 18:36:22 +0300162The result is the same, but this code uses only non-blocking [delay].
Roman Elizarov7deefb82017-01-31 10:33:17 +0300163
164`runBlocking { ... }` works as an adaptor that is used here to start the top-level main coroutine.
165The regular code outside of `runBlocking` _blocks_, until the coroutine inside `runBlocking` is active.
166
167This is also a way to write unit-tests for suspending functions:
168
169```kotlin
170class MyTest {
171 @Test
172 fun testMySuspendingFunction() = runBlocking<Unit> {
173 // here we can use suspending functions using any assertion style that we like
174 }
175}
176```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300177
178<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300179
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300180### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300181
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300182Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300183wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300184
185```kotlin
186fun main(args: Array<String>) = runBlocking<Unit> {
187 val job = launch(CommonPool) { // create new coroutine and keep a reference to its Job
188 delay(1000L)
189 println("World!")
190 }
191 println("Hello,")
192 job.join() // wait until child coroutine completes
193}
194```
195
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300196> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300197
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300198<!--- TEST
199Hello,
200World!
201-->
202
Roman Elizarov7deefb82017-01-31 10:33:17 +0300203Now 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 +0300204the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300205
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300206### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300207
208Let's extract the block of code inside `launch(CommonPool} { ... }` into a separate function. When you
209perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
210That is your first _suspending function_. Suspending functions can be used inside coroutines
211just like regular functions, but their additional feature is that they can, in turn,
212use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
213
214```kotlin
215fun main(args: Array<String>) = runBlocking<Unit> {
216 val job = launch(CommonPool) { doWorld() }
217 println("Hello,")
218 job.join()
219}
220
221// this is your first suspending function
222suspend fun doWorld() {
223 delay(1000L)
224 println("World!")
225}
226```
227
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300228> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300229
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300230<!--- TEST
231Hello,
232World!
233-->
234
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300235### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300236
237Run the following code:
238
239```kotlin
240fun main(args: Array<String>) = runBlocking<Unit> {
241 val jobs = List(100_000) { // create a lot of coroutines and list their jobs
242 launch(CommonPool) {
243 delay(1000L)
244 print(".")
245 }
246 }
247 jobs.forEach { it.join() } // wait for all jobs to complete
248}
249```
250
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300251> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300252
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300253<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
254
Roman Elizarov7deefb82017-01-31 10:33:17 +0300255It starts 100K coroutines and, after a second, each coroutine prints a dot.
256Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
257
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300258### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300259
260The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300261returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300262
263```kotlin
264fun main(args: Array<String>) = runBlocking<Unit> {
265 launch(CommonPool) {
266 repeat(1000) { i ->
267 println("I'm sleeping $i ...")
268 delay(500L)
269 }
270 }
271 delay(1300L) // just quit after delay
272}
273```
274
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300275> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300276
277You can run and see that it prints three lines and terminates:
278
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300279```text
Roman Elizarov7deefb82017-01-31 10:33:17 +0300280I'm sleeping 0 ...
281I'm sleeping 1 ...
282I'm sleeping 2 ...
283```
284
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300285<!--- TEST -->
286
Roman Elizarov7deefb82017-01-31 10:33:17 +0300287Active coroutines do not keep the process alive. They are like daemon threads.
288
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300289## Cancellation and timeouts
290
291This section covers coroutine cancellation and timeouts.
292
293### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300294
295In small application the return from "main" method might sound like a good idea to get all coroutines
296implicitly terminated. In a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300297The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300298
299```kotlin
300fun main(args: Array<String>) = runBlocking<Unit> {
301 val job = launch(CommonPool) {
302 repeat(1000) { i ->
303 println("I'm sleeping $i ...")
304 delay(500L)
305 }
306 }
307 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300308 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300309 job.cancel() // cancels the job
310 delay(1300L) // delay a bit to ensure it was cancelled indeed
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300311 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300312}
313```
314
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300315> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300316
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300317It produces the following output:
318
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300319```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300320I'm sleeping 0 ...
321I'm sleeping 1 ...
322I'm sleeping 2 ...
323main: I'm tired of waiting!
324main: Now I can quit.
325```
326
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300327<!--- TEST -->
328
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300329As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
330
331### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300332
Tair Rzayevaf734622017-02-01 22:30:16 +0200333Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300334All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300335coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300336a computation and does not check for cancellation, then it cannot be cancelled, like the following
337example shows:
338
339```kotlin
340fun main(args: Array<String>) = runBlocking<Unit> {
341 val job = launch(CommonPool) {
342 var nextPrintTime = 0L
343 var i = 0
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300344 while (i < 10) { // computation loop
Roman Elizarov7deefb82017-01-31 10:33:17 +0300345 val currentTime = System.currentTimeMillis()
346 if (currentTime >= nextPrintTime) {
347 println("I'm sleeping ${i++} ...")
348 nextPrintTime = currentTime + 500L
349 }
350 }
351 }
352 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300353 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300354 job.cancel() // cancels the job
355 delay(1300L) // delay a bit to see if it was cancelled....
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300356 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300357}
358```
359
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300360> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300361
362Run it to see that it continues to print "I'm sleeping" even after cancellation.
363
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300364<!--- TEST
365I'm sleeping 0 ...
366I'm sleeping 1 ...
367I'm sleeping 2 ...
368main: I'm tired of waiting!
369I'm sleeping 3 ...
370I'm sleeping 4 ...
371I'm sleeping 5 ...
372main: Now I can quit.
373-->
374
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300375### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300376
377There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov419a6c82017-02-09 18:36:22 +0300378invoke a suspending function. There is a [yield] function that is a good choice for that purpose.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300379The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300380
381Replace `while (true)` in the previous example with `while (isActive)` and rerun it.
382
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300383```kotlin
384fun main(args: Array<String>) = runBlocking<Unit> {
385 val job = launch(CommonPool) {
386 var nextPrintTime = 0L
387 var i = 0
388 while (isActive) { // cancellable computation loop
389 val currentTime = System.currentTimeMillis()
390 if (currentTime >= nextPrintTime) {
391 println("I'm sleeping ${i++} ...")
392 nextPrintTime = currentTime + 500L
393 }
394 }
395 }
396 delay(1300L) // delay a bit
397 println("main: I'm tired of waiting!")
398 job.cancel() // cancels the job
399 delay(1300L) // delay a bit to see if it was cancelled....
400 println("main: Now I can quit.")
401}
402```
403
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300404> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300405
Roman Elizarov419a6c82017-02-09 18:36:22 +0300406As you can see, now this loop can be cancelled. [isActive][CoroutineScope.isActive] is a property that is available inside
407the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300408
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300409<!--- TEST
410I'm sleeping 0 ...
411I'm sleeping 1 ...
412I'm sleeping 2 ...
413main: I'm tired of waiting!
414main: Now I can quit.
415-->
416
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300417### Closing resources with finally
418
Roman Elizarov419a6c82017-02-09 18:36:22 +0300419Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300420all the usual way. For example, the `try {...} finally {...}` and Kotlin `use` function execute their
421finalization actions normally when coroutine is cancelled:
422
423```kotlin
424fun main(args: Array<String>) = runBlocking<Unit> {
425 val job = launch(CommonPool) {
426 try {
427 repeat(1000) { i ->
428 println("I'm sleeping $i ...")
429 delay(500L)
430 }
431 } finally {
432 println("I'm running finally")
433 }
434 }
435 delay(1300L) // delay a bit
436 println("main: I'm tired of waiting!")
437 job.cancel() // cancels the job
438 delay(1300L) // delay a bit to ensure it was cancelled indeed
439 println("main: Now I can quit.")
440}
441```
442
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300443> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300444
445The example above produces the following output:
446
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300447```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300448I'm sleeping 0 ...
449I'm sleeping 1 ...
450I'm sleeping 2 ...
451main: I'm tired of waiting!
452I'm running finally
453main: Now I can quit.
454```
455
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300456<!--- TEST -->
457
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300458### Run non-cancellable block
459
460Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300461[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300462problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
463communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
464rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarov419a6c82017-02-09 18:36:22 +0300465`run(NonCancellable) {...}` using [run] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300466
467```kotlin
468fun main(args: Array<String>) = runBlocking<Unit> {
469 val job = launch(CommonPool) {
470 try {
471 repeat(1000) { i ->
472 println("I'm sleeping $i ...")
473 delay(500L)
474 }
475 } finally {
476 run(NonCancellable) {
477 println("I'm running finally")
478 delay(1000L)
479 println("And I've just delayed for 1 sec because I'm non-cancellable")
480 }
481 }
482 }
483 delay(1300L) // delay a bit
484 println("main: I'm tired of waiting!")
485 job.cancel() // cancels the job
486 delay(1300L) // delay a bit to ensure it was cancelled indeed
487 println("main: Now I can quit.")
488}
489```
490
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300491> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300492
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300493<!--- TEST
494I'm sleeping 0 ...
495I'm sleeping 1 ...
496I'm sleeping 2 ...
497main: I'm tired of waiting!
498I'm running finally
499And I've just delayed for 1 sec because I'm non-cancellable
500main: Now I can quit.
501-->
502
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300503### Timeout
504
505The most obvious reason to cancel coroutine execution in practice,
506is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300507While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
508the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300509Look at the following example:
510
511```kotlin
512fun main(args: Array<String>) = runBlocking<Unit> {
513 withTimeout(1300L) {
514 repeat(1000) { i ->
515 println("I'm sleeping $i ...")
516 delay(500L)
517 }
518 }
519}
520```
521
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300522> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300523
524It produces the following output:
525
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300526```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300527I'm sleeping 0 ...
528I'm sleeping 1 ...
529I'm sleeping 2 ...
530Exception in thread "main" java.util.concurrent.CancellationException: Timed out waiting for 1300 MILLISECONDS
531```
532
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300533<!--- TEST STARTS_WITH -->
534
Roman Elizarov419a6c82017-02-09 18:36:22 +0300535We have not seen the [CancellationException] stack trace printed on the console before. That is because
Roman Elizarov7c864d82017-02-27 10:17:50 +0300536inside a cancelled coroutine `CancellationException` is considered to be a normal reason for coroutine completion.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300537However, in this example we have used `withTimeout` right inside the `main` function.
538
539Because cancellation is just an exception, all the resources will be closed in a usual way.
540You can wrap the code with timeout in `try {...} catch (e: CancellationException) {...}` block if
541you need to do some additional action specifically on timeout.
542
543## Composing suspending functions
544
545This section covers various approaches to composition of suspending functions.
546
547### Sequential by default
548
549Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300550remote service call or computation. We just pretend they are useful, but actually each one just
551delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300552
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300553<!--- INCLUDE .*/example-compose-([0-9]+).kt
554import kotlin.system.measureTimeMillis
555-->
556
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300557```kotlin
558suspend fun doSomethingUsefulOne(): Int {
559 delay(1000L) // pretend we are doing something useful here
560 return 13
561}
562
563suspend fun doSomethingUsefulTwo(): Int {
564 delay(1000L) // pretend we are doing something useful here, too
565 return 29
566}
567```
568
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300569<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
570
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300571What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
572`doSomethingUsefulTwo` and compute the sum of their results?
573In practise we do this if we use the results of the first function to make a decision on whether we need
574to invoke the second one or to decide on how to invoke it.
575
576We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300577code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300578time it takes to execute both suspending functions:
579
580```kotlin
581fun main(args: Array<String>) = runBlocking<Unit> {
582 val time = measureTimeMillis {
583 val one = doSomethingUsefulOne()
584 val two = doSomethingUsefulTwo()
585 println("The answer is ${one + two}")
586 }
587 println("Completed in $time ms")
588}
589```
590
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300591> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300592
593It produces something like this:
594
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300595```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300596The answer is 42
597Completed in 2017 ms
598```
599
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300600<!--- TEST FLEXIBLE_TIME -->
601
Roman Elizarov32d95322017-02-09 15:57:31 +0300602### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300603
604What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300605we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300606
Roman Elizarov419a6c82017-02-09 18:36:22 +0300607Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
608that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
609does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300610that 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 +0300611but `Deferred` is also a `Job`, so you can cancel it if needed.
612
613```kotlin
614fun main(args: Array<String>) = runBlocking<Unit> {
615 val time = measureTimeMillis {
Roman Elizarov32d95322017-02-09 15:57:31 +0300616 val one = async(CommonPool) { doSomethingUsefulOne() }
617 val two = async(CommonPool) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300618 println("The answer is ${one.await() + two.await()}")
619 }
620 println("Completed in $time ms")
621}
622```
623
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300624> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300625
626It produces something like this:
627
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300628```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300629The answer is 42
630Completed in 1017 ms
631```
632
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300633<!--- TEST FLEXIBLE_TIME -->
634
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300635This is twice as fast, because we have concurrent execution of two coroutines.
636Note, that concurrency with coroutines is always explicit.
637
Roman Elizarov32d95322017-02-09 15:57:31 +0300638### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300639
Roman Elizarov419a6c82017-02-09 18:36:22 +0300640There is a laziness option to [async] with `start = false` parameter.
641It starts coroutine only when its result is needed by some
642[await][Deferred.await] or if a [start][Job.start] function
Roman Elizarov32d95322017-02-09 15:57:31 +0300643is invoked. Run the following example that differs from the previous one only by this option:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300644
645```kotlin
646fun main(args: Array<String>) = runBlocking<Unit> {
647 val time = measureTimeMillis {
Roman Elizarov32d95322017-02-09 15:57:31 +0300648 val one = async(CommonPool, start = false) { doSomethingUsefulOne() }
649 val two = async(CommonPool, start = false) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300650 println("The answer is ${one.await() + two.await()}")
651 }
652 println("Completed in $time ms")
653}
654```
655
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300656> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300657
658It produces something like this:
659
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300660```text
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300661The answer is 42
662Completed in 2017 ms
663```
664
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300665<!--- TEST FLEXIBLE_TIME -->
666
Roman Elizarov32d95322017-02-09 15:57:31 +0300667So, we are back to sequential execution, because we _first_ start and await for `one`, _and then_ start and await
668for `two`. It is not the intended use-case for laziness. It is designed as a replacement for
669the standard `lazy` function in cases when computation of the value involves suspending functions.
670
671### Async-style functions
672
673We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300674_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Roman Elizarov32d95322017-02-09 15:57:31 +0300675either "async" prefix of "Async" suffix to highlight the fact that they only start asynchronous
676computation and one needs to use the resulting deferred value to get the result.
677
678```kotlin
679// The result type of asyncSomethingUsefulOne is Deferred<Int>
680fun asyncSomethingUsefulOne() = async(CommonPool) {
681 doSomethingUsefulOne()
682}
683
684// The result type of asyncSomethingUsefulTwo is Deferred<Int>
685fun asyncSomethingUsefulTwo() = async(CommonPool) {
686 doSomethingUsefulTwo()
687}
688```
689
690Note, that these `asyncXXX` function are **not** _suspending_ functions. They can be used from anywhere.
691However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
692with the invoking code.
693
694The following example shows their use outside of coroutine:
695
696```kotlin
697// note, that we don't have `runBlocking` to the right of `main` in this example
698fun main(args: Array<String>) {
699 val time = measureTimeMillis {
700 // we can initiate async actions outside of a coroutine
701 val one = asyncSomethingUsefulOne()
702 val two = asyncSomethingUsefulTwo()
703 // but waiting for a result must involve either suspending or blocking.
704 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
705 runBlocking {
706 println("The answer is ${one.await() + two.await()}")
707 }
708 }
709 println("Completed in $time ms")
710}
711```
712
713> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300714
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300715<!--- TEST FLEXIBLE_TIME
716The answer is 42
717Completed in 1085 ms
718-->
719
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300720## Coroutine context and dispatchers
721
Roman Elizarov32d95322017-02-09 15:57:31 +0300722We've already seen `launch(CommonPool) {...}`, `async(CommonPool) {...}`, `run(NonCancellable) {...}`, etc.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300723In these code snippets [CommonPool] and [NonCancellable] are _coroutine contexts_.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300724This section covers other available choices.
725
726### Dispatchers and threads
727
Roman Elizarov419a6c82017-02-09 18:36:22 +0300728Coroutine context includes a [_coroutine dispatcher_][CoroutineDispatcher] which determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300729the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
730to a specific thread, dispatch it to a thread pool, or let it run unconfined. Try the following example:
731
732```kotlin
733fun main(args: Array<String>) = runBlocking<Unit> {
734 val jobs = arrayListOf<Job>()
735 jobs += launch(Unconfined) { // not confined -- will work with main thread
736 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
737 }
738 jobs += launch(context) { // context of the parent, runBlocking coroutine
739 println(" 'context': I'm working in thread ${Thread.currentThread().name}")
740 }
741 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
742 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
743 }
744 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
745 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
746 }
747 jobs.forEach { it.join() }
748}
749```
750
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300751> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300752
753It produces the following output (maybe in different order):
754
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300755```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300756 'Unconfined': I'm working in thread main
757 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
758 'newSTC': I'm working in thread MyOwnThread
759 'context': I'm working in thread main
760```
761
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300762<!--- TEST LINES_START_UNORDERED -->
763
Roman Elizarov419a6c82017-02-09 18:36:22 +0300764The difference between parent [context][CoroutineScope.context] and [Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300765
766### Unconfined vs confined dispatcher
767
Roman Elizarov419a6c82017-02-09 18:36:22 +0300768The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300769first suspension point. After suspension it resumes in the thread that is fully determined by the
770suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
771consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
772
Roman Elizarov419a6c82017-02-09 18:36:22 +0300773On the other side, [context][CoroutineScope.context] property that is available inside the block of any coroutine
774via [CoroutineScope] interface, is a reference to a context of this particular coroutine.
775This way, a parent context can be inherited. The default context of [runBlocking], in particular,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300776is confined to be invoker thread, so inheriting it has the effect of confining execution to
777this thread with a predictable FIFO scheduling.
778
779```kotlin
780fun main(args: Array<String>) = runBlocking<Unit> {
781 val jobs = arrayListOf<Job>()
782 jobs += launch(Unconfined) { // not confined -- will work with main thread
783 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
784 delay(1000)
785 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
786 }
787 jobs += launch(context) { // context of the parent, runBlocking coroutine
788 println(" 'context': I'm working in thread ${Thread.currentThread().name}")
789 delay(1000)
790 println(" 'context': After delay in thread ${Thread.currentThread().name}")
791 }
792 jobs.forEach { it.join() }
793}
794```
795
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300796> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-contest-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300797
798Produces the output:
799
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300800```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300801 'Unconfined': I'm working in thread main
802 'context': I'm working in thread main
803 'Unconfined': After delay in thread kotlinx.coroutines.ScheduledExecutor
804 'context': After delay in thread main
805```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300806
807<!--- TEST LINES_START -->
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300808
Roman Elizarov7c864d82017-02-27 10:17:50 +0300809So, the coroutine that had inherited `context` of `runBlocking {...}` continues to execute in the `main` thread,
Roman Elizarov419a6c82017-02-09 18:36:22 +0300810while the unconfined one had resumed in the scheduler thread that [delay] function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300811
812### Debugging coroutines and threads
813
Roman Elizarov419a6c82017-02-09 18:36:22 +0300814Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
815with a multi-threaded dispatcher like [CommonPool]. Even with a single-threaded dispatcher it might be hard to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300816figure out what coroutine was doing what, where, and when. The common approach to debugging applications with
817threads is to print the thread name in the log file on each log statement. This feature is universally supported
818by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
819`kotlinx.coroutines` includes debugging facilities to make it easier.
820
821Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
822
823```kotlin
824fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
825
826fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov32d95322017-02-09 15:57:31 +0300827 val a = async(context) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300828 log("I'm computing a piece of the answer")
829 6
830 }
Roman Elizarov32d95322017-02-09 15:57:31 +0300831 val b = async(context) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300832 log("I'm computing another piece of the answer")
833 7
834 }
835 log("The answer is ${a.await() * b.await()}")
836}
837```
838
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300839> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300840
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300841There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300842and two coroutines computing deferred values `a` (#2) and `b` (#3).
843They are all executing in the context of `runBlocking` and are confined to the main thread.
844The output of this code is:
845
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300846```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300847[main @coroutine#2] I'm computing a piece of the answer
848[main @coroutine#3] I'm computing another piece of the answer
849[main @coroutine#1] The answer is 42
850```
851
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300852<!--- TEST -->
853
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300854The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
855thread, but the identifier of the currently executing coroutine is appended to it. This identifier
856is consecutively assigned to all created coroutines when debugging mode is turned on.
857
Roman Elizarov419a6c82017-02-09 18:36:22 +0300858You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300859
860### Jumping between threads
861
862Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
863
864```kotlin
865fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
866
867fun main(args: Array<String>) {
868 val ctx1 = newSingleThreadContext("Ctx1")
869 val ctx2 = newSingleThreadContext("Ctx2")
870 runBlocking(ctx1) {
871 log("Started in ctx1")
872 run(ctx2) {
873 log("Working in ctx2")
874 }
875 log("Back to ctx1")
876 }
877}
878```
879
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300880> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300881
Roman Elizarov419a6c82017-02-09 18:36:22 +0300882It demonstrates two new techniques. One is using [runBlocking] with an explicitly specified context, and
883the 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 +0300884same coroutine as you can see in the output below:
885
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300886```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300887[Ctx1 @coroutine#1] Started in ctx1
888[Ctx2 @coroutine#1] Working in ctx2
889[Ctx1 @coroutine#1] Back to ctx1
890```
891
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300892<!--- TEST -->
893
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300894### Job in the context
895
Roman Elizarov419a6c82017-02-09 18:36:22 +0300896The coroutine [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300897using `context[Job]` expression:
898
899```kotlin
900fun main(args: Array<String>) = runBlocking<Unit> {
901 println("My job is ${context[Job]}")
902}
903```
904
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300905> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300906
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300907It produces somethine like
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300908
909```
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300910My job is BlockingCoroutine{Active}@65ae6ba4
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300911```
912
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300913<!--- TEST lines.size == 1 && lines[0].startsWith("My job is BlockingCoroutine{Active}@") -->
914
Roman Elizarov419a6c82017-02-09 18:36:22 +0300915So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for `context[Job]!!.isActive`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300916
917### Children of a coroutine
918
Roman Elizarov419a6c82017-02-09 18:36:22 +0300919When [context][CoroutineScope.context] of a coroutine is used to launch another coroutine,
920the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300921a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
922are recursively cancelled, too.
923
924```kotlin
925fun main(args: Array<String>) = runBlocking<Unit> {
926 // start a coroutine to process some kind of incoming request
927 val request = launch(CommonPool) {
928 // it spawns two other jobs, one with its separate context
929 val job1 = launch(CommonPool) {
930 println("job1: I have my own context and execute independently!")
931 delay(1000)
932 println("job1: I am not affected by cancellation of the request")
933 }
934 // and the other inherits the parent context
935 val job2 = launch(context) {
936 println("job2: I am a child of the request coroutine")
937 delay(1000)
938 println("job2: I will not execute this line if my parent request is cancelled")
939 }
940 // request completes when both its sub-jobs complete:
941 job1.join()
942 job2.join()
943 }
944 delay(500)
945 request.cancel() // cancel processing of the request
946 delay(1000) // delay a second to see what happens
947 println("main: Who has survived request cancellation?")
948}
949```
950
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300951> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300952
953The output of this code is:
954
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300955```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300956job1: I have my own context and execute independently!
957job2: I am a child of the request coroutine
958job1: I am not affected by cancellation of the request
959main: Who has survived request cancellation?
960```
961
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300962<!--- TEST -->
963
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300964### Combining contexts
965
966Coroutine context can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +0300967of 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 +0300968its dispatcher replaced:
969
970```kotlin
971fun main(args: Array<String>) = runBlocking<Unit> {
972 // start a coroutine to process some kind of incoming request
973 val request = launch(context) { // use the context of `runBlocking`
974 // spawns CPU-intensive child job in CommonPool !!!
975 val job = launch(context + CommonPool) {
976 println("job: I am a child of the request coroutine, but with a different dispatcher")
977 delay(1000)
978 println("job: I will not execute this line if my parent request is cancelled")
979 }
980 job.join() // request completes when its sub-job completes
981 }
982 delay(500)
983 request.cancel() // cancel processing of the request
984 delay(1000) // delay a second to see what happens
985 println("main: Who has survived request cancellation?")
986}
987```
988
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300989> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300990
991The expected outcome of this code is:
992
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300993```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300994job: I am a child of the request coroutine, but with a different dispatcher
995main: Who has survived request cancellation?
996```
997
Roman Elizarov731f0ad2017-02-22 20:48:45 +0300998<!--- TEST -->
999
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001000### Naming coroutines for debugging
1001
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001002Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001003coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
1004or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001005[CoroutineName] serves the same function as a thread name. It'll get displayed in the thread name that
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001006is executing this coroutine when debugging more is turned on.
1007
1008The following example demonstrates this concept:
1009
1010```kotlin
1011fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
1012
1013fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
1014 log("Started main coroutine")
1015 // run two background value computations
Roman Elizarov32d95322017-02-09 15:57:31 +03001016 val v1 = async(CommonPool + CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001017 log("Computing v1")
1018 delay(500)
1019 252
1020 }
Roman Elizarov32d95322017-02-09 15:57:31 +03001021 val v2 = async(CommonPool + CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001022 log("Computing v2")
1023 delay(1000)
1024 6
1025 }
1026 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
1027}
1028```
1029
Roman Elizarovfa7723e2017-02-06 11:17:51 +03001030> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001031
1032The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
1033
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001034```text
Roman Elizarov2f6d7c92017-02-03 15:16:07 +03001035[main @main#1] Started main coroutine
1036[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
1037[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
1038[main @main#1] The answer for v1 / v2 = 42
1039```
Roman Elizarov1293ccd2017-02-01 18:49:54 +03001040
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001041<!--- TEST FLEXIBLE_THREAD -->
1042
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001043### Cancellation via explicit job
1044
1045Let us put our knowledge about contexts, children and jobs together. Assume that our application has
1046an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
1047and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
1048and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
1049to avoid memory leaks.
1050
1051We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
1052the lifecycle of our activity. A job instance is created using [Job()][Job.invoke] factory function
1053as the following example shows. We need to make sure that all the coroutines are started
1054with this job in their context and then a single invocation of [Job.cancel] terminates them all.
1055
1056```kotlin
1057fun main(args: Array<String>) = runBlocking<Unit> {
1058 val job = Job() // create a job object to manage our lifecycle
1059 // now launch ten coroutines for a demo, each working for a different time
1060 val coroutines = List(10) { i ->
1061 // they are all children of our job object
1062 launch(context + job) { // we use the context of main runBlocking thread, but with our own job object
1063 delay(i * 200L) // variable delay 0ms, 200ms, 400ms, ... etc
1064 println("Coroutine $i is done")
1065 }
1066 }
1067 println("Launched ${coroutines.size} coroutines")
1068 delay(500L) // delay for half a second
1069 println("Cancelling job!")
1070 job.cancel() // cancel our job.. !!!
1071 delay(1000L) // delay for more to see if our coroutines are still working
1072}
1073```
1074
1075> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-09.kt)
1076
1077The output of this example is:
1078
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001079```text
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001080Launched 10 coroutines
1081Coroutine 0 is done
1082Coroutine 1 is done
1083Coroutine 2 is done
1084Cancelling job!
1085```
1086
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001087<!--- TEST -->
1088
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001089As you can see, only the first three coroutines had printed a message and the others were cancelled
1090by a single invocation of `job.cancel()`. So all we need to do in our hypothetical Android
1091application is to create a parent job object when activity is created, use it for child coroutines,
1092and cancel it when activity is destroyed.
1093
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001094## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001095
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001096Deferred values provide a convenient way to transfer a single value between coroutines.
1097Channels provide a way to transfer a stream of values.
1098
1099<!--- INCLUDE .*/example-channel-([0-9]+).kt
1100import kotlinx.coroutines.experimental.channels.*
1101-->
1102
1103### Channel basics
1104
Roman Elizarov419a6c82017-02-09 18:36:22 +03001105A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1106instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1107a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001108
1109```kotlin
1110fun main(args: Array<String>) = runBlocking<Unit> {
1111 val channel = Channel<Int>()
1112 launch(CommonPool) {
1113 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1114 for (x in 1..5) channel.send(x * x)
1115 }
1116 // here we print five received integers:
1117 repeat(5) { println(channel.receive()) }
1118 println("Done!")
1119}
1120```
1121
1122> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-01.kt)
1123
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001124The output of this code is:
1125
1126```text
11271
11284
11299
113016
113125
1132Done!
1133```
1134
1135<!--- TEST -->
1136
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001137### Closing and iteration over channels
1138
1139Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1140On the receiver side it is convenient to use a regular `for` loop to receive elements
1141from the channel.
1142
Roman Elizarov419a6c82017-02-09 18:36:22 +03001143Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001144The iteration stops as soon as this close token is received, so there is a guarantee
1145that all previously sent elements before the close are received:
1146
1147```kotlin
1148fun main(args: Array<String>) = runBlocking<Unit> {
1149 val channel = Channel<Int>()
1150 launch(CommonPool) {
1151 for (x in 1..5) channel.send(x * x)
1152 channel.close() // we're done sending
1153 }
1154 // here we print received values using `for` loop (until the channel is closed)
1155 for (y in channel) println(y)
1156 println("Done!")
1157}
1158```
1159
1160> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-02.kt)
1161
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001162<!--- TEST
11631
11644
11659
116616
116725
1168Done!
1169-->
1170
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001171### Building channel producers
1172
Roman Elizarova5e653f2017-02-13 13:49:55 +03001173The pattern where a coroutine is producing a sequence of elements is quite common.
1174This is a part of _producer-consumer_ pattern that is often found in concurrent code.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001175You 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 +03001176to common sense that results must be returned from functions.
1177
1178There is a convenience coroutine builder named [produce] that makes it easy to do it right:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001179
1180```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001181fun produceSquares() = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001182 for (x in 1..5) send(x * x)
1183}
1184
1185fun main(args: Array<String>) = runBlocking<Unit> {
1186 val squares = produceSquares()
1187 for (y in squares) println(y)
1188 println("Done!")
1189}
1190```
1191
1192> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-03.kt)
1193
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001194<!--- TEST
11951
11964
11979
119816
119925
1200Done!
1201-->
1202
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001203### Pipelines
1204
1205Pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
1206
1207```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001208fun produceNumbers() = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001209 var x = 1
1210 while (true) send(x++) // infinite stream of integers starting from 1
1211}
1212```
1213
Roman Elizarova5e653f2017-02-13 13:49:55 +03001214And another coroutine or coroutines are consuming that stream, doing some processing, and producing some other results.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001215In the below example the numbers are just squared:
1216
1217```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001218fun square(numbers: ReceiveChannel<Int>) = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001219 for (x in numbers) send(x * x)
1220}
1221```
1222
Roman Elizarova5e653f2017-02-13 13:49:55 +03001223The main code starts and connects the whole pipeline:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001224
1225```kotlin
1226fun main(args: Array<String>) = runBlocking<Unit> {
1227 val numbers = produceNumbers() // produces integers from 1 and on
1228 val squares = square(numbers) // squares integers
1229 for (i in 1..5) println(squares.receive()) // print first five
1230 println("Done!") // we are done
1231 squares.cancel() // need to cancel these coroutines in a larger app
1232 numbers.cancel()
1233}
1234```
1235
1236> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-04.kt)
1237
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001238<!--- TEST
12391
12404
12419
124216
124325
1244Done!
1245-->
1246
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001247We don't have to cancel these coroutines in this example app, because
1248[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1249but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1250Alternatively, we could have run pipeline coroutines as
1251[children of a coroutine](#children-of-a-coroutine).
1252
1253### Prime numbers with pipeline
1254
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001255Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001256of coroutines. We start with an infinite sequence of numbers. This time we introduce an
1257explicit context parameter, so that caller can control where our coroutines run:
1258
1259<!--- INCLUDE kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
1260import kotlin.coroutines.experimental.CoroutineContext
1261-->
1262
1263```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001264fun numbersFrom(context: CoroutineContext, start: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001265 var x = start
1266 while (true) send(x++) // infinite stream of integers from start
1267}
1268```
1269
1270The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1271that are divisible by the given prime number:
1272
1273```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001274fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = produce<Int>(context) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001275 for (x in numbers) if (x % prime != 0) send(x)
1276}
1277```
1278
1279Now 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 +03001280and launching new pipeline stage for each prime number found:
1281
1282```
Roman Elizarova5e653f2017-02-13 13:49:55 +03001283numbersFrom(2) -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
Roman Elizarov62500ba2017-02-09 18:55:40 +03001284```
1285
1286The following example prints the first ten prime numbers,
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001287running the whole pipeline in the context of the main thread:
1288
1289```kotlin
1290fun main(args: Array<String>) = runBlocking<Unit> {
1291 var cur = numbersFrom(context, 2)
1292 for (i in 1..10) {
1293 val prime = cur.receive()
1294 println(prime)
1295 cur = filter(context, cur, prime)
1296 }
1297}
1298```
1299
1300> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt)
1301
1302The output of this code is:
1303
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001304```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +030013052
13063
13075
13087
130911
131013
131117
131219
131323
131429
1315```
1316
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001317<!--- TEST -->
1318
Roman Elizarova5e653f2017-02-13 13:49:55 +03001319Note, that you can build the same pipeline using `buildIterator` coroutine builder from the standard library.
1320Replace `produce` with `buildIterator`, `send` with `yield`, `receive` with `next`,
Roman Elizarov62500ba2017-02-09 18:55:40 +03001321`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1322However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1323multiple CPU cores if you run it in [CommonPool] context.
1324
Roman Elizarova5e653f2017-02-13 13:49:55 +03001325Anyway, this is an extremely impractical way to find prime numbers. In practice, pipelines do involve some
Roman Elizarov62500ba2017-02-09 18:55:40 +03001326other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1327built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
Roman Elizarova5e653f2017-02-13 13:49:55 +03001328`produce` which is fully asynchronous.
Roman Elizarov62500ba2017-02-09 18:55:40 +03001329
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001330### Fan-out
1331
1332Multiple coroutines may receive from the same channel, distributing work between themselves.
1333Let us start with a producer coroutine that is periodically producing integers
1334(ten numbers per second):
1335
1336```kotlin
Roman Elizarova5e653f2017-02-13 13:49:55 +03001337fun produceNumbers() = produce<Int>(CommonPool) {
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001338 var x = 1 // start from 1
1339 while (true) {
1340 send(x++) // produce next
1341 delay(100) // wait 0.1s
1342 }
1343}
1344```
1345
1346Then we can have several processor coroutines. In this example, they just print their id and
1347received number:
1348
1349```kotlin
1350fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch(CommonPool) {
1351 while (true) {
1352 val x = channel.receive()
1353 println("Processor #$id received $x")
1354 }
1355}
1356```
1357
1358Now let us launch five processors and let them work for a second. See what happens:
1359
1360```kotlin
1361fun main(args: Array<String>) = runBlocking<Unit> {
1362 val producer = produceNumbers()
1363 repeat(5) { launchProcessor(it, producer) }
1364 delay(1000)
1365 producer.cancel() // cancel producer coroutine and thus kill them all
1366}
1367```
1368
1369> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-06.kt)
1370
1371The output will be similar to the the following one, albeit the processor ids that receive
1372each specific integer may be different:
1373
1374```
1375Processor #2 received 1
1376Processor #4 received 2
1377Processor #0 received 3
1378Processor #1 received 4
1379Processor #3 received 5
1380Processor #2 received 6
1381Processor #4 received 7
1382Processor #0 received 8
1383Processor #1 received 9
1384Processor #3 received 10
1385```
1386
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001387<!--- TEST lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") } -->
1388
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001389Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1390over the channel that processor coroutines are doing.
1391
1392### Fan-in
1393
1394Multiple coroutines may send to the same channel.
1395For example, let us have a channel of strings, and a suspending function that
1396repeatedly sends a specified string to this channel with a specified delay:
1397
1398```kotlin
1399suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1400 while (true) {
1401 delay(time)
1402 channel.send(s)
1403 }
1404}
1405```
1406
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001407Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001408(in this example we launch them in the context of the main thread):
1409
1410```kotlin
1411fun main(args: Array<String>) = runBlocking<Unit> {
1412 val channel = Channel<String>()
1413 launch(context) { sendString(channel, "foo", 200L) }
1414 launch(context) { sendString(channel, "BAR!", 500L) }
1415 repeat(6) { // receive first six
1416 println(channel.receive())
1417 }
1418}
1419```
1420
1421> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt)
1422
1423The output is:
1424
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001425```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001426foo
1427foo
1428BAR!
1429foo
1430foo
1431BAR!
1432```
1433
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001434<!--- TEST -->
1435
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001436### Buffered channels
1437
1438The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1439meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1440if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001441
Roman Elizarova5e653f2017-02-13 13:49:55 +03001442Both [Channel()][Channel.invoke] factory function and [produce] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001443specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1444similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1445
1446Take a look at the behavior of the following code:
1447
1448```kotlin
1449fun main(args: Array<String>) = runBlocking<Unit> {
1450 val channel = Channel<Int>(4) // create buffered channel
1451 launch(context) { // launch sender coroutine
1452 repeat(10) {
1453 println("Sending $it") // print before sending each element
1454 channel.send(it) // will suspend when buffer is full
1455 }
1456 }
1457 // don't receive anything... just wait....
1458 delay(1000)
1459}
1460```
1461
1462> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt)
1463
1464It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1465
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001466```text
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001467Sending 0
1468Sending 1
1469Sending 2
1470Sending 3
1471Sending 4
1472```
1473
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001474<!--- TEST -->
1475
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001476The 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 +03001477
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001478## Shared mutable state and concurrency
1479
1480Coroutines can be executed concurrently using a multi-threaded dispatcher like [CommonPool]. It presents
1481all the usual concurrency problems. The main problem being synchronization of access to **shared mutable state**.
1482Some solutions to this problem in the land of coroutines are similar to the solutions in the multi-threaded world,
1483but others are unique.
1484
1485### The problem
1486
1487Let us launch 100k coroutines all doing the same action. We'll also measure their completion time for
1488further comparisons:
1489
1490<!--- INCLUDE .*/example-sync-([0-9]+).kt
1491import kotlin.system.measureTimeMillis
1492-->
1493
1494<!--- INCLUDE .*/example-sync-02.kt
1495import java.util.concurrent.atomic.AtomicInteger
1496-->
1497
1498<!--- INCLUDE .*/example-sync-04.kt
1499import kotlinx.coroutines.experimental.sync.Mutex
1500-->
1501
1502<!--- INCLUDE .*/example-sync-05.kt
1503import kotlinx.coroutines.experimental.channels.*
1504-->
1505
1506```kotlin
1507suspend fun massiveRun(action: suspend () -> Unit) {
1508 val n = 100_000
1509 val time = measureTimeMillis {
1510 val jobs = List(n) {
1511 launch(CommonPool) {
1512 action()
1513 }
1514 }
1515 jobs.forEach { it.join() }
1516 }
1517 println("Completed in $time ms")
1518}
1519```
1520
1521<!--- INCLUDE .*/example-sync-([0-9]+).kt -->
1522
Roman Elizarova84730b2017-02-22 11:58:50 +03001523We start with a very simple action that increments a shared mutable variable.
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001524
1525```kotlin
1526var counter = 0
1527
1528fun main(args: Array<String>) = runBlocking<Unit> {
1529 massiveRun {
1530 counter++
1531 }
1532 println("Counter = $counter")
1533}
1534```
1535
1536> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01.kt)
1537
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001538<!--- TEST lines.size == 2 && lines[1].startsWith("Counter = ") -->
1539
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001540What does it print at the end? It is highly unlikely to ever print "100000", because all the
1541100k coroutines increment the `counter` concurrently without any synchronization.
1542
1543### Thread-safe data structures
1544
1545The general solution that works both for threads and for coroutines is to use a thread-safe (aka synchronized,
1546linearizable, or atomic) data structure that provides all the necessarily synchronization for the corresponding
1547operations that needs to be performed on a shared state.
1548In the case of a simple counter we can use `AtomicInteger` class:
1549
1550```kotlin
1551var counter = AtomicInteger()
1552
1553fun main(args: Array<String>) = runBlocking<Unit> {
1554 massiveRun {
1555 counter.incrementAndGet()
1556 }
1557 println("Counter = ${counter.get()}")
1558}
1559```
1560
1561> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-02.kt)
1562
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001563<!--- TEST lines.size == 2 && lines[1] == "Counter = 100000" -->
1564
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001565This is the fastest solution for this particular problem. It works for plain counters, collections, queues and other
1566standard data structures and basic operations on them. However, it does not easily scale to complex
1567state or to complex operations that do not have ready-to-use thread-safe implementations.
1568
1569### Thread confinement
1570
1571Thread confinement is an approach to the problem of shared mutable state where all access to the particular shared
1572state is confined to a single thread. It is typically used in UI applications, where all UI state is confined to
1573the single event-dispatch/application thread. It is easy to apply with coroutines by using a
1574single-threaded context:
1575
1576```kotlin
1577val counterContext = newSingleThreadContext("CounterContext")
1578var counter = 0
1579
1580fun main(args: Array<String>) = runBlocking<Unit> {
1581 massiveRun {
1582 run(counterContext) {
1583 counter++
1584 }
1585 }
1586 println("Counter = $counter")
1587}
1588```
1589
1590> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-03.kt)
1591
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001592<!--- TEST lines.size == 2 && lines[1] == "Counter = 100000" -->
1593
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001594### Mutual exclusion
1595
1596Mutual exclusion solution to the problem is to protect all modifications of the shared state with a _critical section_
1597that is never executed concurrently. In a blocking world you'd typically use `synchronized` or `ReentrantLock` for that.
1598Coroutine's alternative is called [Mutex]. It has [lock][Mutex.lock] and [unlock][Mutex.unlock] functions to
1599delimit a critical section. The key difference is that `Mutex.lock` is a suspending function. It does not block a thread.
1600
1601```kotlin
1602val mutex = Mutex()
1603var counter = 0
1604
1605fun main(args: Array<String>) = runBlocking<Unit> {
1606 massiveRun {
1607 mutex.lock()
1608 try { counter++ }
1609 finally { mutex.unlock() }
1610 }
1611 println("Counter = $counter")
1612}
1613```
1614
1615> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-04.kt)
1616
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001617<!--- TEST lines.size == 2 && lines[1] == "Counter = 100000" -->
1618
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001619### Actors
1620
1621An actor is a combination of a coroutine, the state that is confined and is encapsulated into this coroutine,
1622and a channel to communicate with other coroutines. A simple actor can be written as a function,
1623but an actor with a complex state is better suited for a class.
1624
1625```kotlin
1626// Message types for counterActor
1627sealed class CounterMsg
1628object IncCounter : CounterMsg() // one-way message to increment counter
1629class GetCounter(val response: SendChannel<Int>) : CounterMsg() // a request with reply
1630
1631// This function launches a new counter actor
1632fun counterActor(request: ReceiveChannel<CounterMsg>) = launch(CommonPool) {
1633 var counter = 0 // actor state
Roman Elizarova84730b2017-02-22 11:58:50 +03001634 while (isActive) { // main loop of the actor
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001635 val msg = request.receive()
1636 when (msg) {
1637 is IncCounter -> counter++
1638 is GetCounter -> msg.response.send(counter)
1639 }
1640 }
1641}
1642
1643fun main(args: Array<String>) = runBlocking<Unit> {
1644 val request = Channel<CounterMsg>()
1645 counterActor(request)
1646 massiveRun {
1647 request.send(IncCounter)
1648 }
1649 val response = Channel<Int>()
1650 request.send(GetCounter(response))
1651 println("Counter = ${response.receive()}")
1652}
1653```
1654
1655> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-05.kt)
1656
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001657<!--- TEST lines.size == 2 && lines[1] == "Counter = 100000" -->
1658
Roman Elizarovf5bc0472017-02-22 11:38:13 +03001659Notice, that it does not matter (for correctness) what context the actor itself is executed in. An actor is
1660a coroutine and a coroutine is executed sequentially, so confinement of the state to the specific coroutine
1661works as a solution to the problem of shared mutable state.
1662
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001663## Select expression
1664
Roman Elizarova84730b2017-02-22 11:58:50 +03001665Select expression makes it possible to await multiple suspending functions simultaneously and _select_
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001666the first one that becomes available.
1667
1668<!--- INCLUDE .*/example-select-([0-9]+).kt
1669import kotlinx.coroutines.experimental.channels.*
1670import kotlinx.coroutines.experimental.selects.*
1671-->
1672
1673### Selecting from channels
1674
1675Let us have two channels of strings `fizz` and `buzz`. The `fizz` channel produces "Fizz" string every 300 ms:
1676
1677```kotlin
1678val fizz = produce<String>(CommonPool) { // produce using common thread pool
1679 while (true) {
1680 delay(300)
1681 send("Fizz")
1682 }
1683}
1684```
1685
1686And the `buzz` channel produces "Buzz!" string every 500 ms:
1687
1688```kotlin
1689val buzz = produce<String>(CommonPool) {
1690 while (true) {
1691 delay(500)
1692 send("Buzz!")
1693 }
1694}
1695```
1696
1697Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
1698other. But [select] expression allows us to receive from _both_ simultaneously using its
1699[onReceive][SelectBuilder.onReceive] clauses:
1700
1701```kotlin
1702suspend fun selectFizzBuzz() {
1703 select<Unit> { // <Unit> means that this select expression does not produce any result
1704 fizz.onReceive { value -> // this is the first select clause
1705 println("fizz -> '$value'")
1706 }
1707 buzz.onReceive { value -> // this is the second select clause
1708 println("buzz -> '$value'")
1709 }
1710 }
1711}
1712```
1713
Roman Elizarova84730b2017-02-22 11:58:50 +03001714Let us run it seven times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001715
1716```kotlin
1717fun main(args: Array<String>) = runBlocking<Unit> {
1718 repeat(7) {
1719 selectFizzBuzz()
1720 }
1721}
1722```
1723
1724> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-01.kt)
1725
1726The result of this code is:
1727
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001728```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001729fizz -> 'Fizz'
1730buzz -> 'Buzz!'
1731fizz -> 'Fizz'
1732fizz -> 'Fizz'
1733buzz -> 'Buzz!'
1734fizz -> 'Fizz'
1735buzz -> 'Buzz!'
1736```
1737
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001738<!--- TEST -->
1739
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001740### Selecting on close
1741
1742The [onReceive][SelectBuilder.onReceive] clause in `select` fails when the channel is closed and the corresponding
1743`select` throws an exception. We can use [onReceiveOrNull][SelectBuilder.onReceiveOrNull] clause to perform a
Roman Elizarova84730b2017-02-22 11:58:50 +03001744specific 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 +03001745the result of its selected clause:
1746
1747```kotlin
1748suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): String =
1749 select<String> {
1750 a.onReceiveOrNull { value ->
1751 if (value == null)
1752 "Channel 'a' is closed"
1753 else
1754 "a -> '$value'"
1755 }
1756 b.onReceiveOrNull { value ->
1757 if (value == null)
1758 "Channel 'b' is closed"
1759 else
1760 "b -> '$value'"
1761 }
1762 }
1763```
1764
Roman Elizarova84730b2017-02-22 11:58:50 +03001765Let's use it with channel `a` that produces "Hello" string four times and
1766channel `b` that produces "World" four times:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001767
1768```kotlin
1769fun main(args: Array<String>) = runBlocking<Unit> {
1770 // we are using the context of the main thread in this example for predictability ...
1771 val a = produce<String>(context) {
Roman Elizarova84730b2017-02-22 11:58:50 +03001772 repeat(4) { send("Hello $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001773 }
1774 val b = produce<String>(context) {
Roman Elizarova84730b2017-02-22 11:58:50 +03001775 repeat(4) { send("World $it") }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001776 }
1777 repeat(8) { // print first eight results
1778 println(selectAorB(a, b))
1779 }
1780}
1781```
1782
1783> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-02.kt)
1784
Roman Elizarova84730b2017-02-22 11:58:50 +03001785The result of this code is quite interesting, so we'll analyze it in mode detail:
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001786
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001787```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001788a -> 'Hello 0'
1789a -> 'Hello 1'
1790b -> 'World 0'
1791a -> 'Hello 2'
1792a -> 'Hello 3'
1793b -> 'World 1'
1794Channel 'a' is closed
1795Channel 'a' is closed
1796```
1797
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001798<!--- TEST -->
1799
Roman Elizarova84730b2017-02-22 11:58:50 +03001800There are couple of observations to make out of it.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001801
1802First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
1803the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
Roman Elizarova84730b2017-02-22 11:58:50 +03001804being 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 +03001805time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
1806
1807The second observation, is that [onReceiveOrNull][SelectBuilder.onReceiveOrNull] gets immediately selected when the
1808channel is already closed.
1809
1810### Selecting to send
1811
1812Select expression has [onSend][SelectBuilder.onSend] clause that can be used for a great good in combination
1813with a biased nature of selection.
1814
Roman Elizarova84730b2017-02-22 11:58:50 +03001815Let us write an example of producer of integers that sends its values to a `side` channel when
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001816the consumers on its primary channel cannot keep up with it:
1817
1818```kotlin
1819fun produceNumbers(side: SendChannel<Int>) = produce<Int>(CommonPool) {
1820 for (num in 1..10) { // produce 10 numbers from 1 to 10
1821 delay(100) // every 100 ms
1822 select<Unit> {
Roman Elizarova84730b2017-02-22 11:58:50 +03001823 onSend(num) {} // Send to the primary channel
1824 side.onSend(num) {} // or to the side channel
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001825 }
1826 }
1827}
1828```
1829
1830Consumer is going to be quite slow, taking 250 ms to process each number:
1831
1832```kotlin
1833fun main(args: Array<String>) = runBlocking<Unit> {
1834 val side = Channel<Int>() // allocate side channel
1835 launch(context) { // this is a very fast consumer for the side channel
1836 for (num in side) println("Side channel has $num")
1837 }
1838 for (num in produceNumbers(side)) {
1839 println("Consuming $num")
1840 delay(250) // let us digest the consumed number properly, do not hurry
1841 }
1842 println("Done consuming")
1843}
1844```
1845
1846> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-03.kt)
1847
1848So let us see what happens:
1849
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001850```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001851Consuming 1
1852Side channel has 2
1853Side channel has 3
1854Consuming 4
1855Side channel has 5
1856Side channel has 6
1857Consuming 7
1858Side channel has 8
1859Side channel has 9
1860Consuming 10
1861Done consuming
1862```
1863
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001864<!--- TEST -->
1865
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001866### Selecting deferred values
1867
Roman Elizarova84730b2017-02-22 11:58:50 +03001868Deferred values can be selected using [onAwait][SelectBuilder.onAwait] clause.
1869Let us start with an async function that returns a deferred string value after
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001870a random delay:
1871
1872<!--- INCLUDE .*/example-select-04.kt
1873import java.util.*
1874-->
1875
1876```kotlin
1877fun asyncString(time: Int) = async(CommonPool) {
1878 delay(time.toLong())
1879 "Waited for $time ms"
1880}
1881```
1882
Roman Elizarova84730b2017-02-22 11:58:50 +03001883Let us start a dozen of them with a random delay.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001884
1885```kotlin
1886fun asyncStringsList(): List<Deferred<String>> {
1887 val random = Random(3)
Roman Elizarova84730b2017-02-22 11:58:50 +03001888 return List(12) { asyncString(random.nextInt(1000)) }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001889}
1890```
1891
Roman Elizarova84730b2017-02-22 11:58:50 +03001892Now 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 +03001893that 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 +03001894so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
1895of deferred values to provide `onAwait` clause for each deferred value.
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001896
1897```kotlin
1898fun main(args: Array<String>) = runBlocking<Unit> {
1899 val list = asyncStringsList()
1900 val result = select<String> {
1901 list.withIndex().forEach { (index, deferred) ->
1902 deferred.onAwait { answer ->
1903 "Deferred $index produced answer '$answer'"
1904 }
1905 }
1906 }
1907 println(result)
Roman Elizarov7c864d82017-02-27 10:17:50 +03001908 val countActive = list.count { it.isActive }
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001909 println("$countActive coroutines are still active")
1910}
1911```
1912
1913> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-04.kt)
1914
1915The output is:
1916
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001917```text
Roman Elizarova84730b2017-02-22 11:58:50 +03001918Deferred 4 produced answer 'Waited for 128 ms'
Roman Elizarovd4dcbe22017-02-22 09:57:46 +0300191911 coroutines are still active
1920```
1921
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001922<!--- TEST -->
1923
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001924### Switch over a channel of deferred values
1925
Roman Elizarova84730b2017-02-22 11:58:50 +03001926Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
1927deferred 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 +03001928[onReceiveOrNull][SelectBuilder.onReceiveOrNull] and [onAwait][SelectBuilder.onAwait] clauses in the same `select`:
1929
1930```kotlin
1931fun switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) = produce<String>(CommonPool) {
Roman Elizarova84730b2017-02-22 11:58:50 +03001932 var current = input.receive() // start with first received deferred value
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001933 while (isActive) { // loop while not cancelled/closed
1934 val next = select<Deferred<String>?> { // return next deferred value from this select or null
1935 input.onReceiveOrNull { update ->
1936 update // replaces next value to wait
1937 }
1938 current.onAwait { value ->
1939 send(value) // send value that current deferred has produced
1940 input.receiveOrNull() // and use the next deferred from the input channel
1941 }
1942 }
1943 if (next == null) {
1944 println("Channel was closed")
1945 break // out of loop
1946 } else {
1947 current = next
1948 }
1949 }
1950}
1951```
1952
1953To test it, we'll use a simple async function that resolves to a specified string after a specified time:
1954
1955```kotlin
1956fun asyncString(str: String, time: Long) = async(CommonPool) {
1957 delay(time)
1958 str
1959}
1960```
1961
1962The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
1963data to it:
1964
1965```kotlin
1966fun main(args: Array<String>) = runBlocking<Unit> {
1967 val chan = Channel<Deferred<String>>() // the channel for test
Roman Elizarova84730b2017-02-22 11:58:50 +03001968 launch(context) { // launch printing coroutine
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001969 for (s in switchMapDeferreds(chan))
1970 println(s) // print each received string
1971 }
1972 chan.send(asyncString("BEGIN", 100))
1973 delay(200) // enough time for "BEGIN" to be produced
1974 chan.send(asyncString("Slow", 500))
Roman Elizarova84730b2017-02-22 11:58:50 +03001975 delay(100) // not enough time to produce slow
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001976 chan.send(asyncString("Replace", 100))
Roman Elizarova84730b2017-02-22 11:58:50 +03001977 delay(500) // give it time before the last one
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001978 chan.send(asyncString("END", 500))
1979 delay(1000) // give it time to process
Roman Elizarova84730b2017-02-22 11:58:50 +03001980 chan.close() // close the channel ...
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001981 delay(500) // and wait some time to let it finish
1982}
1983```
1984
1985> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-select-05.kt)
1986
1987The result of this code:
1988
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001989```text
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001990BEGIN
1991Replace
1992END
1993Channel was closed
1994```
1995
Roman Elizarov731f0ad2017-02-22 20:48:45 +03001996<!--- TEST -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03001997
Roman Elizarove0c817d2017-02-10 10:22:01 +03001998<!--- SITE_ROOT https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core -->
1999<!--- DOCS_ROOT kotlinx-coroutines-core/target/dokka/kotlinx-coroutines-core -->
2000<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002001[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
2002[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
2003[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
2004[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
2005[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception.html
2006[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
2007[CoroutineScope.isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/is-active.html
2008[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
2009[run]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
2010[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
2011[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
2012[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
2013[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
2014[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/await.html
2015[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/start.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002016[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
2017[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002018[CoroutineScope.context]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/context.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002019[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002020[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002021[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
2022[Job.invoke]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/invoke.html
2023[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/cancel.html
Roman Elizarovf5bc0472017-02-22 11:38:13 +03002024<!--- INDEX kotlinx.coroutines.experimental.sync -->
2025[Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/-mutex/index.html
2026[Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/lock.html
2027[Mutex.unlock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.sync/unlock.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03002028<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarov419a6c82017-02-09 18:36:22 +03002029[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002030[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/send.html
2031[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/receive.html
2032[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/close.html
Roman Elizarova5e653f2017-02-13 13:49:55 +03002033[produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/produce.html
Roman Elizarovd4dcbe22017-02-22 09:57:46 +03002034[Channel.invoke]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/invoke.html
2035<!--- INDEX kotlinx.coroutines.experimental.selects -->
2036[select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
2037[SelectBuilder.onReceive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/on-receive.html
2038[SelectBuilder.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/on-receive-or-null.html
2039[SelectBuilder.onSend]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/on-send.html
2040[SelectBuilder.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/on-await.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03002041<!--- END -->