blob: d2c700c5fd34384dee94d525d8a6a9854060088c [file] [log] [blame] [view]
Roman Elizarovf16fd272017-02-07 11:26:00 +03001<!---
2
3Copyright 2016-2017 JetBrains s.r.o.
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17-->
18
Roman Elizarov7deefb82017-01-31 10:33:17 +030019# Guide to kotlinx.coroutines by example
20
21This is a short guide on core features of `kotlinx.coroutines` with a series of examples.
22
Roman Elizarov1293ccd2017-02-01 18:49:54 +030023## Table of contents
24
Roman Elizarovfa7723e2017-02-06 11:17:51 +030025<!--- TOC -->
26
Roman Elizarov1293ccd2017-02-01 18:49:54 +030027* [Coroutine basics](#coroutine-basics)
28 * [Your first coroutine](#your-first-coroutine)
29 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
30 * [Waiting for a job](#waiting-for-a-job)
31 * [Extract function refactoring](#extract-function-refactoring)
32 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
33 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
34* [Cancellation and timeouts](#cancellation-and-timeouts)
35 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
36 * [Cancellation is cooperative](#cancellation-is-cooperative)
37 * [Making computation code cancellable](#making-computation-code-cancellable)
38 * [Closing resources with finally](#closing-resources-with-finally)
39 * [Run non-cancellable block](#run-non-cancellable-block)
40 * [Timeout](#timeout)
41* [Composing suspending functions](#composing-suspending-functions)
42 * [Sequential by default](#sequential-by-default)
Roman Elizarov32d95322017-02-09 15:57:31 +030043 * [Concurrent using async](#concurrent-using-async)
44 * [Lazily started async](#lazily-started-async)
45 * [Async-style functions](#async-style-functions)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030046* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030047 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030048 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
49 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
50 * [Jumping between threads](#jumping-between-threads)
51 * [Job in the context](#job-in-the-context)
52 * [Children of a coroutine](#children-of-a-coroutine)
53 * [Combining contexts](#combining-contexts)
54 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarov2fd7cb32017-02-11 23:18:59 +030055 * [Cancellation via explicit job](#cancellation-via-explicit-job)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030056* [Channels](#channels)
57 * [Channel basics](#channel-basics)
58 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
59 * [Building channel producers](#building-channel-producers)
60 * [Pipelines](#pipelines)
61 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
62 * [Fan-out](#fan-out)
63 * [Fan-in](#fan-in)
64 * [Buffered channels](#buffered-channels)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030065
Roman Elizarovb3d55a52017-02-03 12:47:21 +030066<!--- KNIT kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +030067
Roman Elizarovfa7723e2017-02-06 11:17:51 +030068<!--- INCLUDE .*/example-([a-z]+)-([0-9]+)\.kt
Roman Elizarovf16fd272017-02-07 11:26:00 +030069/*
70 * Copyright 2016-2017 JetBrains s.r.o.
71 *
72 * Licensed under the Apache License, Version 2.0 (the "License");
73 * you may not use this file except in compliance with the License.
74 * You may obtain a copy of the License at
75 *
76 * http://www.apache.org/licenses/LICENSE-2.0
77 *
78 * Unless required by applicable law or agreed to in writing, software
79 * distributed under the License is distributed on an "AS IS" BASIS,
80 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
81 * See the License for the specific language governing permissions and
82 * limitations under the License.
83 */
84
Roman Elizarovb3d55a52017-02-03 12:47:21 +030085// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarovfa7723e2017-02-06 11:17:51 +030086package guide.$$1.example$$2
Roman Elizarovb3d55a52017-02-03 12:47:21 +030087
88import kotlinx.coroutines.experimental.*
89-->
90
Roman Elizarov1293ccd2017-02-01 18:49:54 +030091## Coroutine basics
92
93This section covers basic coroutine concepts.
94
95### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +030096
97Run the following code:
98
99```kotlin
100fun main(args: Array<String>) {
101 launch(CommonPool) { // create new coroutine in common thread pool
102 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
103 println("World!") // print after delay
104 }
105 println("Hello,") // main function continues while coroutine is delayed
106 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
107}
108```
109
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300110> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300111
112Run this code:
113
114```
115Hello,
116World!
117```
118
Roman Elizarov419a6c82017-02-09 18:36:22 +0300119Essentially, coroutines are light-weight threads.
120They are launched with [launch] _coroutine builder_.
121You can achieve the same result replacing
Roman Elizarov7deefb82017-01-31 10:33:17 +0300122`launch(CommonPool) { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
123
124If you start by replacing `launch(CommonPool)` by `thread`, the compiler produces the following error:
125
126```
127Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
128```
129
Roman Elizarov419a6c82017-02-09 18:36:22 +0300130That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
Roman Elizarov7deefb82017-01-31 10:33:17 +0300131coroutine and it can be only used from a coroutine.
132
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300133### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +0300134
135The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same
136code of `main` function. It is easy to get lost. Let's cleanly separate blocking and non-blocking
Roman Elizarov419a6c82017-02-09 18:36:22 +0300137worlds by using [runBlocking]:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300138
139```kotlin
140fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
141 launch(CommonPool) { // create new coroutine in common thread pool
142 delay(1000L)
143 println("World!")
144 }
145 println("Hello,") // main coroutine continues while child is delayed
146 delay(2000L) // non-blocking delay for 2 seconds to keep JVM alive
147}
148```
149
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300150> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300151
Roman Elizarov419a6c82017-02-09 18:36:22 +0300152The result is the same, but this code uses only non-blocking [delay].
Roman Elizarov7deefb82017-01-31 10:33:17 +0300153
154`runBlocking { ... }` works as an adaptor that is used here to start the top-level main coroutine.
155The regular code outside of `runBlocking` _blocks_, until the coroutine inside `runBlocking` is active.
156
157This is also a way to write unit-tests for suspending functions:
158
159```kotlin
160class MyTest {
161 @Test
162 fun testMySuspendingFunction() = runBlocking<Unit> {
163 // here we can use suspending functions using any assertion style that we like
164 }
165}
166```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300167
168<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300169
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300170### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300171
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300172Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
Roman Elizarov419a6c82017-02-09 18:36:22 +0300173wait (in a non-blocking way) until the background [Job] that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300174
175```kotlin
176fun main(args: Array<String>) = runBlocking<Unit> {
177 val job = launch(CommonPool) { // create new coroutine and keep a reference to its Job
178 delay(1000L)
179 println("World!")
180 }
181 println("Hello,")
182 job.join() // wait until child coroutine completes
183}
184```
185
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300186> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300187
188Now 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 +0300189the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300190
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300191### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300192
193Let's extract the block of code inside `launch(CommonPool} { ... }` into a separate function. When you
194perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
195That is your first _suspending function_. Suspending functions can be used inside coroutines
196just like regular functions, but their additional feature is that they can, in turn,
197use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
198
199```kotlin
200fun main(args: Array<String>) = runBlocking<Unit> {
201 val job = launch(CommonPool) { doWorld() }
202 println("Hello,")
203 job.join()
204}
205
206// this is your first suspending function
207suspend fun doWorld() {
208 delay(1000L)
209 println("World!")
210}
211```
212
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300213> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300214
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300215### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300216
217Run the following code:
218
219```kotlin
220fun main(args: Array<String>) = runBlocking<Unit> {
221 val jobs = List(100_000) { // create a lot of coroutines and list their jobs
222 launch(CommonPool) {
223 delay(1000L)
224 print(".")
225 }
226 }
227 jobs.forEach { it.join() } // wait for all jobs to complete
228}
229```
230
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300231> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300232
233It starts 100K coroutines and, after a second, each coroutine prints a dot.
234Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
235
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300236### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300237
238The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300239returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300240
241```kotlin
242fun main(args: Array<String>) = runBlocking<Unit> {
243 launch(CommonPool) {
244 repeat(1000) { i ->
245 println("I'm sleeping $i ...")
246 delay(500L)
247 }
248 }
249 delay(1300L) // just quit after delay
250}
251```
252
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300253> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300254
255You can run and see that it prints three lines and terminates:
256
257```
258I'm sleeping 0 ...
259I'm sleeping 1 ...
260I'm sleeping 2 ...
261```
262
263Active coroutines do not keep the process alive. They are like daemon threads.
264
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300265## Cancellation and timeouts
266
267This section covers coroutine cancellation and timeouts.
268
269### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300270
271In small application the return from "main" method might sound like a good idea to get all coroutines
272implicitly terminated. In a larger, long-running application, you need finer-grained control.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300273The [launch] function returns a [Job] that can be used to cancel running coroutine:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300274
275```kotlin
276fun main(args: Array<String>) = runBlocking<Unit> {
277 val job = launch(CommonPool) {
278 repeat(1000) { i ->
279 println("I'm sleeping $i ...")
280 delay(500L)
281 }
282 }
283 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300284 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300285 job.cancel() // cancels the job
286 delay(1300L) // delay a bit to ensure it was cancelled indeed
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300287 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300288}
289```
290
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300291> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300292
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300293It produces the following output:
294
295```
296I'm sleeping 0 ...
297I'm sleeping 1 ...
298I'm sleeping 2 ...
299main: I'm tired of waiting!
300main: Now I can quit.
301```
302
303As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
304
305### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300306
Tair Rzayevaf734622017-02-01 22:30:16 +0200307Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300308All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
Roman Elizarov419a6c82017-02-09 18:36:22 +0300309coroutine and throw [CancellationException] when cancelled. However, if a coroutine is working in
Roman Elizarov7deefb82017-01-31 10:33:17 +0300310a computation and does not check for cancellation, then it cannot be cancelled, like the following
311example shows:
312
313```kotlin
314fun main(args: Array<String>) = runBlocking<Unit> {
315 val job = launch(CommonPool) {
316 var nextPrintTime = 0L
317 var i = 0
318 while (true) { // computation loop
319 val currentTime = System.currentTimeMillis()
320 if (currentTime >= nextPrintTime) {
321 println("I'm sleeping ${i++} ...")
322 nextPrintTime = currentTime + 500L
323 }
324 }
325 }
326 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300327 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300328 job.cancel() // cancels the job
329 delay(1300L) // delay a bit to see if it was cancelled....
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300330 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300331}
332```
333
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300334> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300335
336Run it to see that it continues to print "I'm sleeping" even after cancellation.
337
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300338### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300339
340There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov419a6c82017-02-09 18:36:22 +0300341invoke a suspending function. There is a [yield] function that is a good choice for that purpose.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300342The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300343
344Replace `while (true)` in the previous example with `while (isActive)` and rerun it.
345
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300346```kotlin
347fun main(args: Array<String>) = runBlocking<Unit> {
348 val job = launch(CommonPool) {
349 var nextPrintTime = 0L
350 var i = 0
351 while (isActive) { // cancellable computation loop
352 val currentTime = System.currentTimeMillis()
353 if (currentTime >= nextPrintTime) {
354 println("I'm sleeping ${i++} ...")
355 nextPrintTime = currentTime + 500L
356 }
357 }
358 }
359 delay(1300L) // delay a bit
360 println("main: I'm tired of waiting!")
361 job.cancel() // cancels the job
362 delay(1300L) // delay a bit to see if it was cancelled....
363 println("main: Now I can quit.")
364}
365```
366
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300367> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300368
Roman Elizarov419a6c82017-02-09 18:36:22 +0300369As you can see, now this loop can be cancelled. [isActive][CoroutineScope.isActive] is a property that is available inside
370the code of coroutines via [CoroutineScope] object.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300371
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300372### Closing resources with finally
373
Roman Elizarov419a6c82017-02-09 18:36:22 +0300374Cancellable suspending functions throw [CancellationException] on cancellation which can be handled in
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300375all the usual way. For example, the `try {...} finally {...}` and Kotlin `use` function execute their
376finalization actions normally when coroutine is cancelled:
377
378```kotlin
379fun main(args: Array<String>) = runBlocking<Unit> {
380 val job = launch(CommonPool) {
381 try {
382 repeat(1000) { i ->
383 println("I'm sleeping $i ...")
384 delay(500L)
385 }
386 } finally {
387 println("I'm running finally")
388 }
389 }
390 delay(1300L) // delay a bit
391 println("main: I'm tired of waiting!")
392 job.cancel() // cancels the job
393 delay(1300L) // delay a bit to ensure it was cancelled indeed
394 println("main: Now I can quit.")
395}
396```
397
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300398> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300399
400The example above produces the following output:
401
402```
403I'm sleeping 0 ...
404I'm sleeping 1 ...
405I'm sleeping 2 ...
406main: I'm tired of waiting!
407I'm running finally
408main: Now I can quit.
409```
410
411### Run non-cancellable block
412
413Any attempt to use a suspending function in the `finally` block of the previous example will cause
Roman Elizarov419a6c82017-02-09 18:36:22 +0300414[CancellationException], because the coroutine running this code is cancelled. Usually, this is not a
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300415problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
416communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
417rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
Roman Elizarov419a6c82017-02-09 18:36:22 +0300418`run(NonCancellable) {...}` using [run] function and [NonCancellable] context as the following example shows:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300419
420```kotlin
421fun main(args: Array<String>) = runBlocking<Unit> {
422 val job = launch(CommonPool) {
423 try {
424 repeat(1000) { i ->
425 println("I'm sleeping $i ...")
426 delay(500L)
427 }
428 } finally {
429 run(NonCancellable) {
430 println("I'm running finally")
431 delay(1000L)
432 println("And I've just delayed for 1 sec because I'm non-cancellable")
433 }
434 }
435 }
436 delay(1300L) // delay a bit
437 println("main: I'm tired of waiting!")
438 job.cancel() // cancels the job
439 delay(1300L) // delay a bit to ensure it was cancelled indeed
440 println("main: Now I can quit.")
441}
442```
443
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300444> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300445
446### Timeout
447
448The most obvious reason to cancel coroutine execution in practice,
449is because its execution time has exceeded some timeout.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300450While you can manually track the reference to the corresponding [Job] and launch a separate coroutine to cancel
451the tracked one after delay, there is a ready to use [withTimeout] function that does it.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300452Look at the following example:
453
454```kotlin
455fun main(args: Array<String>) = runBlocking<Unit> {
456 withTimeout(1300L) {
457 repeat(1000) { i ->
458 println("I'm sleeping $i ...")
459 delay(500L)
460 }
461 }
462}
463```
464
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300465> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300466
467It produces the following output:
468
469```
470I'm sleeping 0 ...
471I'm sleeping 1 ...
472I'm sleeping 2 ...
473Exception in thread "main" java.util.concurrent.CancellationException: Timed out waiting for 1300 MILLISECONDS
474```
475
Roman Elizarov419a6c82017-02-09 18:36:22 +0300476We have not seen the [CancellationException] stack trace printed on the console before. That is because
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300477inside a cancelled coroutine `CancellationException` is a considered a normal reason for coroutine completion.
478However, in this example we have used `withTimeout` right inside the `main` function.
479
480Because cancellation is just an exception, all the resources will be closed in a usual way.
481You can wrap the code with timeout in `try {...} catch (e: CancellationException) {...}` block if
482you need to do some additional action specifically on timeout.
483
484## Composing suspending functions
485
486This section covers various approaches to composition of suspending functions.
487
488### Sequential by default
489
490Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300491remote service call or computation. We just pretend they are useful, but actually each one just
492delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300493
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300494<!--- INCLUDE .*/example-compose-([0-9]+).kt
495import kotlin.system.measureTimeMillis
496-->
497
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300498```kotlin
499suspend fun doSomethingUsefulOne(): Int {
500 delay(1000L) // pretend we are doing something useful here
501 return 13
502}
503
504suspend fun doSomethingUsefulTwo(): Int {
505 delay(1000L) // pretend we are doing something useful here, too
506 return 29
507}
508```
509
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300510<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
511
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300512What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
513`doSomethingUsefulTwo` and compute the sum of their results?
514In practise we do this if we use the results of the first function to make a decision on whether we need
515to invoke the second one or to decide on how to invoke it.
516
517We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
Roman Elizarov32d95322017-02-09 15:57:31 +0300518code, is _sequential_ by default. The following example demonstrates it by measuring the total
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300519time it takes to execute both suspending functions:
520
521```kotlin
522fun main(args: Array<String>) = runBlocking<Unit> {
523 val time = measureTimeMillis {
524 val one = doSomethingUsefulOne()
525 val two = doSomethingUsefulTwo()
526 println("The answer is ${one + two}")
527 }
528 println("Completed in $time ms")
529}
530```
531
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300532> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300533
534It produces something like this:
535
536```
537The answer is 42
538Completed in 2017 ms
539```
540
Roman Elizarov32d95322017-02-09 15:57:31 +0300541### Concurrent using async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300542
543What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
Roman Elizarov419a6c82017-02-09 18:36:22 +0300544we want to get the answer faster, by doing both _concurrently_? This is where [async] comes to help.
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300545
Roman Elizarov419a6c82017-02-09 18:36:22 +0300546Conceptually, [async] is just like [launch]. It starts a separate coroutine which is a light-weight thread
547that works concurrently with all the other coroutines. The difference is that `launch` returns a [Job] and
548does not carry any resulting value, while `async` returns a [Deferred] -- a light-weight non-blocking future
Roman Elizarov32d95322017-02-09 15:57:31 +0300549that 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 +0300550but `Deferred` is also a `Job`, so you can cancel it if needed.
551
552```kotlin
553fun main(args: Array<String>) = runBlocking<Unit> {
554 val time = measureTimeMillis {
Roman Elizarov32d95322017-02-09 15:57:31 +0300555 val one = async(CommonPool) { doSomethingUsefulOne() }
556 val two = async(CommonPool) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300557 println("The answer is ${one.await() + two.await()}")
558 }
559 println("Completed in $time ms")
560}
561```
562
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300563> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300564
565It produces something like this:
566
567```
568The answer is 42
569Completed in 1017 ms
570```
571
572This is twice as fast, because we have concurrent execution of two coroutines.
573Note, that concurrency with coroutines is always explicit.
574
Roman Elizarov32d95322017-02-09 15:57:31 +0300575### Lazily started async
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300576
Roman Elizarov419a6c82017-02-09 18:36:22 +0300577There is a laziness option to [async] with `start = false` parameter.
578It starts coroutine only when its result is needed by some
579[await][Deferred.await] or if a [start][Job.start] function
Roman Elizarov32d95322017-02-09 15:57:31 +0300580is invoked. Run the following example that differs from the previous one only by this option:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300581
582```kotlin
583fun main(args: Array<String>) = runBlocking<Unit> {
584 val time = measureTimeMillis {
Roman Elizarov32d95322017-02-09 15:57:31 +0300585 val one = async(CommonPool, start = false) { doSomethingUsefulOne() }
586 val two = async(CommonPool, start = false) { doSomethingUsefulTwo() }
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300587 println("The answer is ${one.await() + two.await()}")
588 }
589 println("Completed in $time ms")
590}
591```
592
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300593> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300594
595It produces something like this:
596
597```
598The answer is 42
599Completed in 2017 ms
600```
601
Roman Elizarov32d95322017-02-09 15:57:31 +0300602So, we are back to sequential execution, because we _first_ start and await for `one`, _and then_ start and await
603for `two`. It is not the intended use-case for laziness. It is designed as a replacement for
604the standard `lazy` function in cases when computation of the value involves suspending functions.
605
606### Async-style functions
607
608We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
Roman Elizarov419a6c82017-02-09 18:36:22 +0300609_asynchronously_ using [async] coroutine builder. It is a good style to name such functions with
Roman Elizarov32d95322017-02-09 15:57:31 +0300610either "async" prefix of "Async" suffix to highlight the fact that they only start asynchronous
611computation and one needs to use the resulting deferred value to get the result.
612
613```kotlin
614// The result type of asyncSomethingUsefulOne is Deferred<Int>
615fun asyncSomethingUsefulOne() = async(CommonPool) {
616 doSomethingUsefulOne()
617}
618
619// The result type of asyncSomethingUsefulTwo is Deferred<Int>
620fun asyncSomethingUsefulTwo() = async(CommonPool) {
621 doSomethingUsefulTwo()
622}
623```
624
625Note, that these `asyncXXX` function are **not** _suspending_ functions. They can be used from anywhere.
626However, their use always implies asynchronous (here meaning _concurrent_) execution of their action
627with the invoking code.
628
629The following example shows their use outside of coroutine:
630
631```kotlin
632// note, that we don't have `runBlocking` to the right of `main` in this example
633fun main(args: Array<String>) {
634 val time = measureTimeMillis {
635 // we can initiate async actions outside of a coroutine
636 val one = asyncSomethingUsefulOne()
637 val two = asyncSomethingUsefulTwo()
638 // but waiting for a result must involve either suspending or blocking.
639 // here we use `runBlocking { ... }` to block the main thread while waiting for the result
640 runBlocking {
641 println("The answer is ${one.await() + two.await()}")
642 }
643 }
644 println("Completed in $time ms")
645}
646```
647
648> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300649
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300650## Coroutine context and dispatchers
651
Roman Elizarov32d95322017-02-09 15:57:31 +0300652We've already seen `launch(CommonPool) {...}`, `async(CommonPool) {...}`, `run(NonCancellable) {...}`, etc.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300653In these code snippets [CommonPool] and [NonCancellable] are _coroutine contexts_.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300654This section covers other available choices.
655
656### Dispatchers and threads
657
Roman Elizarov419a6c82017-02-09 18:36:22 +0300658Coroutine context includes a [_coroutine dispatcher_][CoroutineDispatcher] which determines what thread or threads
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300659the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
660to a specific thread, dispatch it to a thread pool, or let it run unconfined. Try the following example:
661
662```kotlin
663fun main(args: Array<String>) = runBlocking<Unit> {
664 val jobs = arrayListOf<Job>()
665 jobs += launch(Unconfined) { // not confined -- will work with main thread
666 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
667 }
668 jobs += launch(context) { // context of the parent, runBlocking coroutine
669 println(" 'context': I'm working in thread ${Thread.currentThread().name}")
670 }
671 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
672 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
673 }
674 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
675 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
676 }
677 jobs.forEach { it.join() }
678}
679```
680
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300681> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300682
683It produces the following output (maybe in different order):
684
685```
686 'Unconfined': I'm working in thread main
687 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
688 'newSTC': I'm working in thread MyOwnThread
689 'context': I'm working in thread main
690```
691
Roman Elizarov419a6c82017-02-09 18:36:22 +0300692The difference between parent [context][CoroutineScope.context] and [Unconfined] context will be shown later.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300693
694### Unconfined vs confined dispatcher
695
Roman Elizarov419a6c82017-02-09 18:36:22 +0300696The [Unconfined] coroutine dispatcher starts coroutine in the caller thread, but only until the
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300697first suspension point. After suspension it resumes in the thread that is fully determined by the
698suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
699consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
700
Roman Elizarov419a6c82017-02-09 18:36:22 +0300701On the other side, [context][CoroutineScope.context] property that is available inside the block of any coroutine
702via [CoroutineScope] interface, is a reference to a context of this particular coroutine.
703This way, a parent context can be inherited. The default context of [runBlocking], in particular,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300704is confined to be invoker thread, so inheriting it has the effect of confining execution to
705this thread with a predictable FIFO scheduling.
706
707```kotlin
708fun main(args: Array<String>) = runBlocking<Unit> {
709 val jobs = arrayListOf<Job>()
710 jobs += launch(Unconfined) { // not confined -- will work with main thread
711 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
712 delay(1000)
713 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
714 }
715 jobs += launch(context) { // context of the parent, runBlocking coroutine
716 println(" 'context': I'm working in thread ${Thread.currentThread().name}")
717 delay(1000)
718 println(" 'context': After delay in thread ${Thread.currentThread().name}")
719 }
720 jobs.forEach { it.join() }
721}
722```
723
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300724> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-contest-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300725
726Produces the output:
727
728```
729 'Unconfined': I'm working in thread main
730 'context': I'm working in thread main
731 'Unconfined': After delay in thread kotlinx.coroutines.ScheduledExecutor
732 'context': After delay in thread main
733```
734
735So, the coroutine the had inherited `context` of `runBlocking {...}` continues to execute in the `main` thread,
Roman Elizarov419a6c82017-02-09 18:36:22 +0300736while the unconfined one had resumed in the scheduler thread that [delay] function is using.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300737
738### Debugging coroutines and threads
739
Roman Elizarov419a6c82017-02-09 18:36:22 +0300740Coroutines can suspend on one thread and resume on another thread with [Unconfined] dispatcher or
741with a multi-threaded dispatcher like [CommonPool]. Even with a single-threaded dispatcher it might be hard to
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300742figure out what coroutine was doing what, where, and when. The common approach to debugging applications with
743threads is to print the thread name in the log file on each log statement. This feature is universally supported
744by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
745`kotlinx.coroutines` includes debugging facilities to make it easier.
746
747Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
748
749```kotlin
750fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
751
752fun main(args: Array<String>) = runBlocking<Unit> {
Roman Elizarov32d95322017-02-09 15:57:31 +0300753 val a = async(context) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300754 log("I'm computing a piece of the answer")
755 6
756 }
Roman Elizarov32d95322017-02-09 15:57:31 +0300757 val b = async(context) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300758 log("I'm computing another piece of the answer")
759 7
760 }
761 log("The answer is ${a.await() * b.await()}")
762}
763```
764
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300765> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300766
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300767There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300768and two coroutines computing deferred values `a` (#2) and `b` (#3).
769They are all executing in the context of `runBlocking` and are confined to the main thread.
770The output of this code is:
771
772```
773[main @coroutine#2] I'm computing a piece of the answer
774[main @coroutine#3] I'm computing another piece of the answer
775[main @coroutine#1] The answer is 42
776```
777
778The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
779thread, but the identifier of the currently executing coroutine is appended to it. This identifier
780is consecutively assigned to all created coroutines when debugging mode is turned on.
781
Roman Elizarov419a6c82017-02-09 18:36:22 +0300782You can read more about debugging facilities in the documentation for [newCoroutineContext] function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300783
784### Jumping between threads
785
786Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
787
788```kotlin
789fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
790
791fun main(args: Array<String>) {
792 val ctx1 = newSingleThreadContext("Ctx1")
793 val ctx2 = newSingleThreadContext("Ctx2")
794 runBlocking(ctx1) {
795 log("Started in ctx1")
796 run(ctx2) {
797 log("Working in ctx2")
798 }
799 log("Back to ctx1")
800 }
801}
802```
803
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300804> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300805
Roman Elizarov419a6c82017-02-09 18:36:22 +0300806It demonstrates two new techniques. One is using [runBlocking] with an explicitly specified context, and
807the 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 +0300808same coroutine as you can see in the output below:
809
810```
811[Ctx1 @coroutine#1] Started in ctx1
812[Ctx2 @coroutine#1] Working in ctx2
813[Ctx1 @coroutine#1] Back to ctx1
814```
815
816### Job in the context
817
Roman Elizarov419a6c82017-02-09 18:36:22 +0300818The coroutine [Job] is part of its context. The coroutine can retrieve it from its own context
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300819using `context[Job]` expression:
820
821```kotlin
822fun main(args: Array<String>) = runBlocking<Unit> {
823 println("My job is ${context[Job]}")
824}
825```
826
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300827> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300828
829It produces
830
831```
832My job is BlockingCoroutine{isActive=true}
833```
834
Roman Elizarov419a6c82017-02-09 18:36:22 +0300835So, [isActive][CoroutineScope.isActive] in [CoroutineScope] is just a convenient shortcut for `context[Job]!!.isActive`.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300836
837### Children of a coroutine
838
Roman Elizarov419a6c82017-02-09 18:36:22 +0300839When [context][CoroutineScope.context] of a coroutine is used to launch another coroutine,
840the [Job] of the new coroutine becomes
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300841a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
842are recursively cancelled, too.
843
844```kotlin
845fun main(args: Array<String>) = runBlocking<Unit> {
846 // start a coroutine to process some kind of incoming request
847 val request = launch(CommonPool) {
848 // it spawns two other jobs, one with its separate context
849 val job1 = launch(CommonPool) {
850 println("job1: I have my own context and execute independently!")
851 delay(1000)
852 println("job1: I am not affected by cancellation of the request")
853 }
854 // and the other inherits the parent context
855 val job2 = launch(context) {
856 println("job2: I am a child of the request coroutine")
857 delay(1000)
858 println("job2: I will not execute this line if my parent request is cancelled")
859 }
860 // request completes when both its sub-jobs complete:
861 job1.join()
862 job2.join()
863 }
864 delay(500)
865 request.cancel() // cancel processing of the request
866 delay(1000) // delay a second to see what happens
867 println("main: Who has survived request cancellation?")
868}
869```
870
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300871> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300872
873The output of this code is:
874
875```
876job1: I have my own context and execute independently!
877job2: I am a child of the request coroutine
878job1: I am not affected by cancellation of the request
879main: Who has survived request cancellation?
880```
881
882### Combining contexts
883
884Coroutine context can be combined using `+` operator. The context on the right-hand side replaces relevant entries
Roman Elizarov419a6c82017-02-09 18:36:22 +0300885of 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 +0300886its dispatcher replaced:
887
888```kotlin
889fun main(args: Array<String>) = runBlocking<Unit> {
890 // start a coroutine to process some kind of incoming request
891 val request = launch(context) { // use the context of `runBlocking`
892 // spawns CPU-intensive child job in CommonPool !!!
893 val job = launch(context + CommonPool) {
894 println("job: I am a child of the request coroutine, but with a different dispatcher")
895 delay(1000)
896 println("job: I will not execute this line if my parent request is cancelled")
897 }
898 job.join() // request completes when its sub-job completes
899 }
900 delay(500)
901 request.cancel() // cancel processing of the request
902 delay(1000) // delay a second to see what happens
903 println("main: Who has survived request cancellation?")
904}
905```
906
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300907> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300908
909The expected outcome of this code is:
910
911```
912job: I am a child of the request coroutine, but with a different dispatcher
913main: Who has survived request cancellation?
914```
915
916### Naming coroutines for debugging
917
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300918Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300919coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
920or doing some specific background task, it is better to name it explicitly for debugging purposes.
Roman Elizarov419a6c82017-02-09 18:36:22 +0300921[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 +0300922is executing this coroutine when debugging more is turned on.
923
924The following example demonstrates this concept:
925
926```kotlin
927fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
928
929fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
930 log("Started main coroutine")
931 // run two background value computations
Roman Elizarov32d95322017-02-09 15:57:31 +0300932 val v1 = async(CommonPool + CoroutineName("v1coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300933 log("Computing v1")
934 delay(500)
935 252
936 }
Roman Elizarov32d95322017-02-09 15:57:31 +0300937 val v2 = async(CommonPool + CoroutineName("v2coroutine")) {
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300938 log("Computing v2")
939 delay(1000)
940 6
941 }
942 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
943}
944```
945
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300946> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300947
948The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
949
950```
951[main @main#1] Started main coroutine
952[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
953[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
954[main @main#1] The answer for v1 / v2 = 42
955```
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300956
Roman Elizarov2fd7cb32017-02-11 23:18:59 +0300957### Cancellation via explicit job
958
959Let us put our knowledge about contexts, children and jobs together. Assume that our application has
960an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application
961and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch
962and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed
963to avoid memory leaks.
964
965We can manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to
966the lifecycle of our activity. A job instance is created using [Job()][Job.invoke] factory function
967as the following example shows. We need to make sure that all the coroutines are started
968with this job in their context and then a single invocation of [Job.cancel] terminates them all.
969
970```kotlin
971fun main(args: Array<String>) = runBlocking<Unit> {
972 val job = Job() // create a job object to manage our lifecycle
973 // now launch ten coroutines for a demo, each working for a different time
974 val coroutines = List(10) { i ->
975 // they are all children of our job object
976 launch(context + job) { // we use the context of main runBlocking thread, but with our own job object
977 delay(i * 200L) // variable delay 0ms, 200ms, 400ms, ... etc
978 println("Coroutine $i is done")
979 }
980 }
981 println("Launched ${coroutines.size} coroutines")
982 delay(500L) // delay for half a second
983 println("Cancelling job!")
984 job.cancel() // cancel our job.. !!!
985 delay(1000L) // delay for more to see if our coroutines are still working
986}
987```
988
989> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-09.kt)
990
991The output of this example is:
992
993```
994Launched 10 coroutines
995Coroutine 0 is done
996Coroutine 1 is done
997Coroutine 2 is done
998Cancelling job!
999```
1000
1001As you can see, only the first three coroutines had printed a message and the others were cancelled
1002by a single invocation of `job.cancel()`. So all we need to do in our hypothetical Android
1003application is to create a parent job object when activity is created, use it for child coroutines,
1004and cancel it when activity is destroyed.
1005
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001006## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +03001007
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001008Deferred values provide a convenient way to transfer a single value between coroutines.
1009Channels provide a way to transfer a stream of values.
1010
1011<!--- INCLUDE .*/example-channel-([0-9]+).kt
1012import kotlinx.coroutines.experimental.channels.*
1013-->
1014
1015### Channel basics
1016
Roman Elizarov419a6c82017-02-09 18:36:22 +03001017A [Channel] is conceptually very similar to `BlockingQueue`. One key difference is that
1018instead of a blocking `put` operation it has a suspending [send][SendChannel.send], and instead of
1019a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001020
1021```kotlin
1022fun main(args: Array<String>) = runBlocking<Unit> {
1023 val channel = Channel<Int>()
1024 launch(CommonPool) {
1025 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
1026 for (x in 1..5) channel.send(x * x)
1027 }
1028 // here we print five received integers:
1029 repeat(5) { println(channel.receive()) }
1030 println("Done!")
1031}
1032```
1033
1034> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-01.kt)
1035
1036### Closing and iteration over channels
1037
1038Unlike a queue, a channel can be closed to indicate that no more elements are coming.
1039On the receiver side it is convenient to use a regular `for` loop to receive elements
1040from the channel.
1041
Roman Elizarov419a6c82017-02-09 18:36:22 +03001042Conceptually, a [close][SendChannel.close] is like sending a special close token to the channel.
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001043The iteration stops as soon as this close token is received, so there is a guarantee
1044that all previously sent elements before the close are received:
1045
1046```kotlin
1047fun main(args: Array<String>) = runBlocking<Unit> {
1048 val channel = Channel<Int>()
1049 launch(CommonPool) {
1050 for (x in 1..5) channel.send(x * x)
1051 channel.close() // we're done sending
1052 }
1053 // here we print received values using `for` loop (until the channel is closed)
1054 for (y in channel) println(y)
1055 println("Done!")
1056}
1057```
1058
1059> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-02.kt)
1060
1061### Building channel producers
1062
1063The pattern where a coroutine is producing a sequence of elements into a channel is quite common.
1064You could abstract such a producer into a function that takes channel as its parameter, but this goes contrary
1065to common sense that results must be returned from functions. Here is a convenience
Roman Elizarov419a6c82017-02-09 18:36:22 +03001066coroutine builder named [buildChannel] that makes it easy to do it right:
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001067
1068```kotlin
1069fun produceSquares() = buildChannel<Int>(CommonPool) {
1070 for (x in 1..5) send(x * x)
1071}
1072
1073fun main(args: Array<String>) = runBlocking<Unit> {
1074 val squares = produceSquares()
1075 for (y in squares) println(y)
1076 println("Done!")
1077}
1078```
1079
1080> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-03.kt)
1081
1082### Pipelines
1083
1084Pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
1085
1086```kotlin
1087fun produceNumbers() = buildChannel<Int>(CommonPool) {
1088 var x = 1
1089 while (true) send(x++) // infinite stream of integers starting from 1
1090}
1091```
1092
1093And another coroutine or coroutines are receiving that stream, doing some processing, and sending the result.
1094In the below example the numbers are just squared:
1095
1096```kotlin
1097fun square(numbers: ReceiveChannel<Int>) = buildChannel<Int>(CommonPool) {
1098 for (x in numbers) send(x * x)
1099}
1100```
1101
1102The main code starts and connects pipeline:
1103
1104```kotlin
1105fun main(args: Array<String>) = runBlocking<Unit> {
1106 val numbers = produceNumbers() // produces integers from 1 and on
1107 val squares = square(numbers) // squares integers
1108 for (i in 1..5) println(squares.receive()) // print first five
1109 println("Done!") // we are done
1110 squares.cancel() // need to cancel these coroutines in a larger app
1111 numbers.cancel()
1112}
1113```
1114
1115> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-04.kt)
1116
1117We don't have to cancel these coroutines in this example app, because
1118[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
1119but in a larger app we'll need to stop our pipeline if we don't need it anymore.
1120Alternatively, we could have run pipeline coroutines as
1121[children of a coroutine](#children-of-a-coroutine).
1122
1123### Prime numbers with pipeline
1124
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001125Let's take pipelines to the extreme with an example that generates prime numbers using a pipeline
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001126of coroutines. We start with an infinite sequence of numbers. This time we introduce an
1127explicit context parameter, so that caller can control where our coroutines run:
1128
1129<!--- INCLUDE kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
1130import kotlin.coroutines.experimental.CoroutineContext
1131-->
1132
1133```kotlin
1134fun numbersFrom(context: CoroutineContext, start: Int) = buildChannel<Int>(context) {
1135 var x = start
1136 while (true) send(x++) // infinite stream of integers from start
1137}
1138```
1139
1140The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1141that are divisible by the given prime number:
1142
1143```kotlin
1144fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = buildChannel<Int>(context) {
1145 for (x in numbers) if (x % prime != 0) send(x)
1146}
1147```
1148
1149Now 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 +03001150and launching new pipeline stage for each prime number found:
1151
1152```
1153numbers -> filter(2) -> filter(3) -> filter(5) -> filter(7) ...
1154```
1155
1156The following example prints the first ten prime numbers,
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001157running the whole pipeline in the context of the main thread:
1158
1159```kotlin
1160fun main(args: Array<String>) = runBlocking<Unit> {
1161 var cur = numbersFrom(context, 2)
1162 for (i in 1..10) {
1163 val prime = cur.receive()
1164 println(prime)
1165 cur = filter(context, cur, prime)
1166 }
1167}
1168```
1169
1170> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt)
1171
1172The output of this code is:
1173
1174```
11752
11763
11775
11787
117911
118013
118117
118219
118323
118429
1185```
1186
Roman Elizarov62500ba2017-02-09 18:55:40 +03001187Note, that you can build the same pipeline using `buildIterator` from the standard library.
1188Replace `buildSequence` with `buildIterator`, `send` with `yield`, `receive` with `next`,
1189`ReceiveChannel` with `Iterator`, and get rid of the context. You will not need `runBlocking` either.
1190However, the benefit of a pipeline that uses channels as shown above is that it can actually use
1191multiple CPU cores if you run it in [CommonPool] context.
1192
1193Anyway, this is an extremely impractical way to find prime numbers. In practise, pipelines do involve some
1194other suspending invocations (like asynchronous calls to remote services) and these pipelines cannot be
1195built using `buildSeqeunce`/`buildIterator`, because they do not allow arbitrary suspension, unlike
1196`buildChannel` which is fully asynchronous.
1197
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001198### Fan-out
1199
1200Multiple coroutines may receive from the same channel, distributing work between themselves.
1201Let us start with a producer coroutine that is periodically producing integers
1202(ten numbers per second):
1203
1204```kotlin
1205fun produceNumbers() = buildChannel<Int>(CommonPool) {
1206 var x = 1 // start from 1
1207 while (true) {
1208 send(x++) // produce next
1209 delay(100) // wait 0.1s
1210 }
1211}
1212```
1213
1214Then we can have several processor coroutines. In this example, they just print their id and
1215received number:
1216
1217```kotlin
1218fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch(CommonPool) {
1219 while (true) {
1220 val x = channel.receive()
1221 println("Processor #$id received $x")
1222 }
1223}
1224```
1225
1226Now let us launch five processors and let them work for a second. See what happens:
1227
1228```kotlin
1229fun main(args: Array<String>) = runBlocking<Unit> {
1230 val producer = produceNumbers()
1231 repeat(5) { launchProcessor(it, producer) }
1232 delay(1000)
1233 producer.cancel() // cancel producer coroutine and thus kill them all
1234}
1235```
1236
1237> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-06.kt)
1238
1239The output will be similar to the the following one, albeit the processor ids that receive
1240each specific integer may be different:
1241
1242```
1243Processor #2 received 1
1244Processor #4 received 2
1245Processor #0 received 3
1246Processor #1 received 4
1247Processor #3 received 5
1248Processor #2 received 6
1249Processor #4 received 7
1250Processor #0 received 8
1251Processor #1 received 9
1252Processor #3 received 10
1253```
1254
1255Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1256over the channel that processor coroutines are doing.
1257
1258### Fan-in
1259
1260Multiple coroutines may send to the same channel.
1261For example, let us have a channel of strings, and a suspending function that
1262repeatedly sends a specified string to this channel with a specified delay:
1263
1264```kotlin
1265suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1266 while (true) {
1267 delay(time)
1268 channel.send(s)
1269 }
1270}
1271```
1272
Cedric Beustfa0b28f2017-02-07 07:07:25 -08001273Now, let us see what happens if we launch a couple of coroutines sending strings
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001274(in this example we launch them in the context of the main thread):
1275
1276```kotlin
1277fun main(args: Array<String>) = runBlocking<Unit> {
1278 val channel = Channel<String>()
1279 launch(context) { sendString(channel, "foo", 200L) }
1280 launch(context) { sendString(channel, "BAR!", 500L) }
1281 repeat(6) { // receive first six
1282 println(channel.receive())
1283 }
1284}
1285```
1286
1287> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt)
1288
1289The output is:
1290
1291```
1292foo
1293foo
1294BAR!
1295foo
1296foo
1297BAR!
1298```
1299
1300### Buffered channels
1301
1302The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1303meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1304if receive is invoked first, it is suspended until send is invoked.
Roman Elizarov419a6c82017-02-09 18:36:22 +03001305
1306Both [Channel()][Channel.invoke] factory function and [buildChannel] builder take an optional `capacity` parameter to
Roman Elizarovb7721cf2017-02-03 19:23:08 +03001307specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1308similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1309
1310Take a look at the behavior of the following code:
1311
1312```kotlin
1313fun main(args: Array<String>) = runBlocking<Unit> {
1314 val channel = Channel<Int>(4) // create buffered channel
1315 launch(context) { // launch sender coroutine
1316 repeat(10) {
1317 println("Sending $it") // print before sending each element
1318 channel.send(it) // will suspend when buffer is full
1319 }
1320 }
1321 // don't receive anything... just wait....
1322 delay(1000)
1323}
1324```
1325
1326> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt)
1327
1328It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1329
1330```
1331Sending 0
1332Sending 1
1333Sending 2
1334Sending 3
1335Sending 4
1336```
1337
1338The 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 +03001339
Roman Elizarove0c817d2017-02-10 10:22:01 +03001340<!--- SITE_ROOT https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core -->
1341<!--- DOCS_ROOT kotlinx-coroutines-core/target/dokka/kotlinx-coroutines-core -->
1342<!--- INDEX kotlinx.coroutines.experimental -->
Roman Elizarov419a6c82017-02-09 18:36:22 +03001343[CommonPool]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-common-pool/index.html
1344[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
1345[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-name/index.html
1346[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03001347[CoroutineScope.context]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/context.html
1348[CoroutineScope.isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/is-active.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03001349[Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03001350[Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/await.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03001351[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/index.html
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001352[Job.cancel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/cancel.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03001353[Job.start]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/start.html
Roman Elizarov2fd7cb32017-02-11 23:18:59 +03001354[Job.invoke]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-job/invoke.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03001355[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
1356[Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-unconfined/index.html
1357[CancellationException]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-cancellation-exception.html
1358[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html
1359[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
1360[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/launch.html
1361[newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
1362[run]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run.html
1363[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
1364[withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
1365[yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03001366<!--- INDEX kotlinx.coroutines.experimental.channels -->
Roman Elizarov419a6c82017-02-09 18:36:22 +03001367[Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
Roman Elizarove0c817d2017-02-10 10:22:01 +03001368[Channel.invoke]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/invoke.html
1369[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-receive-channel/receive.html
1370[SendChannel.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/close.html
1371[SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
Roman Elizarov419a6c82017-02-09 18:36:22 +03001372[buildChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/build-channel.html
1373<!--- END -->