Skip to content

Version 1.5.0-RC #2675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 56 commits into from
Apr 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
defd0ec
Fix a test that was flaky because of BlockHound (#2572)
dkhalanskyjb Mar 9, 2021
a8d55d6
Replace deprecated '*compile' configurations. (#2574)
Tapchicoma Mar 9, 2021
187f0aa
Properly reference coroutines-guide-ui.md when opening page from a we…
qwwdfsad Mar 15, 2021
25a33d4
Fix docs for filter. (#2555)
johnjohndoe Mar 16, 2021
cbf3f24
Fix typo in flow/Builders.kt (#2589)
chao2zhang Mar 17, 2021
e15970b
Fix Job.children docs (#2592)
elizarov Mar 18, 2021
81e51a3
Mention default buffering in flattenMerge documentation (#2583)
qwwdfsad Mar 18, 2021
6f13927
Do not initialize CoroutineExceptionHandler in Job <clinit> (#2513)
qwwdfsad Mar 22, 2021
f2940d5
Update Gradle for Kotlin 1.5, add space-dev repository (#2598)
qwwdfsad Mar 22, 2021
05f7d5d
Simplify internal coroutines machinery (#2512)
qwwdfsad Mar 23, 2021
7c6c72f
Allow extra suspension in Lincheck tests for `Semaphore.acquire()` (#…
ndkoval Mar 23, 2021
5f9e52c
Update SharedFlow documentation (#2437)
qwwdfsad Mar 24, 2021
e608dfb
Rework reusability control in cancellable continuation (#2581)
qwwdfsad Mar 24, 2021
ed8e8d1
Introduce ChannelResult and receiveCatching/onReceiveCatching
qwwdfsad Mar 18, 2021
a67fd8e
Introduce trySend and tryReceive channel operations as a future repla…
qwwdfsad Mar 22, 2021
2021b5a
Update contribution guide (#2608)
qwwdfsad Mar 25, 2021
ea039ea
update: delete -Xcoroutines flag since it will be removed in Kotlin 1…
koshachy Apr 6, 2021
7ae273c
Fix wrong docs on Job.join (#2616)
elizarov Apr 6, 2021
98532c9
Deprecation and migration of receiveOrNull and onReceiveOrNull. (#2612)
qwwdfsad Apr 6, 2021
eb963e8
Remove deprecated SendChannel.isFull (#2613)
qwwdfsad Apr 6, 2021
f2f49b0
Complete mono { } on cancellation (#2606)
dkhalanskyjb Apr 7, 2021
86a0658
Make the subscriber in awaitOne less permissive (#2586)
dkhalanskyjb Apr 7, 2021
d23dd3d
Remove internal 'checkCompletion' function and replace it with the id…
qwwdfsad Apr 7, 2021
b61a66c
Display artificial stack frames as calls to functions instead of text…
dkhalanskyjb Apr 7, 2021
4c90fd4
Fix minBy/maxBy usages (#2636)
Apr 8, 2021
43df032
Hide obsolete Channels API in a backwards-compatible manner
qwwdfsad Dec 9, 2020
6a6b34c
Adjust deprecations in reactive integrations
qwwdfsad Dec 9, 2020
80862a5
Fix a flaky test in MonoTest (#2635)
dkhalanskyjb Apr 8, 2021
12f4dbc
Remove debug output from test
qwwdfsad Apr 8, 2021
d905e82
Embrace new channel API, stabilize callbackFlow (#2643)
qwwdfsad Apr 13, 2021
df16bbf
Better NonCancellable docs (#2633)
elizarov Apr 13, 2021
7b1f3b3
Introduce runningFold operator, make scan alias to runningFold (#2645)
qwwdfsad Apr 13, 2021
3c83c0c
Deprecate SendChannel.offer and ReceiveChannel.poll, replace their us…
qwwdfsad Apr 13, 2021
7872f8f
Mark BroadcastChannel, ConflatedBroadcastChannel and all related oper…
qwwdfsad Apr 15, 2021
e62f8f7
Migration to Kotlin 1.5.0-RC (#2653)
qwwdfsad Apr 15, 2021
95ad444
Fix missing indent in @InternalCoroutinesApi warning message
qwwdfsad Apr 19, 2021
8bb5210
Consistently handle exceptions in reactive streams (#2646)
dkhalanskyjb Apr 20, 2021
6a42a77
Mark GlobalScope as delicate API and rewrite coroutine basics doc wit…
elizarov Apr 20, 2021
998f67b
Properly implement replacement for Flow<T>.concatWith(flow) to avoid …
qwwdfsad Apr 20, 2021
c752d64
Shared overflow doc (#2560)
elizarov Apr 20, 2021
cefb84f
Update coroutines-guide.md link (#2661)
koshachy Apr 20, 2021
71df60e
Deprecate awaitSingleOr*, specialize some await* functions for Mono a…
dkhalanskyjb Apr 21, 2021
e49cf79
Mention benign data-race in getResult (#2663)
qwwdfsad Apr 21, 2021
b400b02
Add debugger-related manifest to root metadata artifact of kotlinx-co…
qwwdfsad Apr 21, 2021
5cd57e7
Add ChannelResult.onClosed (#2665)
qwwdfsad Apr 21, 2021
40f79ff
Introduce Flow.last and Flow.lastOrNull operators (#2662)
qwwdfsad Apr 21, 2021
99b4758
Test invariant that IDEA evaluator depends on (#2525)
qwwdfsad Apr 21, 2021
44ebdef
Use cancellation exception from standard library in Kotlin/JS and K/N…
qwwdfsad Apr 21, 2021
347feed
Remove dev repositories and Bintray usages where applicable (#2587)
qwwdfsad Apr 22, 2021
835ee18
Add a way to construct ReactorContext from ContextView (#2622)
dkhalanskyjb Apr 22, 2021
05d3018
Fixes for the reactive integrations (#2617)
dkhalanskyjb Apr 22, 2021
3116b8c
CoroutinesTimeout for JUnit5 (#2402)
dkhalanskyjb Apr 23, 2021
47a063c
Remove the @ExperimentalCoroutinesApi annotation from reactive integr…
dkhalanskyjb Apr 23, 2021
3468479
Merge branch 'master' into develop
qwwdfsad Apr 25, 2021
e61ef4b
Update Kotlin to 1.5.0 (#2674)
qwwdfsad Apr 26, 2021
497312e
Version 1.5.0-RC
qwwdfsad Apr 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
32 changes: 32 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Change log for kotlinx.coroutines

## Version 1.5.0-RC

### Channels API

* Major channels API rework (#330, #974). Existing `offer`, `poll`, and `sendBlocking` methods are deprecated, internal `receiveCatching` and `onReceiveCatching` removed, `receiveOrNull` and `onReceiveOrNull` are completely deprecated. Previously deprecated `SendChannel.isFull` declaration is removed. Channel operators deprecated with `ERROR` are now `HIDDEN`.
* New methods `receiveCatching`, `onReceiveCatching` `trySend`, `tryReceive`, and `trySendBlocking` along with the new result type `ChannelResult` are introduced. They provide better type safety, are less error-prone, and have a consistent future-proof naming scheme. The full rationale behind this change can be found [here](https://github.com/Kotlin/kotlinx.coroutines/issues/974#issuecomment-806569582).
* `BroadcastChannel` and `ConflatedBroadcastChannel` are marked as `ObsoleteCoroutinesApi` in the favor or `SharedFlow` and `StateFlow`. The migration scheme can be found in their documentation. These classes will be deprecated in the next major release.
* `callbackFlow` and `channelFlow` are promoted to stable API.

### Reactive integrations

* All existing API in modules `kotlinx-coroutines-rx2`, `kotlinx-coroutines-rx3`, `kotlinx-coroutines-reactive`, `kotlinx-coroutines-reactor`, and `kotlinx-coroutines-jdk9` were revisited and promoted to stable (#2545).
* `publish` is no longer allowed to emit `null` values (#2646).
* Misleading `awaitSingleOr*` functions on `Publisher` type are deprecated (#2591).
* `MaybeSource.await` is deprecated in the favor of `awaitSingle`, additional lint functions for `Mono` are added in order to prevent ambiguous `Publisher` usages (#2628, #1587).
* `ContextView` support in `kotlinx-coroutines-reactor` (#2575).
* All reactive builders no longer ignore inner cancellation exceptions preventing their completion (#2262, #2646).
* `MaybeSource.collect` and `Maybe.collect` properly finish when they are completed without a value (#2617).
* All exceptions are now consistently handled according to reactive specification, whether they are considered 'fatal' or not by reactive frameworks (#2646).

### Other improvements

* `Flow.last` and `Flow.lastOrNull` operators (#2246).
* `Flow.runningFold` operator (#2641).
* `CoroutinesTimeout` rule for JUnit5 (#2197).
* Internals of `Job` and `AbstractCoroutine` was reworked, resulting in smaller code size, less memory footprint, and better performance (#2513, #2512).
* `CancellationException` from Kotlin standard library is used for cancellation on Koltin/JS and Kotlin/Native (#2638).
* Introduced new `DelicateCoroutineApi` annotation that warns users about potential target API pitfalls and suggests studying API's documentation first. The only delicate API right now is `GlobalScope` (#2637).
* Fixed bug introduced in `1.4.3` when `kotlinx-coroutines-core.jar` triggered IDEA debugger failure (#2619).
* Fixed memory leak of `ChildHandlerNode` with reusable continuations (#2564).
* Various documentation improvements (#2555, #2589, #2592, #2583, #2437, #2616, #2633, #2560).

## Version 1.4.3

### General changes
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ so do familiarize yourself with the following guidelines.
* Follow the style of writing tests that is used in this project:
name test functions as `testXxx`. Don't use backticks in test names.
* If you introduce any new public APIs:
* Comment on the existing issue if you want to work on it or create one beforehand.
Ensure that the issue not only describes a problem, but also describes a solution that had received a positive feedback. Propose a solution if there isn't any.
PRs with new API, but without a corresponding issue with a positive feedback about the proposed implementation are unlikely to
be approved or reviewed.
* All new APIs must come with documentation and tests.
* All new APIs are initially released with `@ExperimentalCoroutineApi` annotation and are graduated later.
* [Update the public API dumps](#updating-the-public-api-dump) and commit the resulting changes as well.
It will not pass the tests otherwise.
* If you plan large API additions, then please start by submitting an issue with the proposed API design
to gather community feedback.
* [Contact the maintainers](#contacting-maintainers) to coordinate any big piece of work in advance.
* Comment on the existing issue if you want to work on it. Ensure that the issue not only describes a problem,
but also describes a solution that had received a positive feedback. Propose a solution if there isn't any.
* Steps for contributing new integration modules are explained [here](integration/README.md#Contributing).

## Building
Expand Down
28 changes: 12 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

[![official JetBrains project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
[![Download](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.4.3)](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.4.3/pom)
[![Kotlin](https://img.shields.io/badge/kotlin-1.4.30-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Download](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.5.0-RC)](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.5.0-RC/pom)
[![Kotlin](https://img.shields.io/badge/kotlin-1.5.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Slack channel](https://img.shields.io/badge/chat-slack-green.svg?logo=slack)](https://kotlinlang.slack.com/messages/coroutines/)

Library support for Kotlin coroutines with [multiplatform](#multiplatform) support.
This is a companion version for the Kotlin `1.4.30` release.
This is a companion version for the Kotlin `1.5.0` release.

```kotlin
suspend fun main() = coroutineScope {
Expand Down Expand Up @@ -75,10 +75,6 @@ suspend fun main() = coroutineScope {

## Using in your projects

The libraries are published to [kotlinx](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines) Bintray repository,
linked to [JCenter](https://bintray.com/bintray/jcenter?filterByPkgName=kotlinx.coroutines) and
pushed to [Maven Central](https://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.jetbrains.kotlinx%20a%3Akotlinx-coroutines*).

### Maven

Add dependencies (you can also add other modules that you need):
Expand All @@ -87,15 +83,15 @@ Add dependencies (you can also add other modules that you need):
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.4.3</version>
<version>1.5.0-RC</version>
</dependency>
```

And make sure that you use the latest Kotlin version:

```xml
<properties>
<kotlin.version>1.4.30</kotlin.version>
<kotlin.version>1.5.0</kotlin.version>
</properties>
```

Expand All @@ -105,15 +101,15 @@ Add dependencies (you can also add other modules that you need):

```groovy
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC'
}
```

And make sure that you use the latest Kotlin version:

```groovy
buildscript {
ext.kotlin_version = '1.4.30'
ext.kotlin_version = '1.5.0'
}
```

Expand All @@ -131,15 +127,15 @@ Add dependencies (you can also add other modules that you need):

```groovy
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC")
}
```

And make sure that you use the latest Kotlin version:

```groovy
plugins {
kotlin("jvm") version "1.4.30"
kotlin("jvm") version "1.5.0"
}
```

Expand All @@ -151,7 +147,7 @@ Add [`kotlinx-coroutines-android`](ui/kotlinx-coroutines-android)
module as a dependency when using `kotlinx.coroutines` on Android:

```groovy
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC'
```

This gives you access to the Android [Dispatchers.Main]
Expand Down Expand Up @@ -184,7 +180,7 @@ In common code that should get compiled for different platforms, you can add a d
```groovy
commonMain {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC")
}
}
```
Expand All @@ -196,7 +192,7 @@ Platform-specific dependencies are recommended to be used only for non-multiplat
#### JS

Kotlin/JS version of `kotlinx.coroutines` is published as
[`kotlinx-coroutines-core-js`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.4.3/jar)
[`kotlinx-coroutines-core-js`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.5.0-RC/jar)
(follow the link to get the dependency declaration snippet) and as [`kotlinx-coroutines-core`](https://www.npmjs.com/package/kotlinx-coroutines-core) NPM package.

#### Native
Expand Down
22 changes: 6 additions & 16 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,11 @@ buildscript {
}

repositories {
maven {url "https://kotlin.bintray.com/kotlinx"}
// Future replacement for kotlin-dev, with cache redirector
maven { url "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
maven {
url "https://kotlin.bintray.com/kotlin-dev"
credentials {
username = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') ?: ""
password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') ?: ""
}
}
// Leftover until we migrated to Dokka 1.4.30
maven { url "https://kotlin.bintray.com/kotlin-dev" }
maven { url "https://jetbrains.bintray.com/kotlin-native-dependencies" }
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
}

dependencies {
Expand Down Expand Up @@ -150,9 +143,6 @@ allprojects {
*/
google()
mavenCentral()
// Future replacement for kotlin-dev, with cache redirector
maven { url "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
maven { url "https://kotlin.bintray.com/kotlinx" }
}
}

Expand All @@ -163,9 +153,9 @@ configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != core
apply plugin: "kotlin-${platform}-conventions"
dependencies {
// See comment below for rationale, it will be replaced with "project" dependency
compile project(":$coreModule")
api project(":$coreModule")
// the only way IDEA can resolve test classes
testCompile project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs
testImplementation project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs
}
}

Expand Down Expand Up @@ -243,7 +233,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) {
if (it.name != 'kotlinx-coroutines-bom') {
apply from: rootProject.file('gradle/dokka.gradle')
}
apply from: rootProject.file('gradle/publish-bintray.gradle')
apply from: rootProject.file('gradle/publish.gradle')
}

configure(subprojects.findAll { !unpublished.contains(it.name) }) {
Expand Down
2 changes: 2 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ repositories {
maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-dev")
} else {
maven("https://plugins.gradle.org/m2")
// Leftover until we migrated to Dokka 1.4.30
maven("https://dl.bintray.com/kotlin/kotlin-dev")
}
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev")

if (buildSnapshotTrain) {
mavenLocal()
Expand Down
14 changes: 0 additions & 14 deletions buildSrc/src/main/kotlin/Publishing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,6 @@ fun configureMavenPublication(rh: RepositoryHandler, project: Project) {
}
}

fun configureBintrayPublication(rh: RepositoryHandler, project: Project) {
rh.maven {
val user = "kotlin"
val repo = "kotlinx"
val name = "kotlinx.coroutines"
url = URI("https://api.bintray.com/maven/$user/$repo/$name/;publish=0;override=0")

credentials {
username = project.findProperty("bintrayUser") as? String ?: System.getenv("BINTRAY_USER")
password = project.findProperty("bintrayApiKey") as? String ?: System.getenv("BINTRAY_API_KEY")
}
}
}

fun signPublicationIfKeyPresent(project: Project, publication: MavenPublication) {
val keyId = project.getSensitiveProperty("libs.sign.key.id")
val signingKey = project.getSensitiveProperty("libs.sign.key.private")
Expand Down
10 changes: 5 additions & 5 deletions buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ if (rootProject.extra.get("jvm_ir_enabled") as Boolean) {
}

dependencies {
testCompile(kotlin("test"))
testImplementation(kotlin("test"))
// Workaround to make addSuppressed work in tests
testCompile(kotlin("reflect"))
testCompile(kotlin("stdlib-jdk7"))
testCompile(kotlin("test-junit"))
testCompile("junit:junit:${version("junit")}")
testImplementation(kotlin("reflect"))
testImplementation(kotlin("stdlib-jdk7"))
testImplementation(kotlin("test-junit"))
testImplementation("junit:junit:${version("junit")}")
}

tasks.compileKotlin {
Expand Down
Binary file modified docs/images/after.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/before.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/new-mvn-project-jvm.png
Binary file not shown.
22 changes: 16 additions & 6 deletions docs/topics/composing-suspending-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ suspend fun doSomethingUsefulTwo(): Int {

What do we do if we need them to be invoked _sequentially_ &mdash; first `doSomethingUsefulOne` _and then_
`doSomethingUsefulTwo`, and compute the sum of their results?
In practice we do this if we use the result of the first function to make a decision on whether we need
In practice, we do this if we use the result of the first function to make a decision on whether we need
to invoke the second one or to decide on how to invoke it.

We use a normal sequential invocation, because the code in the coroutine, just like in the regular
Expand Down Expand Up @@ -190,18 +190,26 @@ standard `lazy` function in cases when computation of the value involves suspend
## Async-style functions

We can define async-style functions that invoke `doSomethingUsefulOne` and `doSomethingUsefulTwo`
_asynchronously_ using the [async] coroutine builder with an explicit [GlobalScope] reference.
_asynchronously_ using the [async] coroutine builder using a [GlobalScope] reference to
opt-out of the structured concurrency.
We name such functions with the
"...Async" suffix to highlight the fact that they only start asynchronous computation and one needs
to use the resulting deferred value to get the result.

> [GlobalScope] is a delicate API that can backfire in non-trivial ways, one of which will be explained
> below, so you must explicitly opt-in into using `GlobalScope` with `@OptIn(DelicateCoroutinesApi::class)`.
>
{type="note"}

```kotlin
// The result type of somethingUsefulOneAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulOneAsync() = GlobalScope.async {
doSomethingUsefulOne()
}

// The result type of somethingUsefulTwoAsync is Deferred<Int>
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulTwoAsync() = GlobalScope.async {
doSomethingUsefulTwo()
}
Expand Down Expand Up @@ -236,10 +244,12 @@ fun main() {
}
//sampleEnd

@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulOneAsync() = GlobalScope.async {
doSomethingUsefulOne()
}

@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulTwoAsync() = GlobalScope.async {
doSomethingUsefulTwo()
}
Expand Down Expand Up @@ -272,9 +282,9 @@ Completed in 1085 ms
{type="note"}

Consider what happens if between the `val one = somethingUsefulOneAsync()` line and `one.await()` expression there is some logic
error in the code and the program throws an exception and the operation that was being performed by the program aborts.
error in the code, and the program throws an exception, and the operation that was being performed by the program aborts.
Normally, a global error-handler could catch this exception, log and report the error for developers, but the program
could otherwise continue doing other operations. But here we have `somethingUsefulOneAsync` still running in the background,
could otherwise continue doing other operations. However, here we have `somethingUsefulOneAsync` still running in the background,
even though the operation that initiated it was aborted. This problem does not happen with structured
concurrency, as shown in the section below.

Expand All @@ -293,7 +303,7 @@ suspend fun concurrentSum(): Int = coroutineScope {
}
```

This way, if something goes wrong inside the code of the `concurrentSum` function and it throws an exception,
This way, if something goes wrong inside the code of the `concurrentSum` function, and it throws an exception,
all the coroutines that were launched in its scope will be cancelled.

<!--- CLEAR -->
Expand Down Expand Up @@ -403,4 +413,4 @@ Computation failed with ArithmeticException
[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
[_coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html

<!--- END -->
<!--- END -->
Loading