Skip to content

Commit d737da6

Browse files
authored
Merge pull request #3304 from Kotlin/version-1.6.2
Version 1.6.2
2 parents c38ecb6 + eb9dd55 commit d737da6

File tree

66 files changed

+481
-541
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+481
-541
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ build
1212
out
1313
target
1414
local.properties
15+
/kotlin-js-store

CHANGES.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Change log for kotlinx.coroutines
22

3+
## Version 1.6.2
4+
5+
* Fixed a bug with `ThreadLocalElement` not being correctly updated when the most outer `suspend` function was called directly without `kotlinx.coroutines` (#2930).
6+
* Fixed multiple data races: one that might have been affecting `runBlocking` event loop, and a benign data race in `Mutex` (#3250, #3251).
7+
* Obsolete `TestCoroutineContext` is removed, which fixes the `kotlinx-coroutines-test` JPMS package being split between `kotlinx-coroutines-core` and `kotlinx-coroutines-test` (#3218).
8+
* Updated the ProGuard rules to further shrink the size of the resulting DEX file with coroutines (#3111, #3263). Thanks, @agrieve!
9+
* Atomicfu is updated to `0.17.2`, which includes a more efficient and robust JS IR transformer (#3255).
10+
* Kotlin is updated to `1.6.21`, Gradle version is updated to `7.4.2` (#3281). Thanks, @wojtek-kalicinski!
11+
* Various documentation improvements.
12+
313
## Version 1.6.1
414

515
* Rollback of time-related functions dispatching on `Dispatchers.Main`.

README.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Kotlin Stable](https://kotl.in/badges/stable.svg)](https://kotlinlang.org/docs/components-stability.html)
44
[![JetBrains official project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
55
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
6-
[![Download](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.6.1)](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.6.1/pom)
6+
[![Download](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.6.2)](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.6.2/pom)
77
[![Kotlin](https://img.shields.io/badge/kotlin-1.6.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
88
[![Slack channel](https://img.shields.io/badge/chat-slack-green.svg?logo=slack)](https://kotlinlang.slack.com/messages/coroutines/)
99

@@ -62,9 +62,9 @@ suspend fun main() = coroutineScope {
6262
## Documentation
6363

6464
* Presentations and videos:
65-
* [Introduction to Coroutines](https://www.youtube.com/watch?v=_hfBv0a09Jc) (Roman Elizarov at KotlinConf 2017, [slides](https://www.slideshare.net/elizarov/introduction-to-coroutines-kotlinconf-2017))
66-
* [Deep dive into Coroutines](https://www.youtube.com/watch?v=YrrUCSi72E8) (Roman Elizarov at KotlinConf 2017, [slides](https://www.slideshare.net/elizarov/deep-dive-into-coroutines-on-jvm-kotlinconf-2017))
6765
* [Kotlin Coroutines in Practice](https://www.youtube.com/watch?v=a3agLJQ6vt8) (Roman Elizarov at KotlinConf 2018, [slides](https://www.slideshare.net/elizarov/kotlin-coroutines-in-practice-kotlinconf-2018))
66+
* [Deep Dive into Coroutines](https://www.youtube.com/watch?v=YrrUCSi72E8) (Roman Elizarov at KotlinConf 2017, [slides](https://www.slideshare.net/elizarov/deep-dive-into-coroutines-on-jvm-kotlinconf-2017))
67+
* [History of Structured Concurrency in Coroutines](https://www.youtube.com/watch?v=Mj5P47F6nJg) (Roman Elizarov at Hydra 2019, [slides](https://speakerdeck.com/elizarov/structured-concurrency))
6868
* Guides and manuals:
6969
* [Guide to kotlinx.coroutines by example](https://kotlinlang.org/docs/coroutines-guide.html) (**read it first**)
7070
* [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md)
@@ -84,15 +84,15 @@ Add dependencies (you can also add other modules that you need):
8484
<dependency>
8585
<groupId>org.jetbrains.kotlinx</groupId>
8686
<artifactId>kotlinx-coroutines-core</artifactId>
87-
<version>1.6.1</version>
87+
<version>1.6.2</version>
8888
</dependency>
8989
```
9090

9191
And make sure that you use the latest Kotlin version:
9292

9393
```xml
9494
<properties>
95-
<kotlin.version>1.6.0</kotlin.version>
95+
<kotlin.version>1.6.20</kotlin.version>
9696
</properties>
9797
```
9898

@@ -102,7 +102,7 @@ Add dependencies (you can also add other modules that you need):
102102

103103
```kotlin
104104
dependencies {
105-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1")
105+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2")
106106
}
107107
```
108108

@@ -111,10 +111,10 @@ And make sure that you use the latest Kotlin version:
111111
```kotlin
112112
plugins {
113113
// For build.gradle.kts (Kotlin DSL)
114-
kotlin("jvm") version "1.6.0"
114+
kotlin("jvm") version "1.6.20"
115115

116116
// For build.gradle (Groovy DSL)
117-
id "org.jetbrains.kotlin.jvm" version "1.6.0"
117+
id "org.jetbrains.kotlin.jvm" version "1.6.20"
118118
}
119119
```
120120

@@ -132,7 +132,7 @@ Add [`kotlinx-coroutines-android`](ui/kotlinx-coroutines-android)
132132
module as a dependency when using `kotlinx.coroutines` on Android:
133133

134134
```kotlin
135-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1")
135+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2")
136136
```
137137

138138
This gives you access to the Android [Dispatchers.Main]
@@ -167,7 +167,7 @@ In common code that should get compiled for different platforms, you can add a d
167167
```kotlin
168168
commonMain {
169169
dependencies {
170-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1")
170+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2")
171171
}
172172
}
173173
```
@@ -179,7 +179,7 @@ Platform-specific dependencies are recommended to be used only for non-multiplat
179179
#### JS
180180

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

185185
#### Native

benchmarks/build.gradle.kts

+6-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import me.champeau.gradle.*
88
import org.jetbrains.kotlin.gradle.tasks.*
99

1010
plugins {
11-
id("net.ltgt.apt")
1211
id("com.github.johnrengelman.shadow")
1312
id("me.champeau.gradle.jmh") apply false
1413
}
@@ -31,8 +30,6 @@ tasks.named<KotlinCompile>("compileJmhKotlin") {
3130
}
3231
}
3332

34-
35-
3633
// It is better to use the following to run benchmarks, otherwise you may get unexpected errors:
3734
// ./gradlew --no-daemon cleanJmhJar jmh -Pjmh="MyBenchmark"
3835
extensions.configure<JMHPluginExtension>("jmh") {
@@ -54,6 +51,12 @@ val jmhJarTask = tasks.named<Jar>("jmhJar") {
5451
}
5552

5653
tasks {
54+
// For some reason the DuplicatesStrategy from jmh is not enough
55+
// and errors with duplicates appear unless I force it to WARN only:
56+
withType<Copy> {
57+
duplicatesStrategy = DuplicatesStrategy.WARN
58+
}
59+
5760
build {
5861
dependsOn(jmhJarTask)
5962
}

benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ abstract class ParametrizedDispatcherBase : CoroutineScope {
2525
private var closeable: Closeable? = null
2626

2727
@Setup
28-
@UseExperimental(InternalCoroutinesApi::class)
2928
open fun setup() {
3029
coroutineContext = when {
3130
dispatcher == "fjp" -> ForkJoinPool.commonPool().asCoroutineDispatcher()

build.gradle

+7-6
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ buildscript {
5454
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
5555
classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
5656
classpath "org.jetbrains.kotlinx:kotlinx-knit:$knit_version"
57-
classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version"
57+
classpath "com.github.node-gradle:gradle-node-plugin:$gradle_node_version"
5858
classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version"
59-
classpath "ru.vyarus:gradle-animalsniffer-plugin:1.5.3" // Android API check
59+
classpath "ru.vyarus:gradle-animalsniffer-plugin:1.5.4" // Android API check
6060
classpath "org.jetbrains.kotlinx:kover:$kover_version"
6161

6262
// JMH plugins
63-
classpath "com.github.jengelman.gradle.plugins:shadow:5.1.0"
63+
classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.2"
6464
}
6565

6666
CacheRedirector.configureBuildScript(buildscript, rootProject)
@@ -130,6 +130,9 @@ allprojects {
130130
}
131131
}
132132

133+
// needs to be before evaluationDependsOn due to weird Gradle ordering
134+
apply plugin: "animalsniffer-conventions"
135+
133136
// Add dependency to core source sets. Core is configured in kx-core/build.gradle
134137
configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != coreModule }) {
135138
evaluationDependsOn(":$coreModule")
@@ -232,7 +235,7 @@ def core_docs_url = "https://kotlin.github.io/kotlinx.coroutines/$coreModule/"
232235
def core_docs_file = "$projectDir/kotlinx-coroutines-core/build/dokka/htmlPartial/package-list"
233236
apply plugin: "org.jetbrains.dokka"
234237

235-
configure(subprojects.findAll { !unpublished.contains(it.name) }) {
238+
configure(subprojects.findAll { !unpublished.contains(it.name) && it.name != coreModule }) {
236239
if (it.name != 'kotlinx-coroutines-bom') {
237240
apply from: rootProject.file('gradle/dokka.gradle.kts')
238241
}
@@ -303,8 +306,6 @@ def publishTasks = getTasksByName("publish", true) + getTasksByName("publishNpm"
303306

304307
task deploy(dependsOn: publishTasks)
305308

306-
apply plugin: "animalsniffer-conventions"
307-
308309
clean.dependsOn gradle.includedBuilds.collect { it.task(':clean') }
309310

310311
// --------------- Knit configuration ---------------

buildSrc/src/main/kotlin/Publishing.kt

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.gradle.api.Project
88
import org.gradle.api.artifacts.dsl.*
99
import org.gradle.api.publish.maven.*
10+
import org.gradle.kotlin.dsl.*
1011
import org.gradle.plugins.signing.*
1112
import java.net.*
1213

@@ -56,6 +57,11 @@ fun configureMavenPublication(rh: RepositoryHandler, project: Project) {
5657
password = project.getSensitiveProperty("libs.sonatype.password")
5758
}
5859
}
60+
61+
// Something that's easy to "clean" for development, not mavenLocal
62+
rh.maven("${project.rootProject.buildDir}/repo") {
63+
name = "buildRepo"
64+
}
5965
}
6066

6167
fun signPublicationIfKeyPresent(project: Project, publication: MavenPublication) {

buildSrc/src/main/kotlin/animalsniffer-conventions.gradle.kts

+11-9
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@
44

55
import ru.vyarus.gradle.plugin.animalsniffer.*
66

7-
subprojects {
7+
configure(subprojects) {
88
// Skip JDK 8 projects or unpublished ones
9-
if (!shouldSniff()) return@subprojects
9+
if (!shouldSniff()) return@configure
1010
apply(plugin = "ru.vyarus.animalsniffer")
11-
configure<AnimalSnifferExtension> {
12-
sourceSets = listOf((project.extensions.getByName("sourceSets") as SourceSetContainer).getByName("main"))
13-
}
14-
val signature: Configuration by configurations
15-
dependencies {
16-
signature("net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature")
17-
signature("org.codehaus.mojo.signature:java17:1.0@signature")
11+
project.plugins.withType(JavaPlugin::class.java) {
12+
configure<AnimalSnifferExtension> {
13+
sourceSets = listOf((project.extensions.getByName("sourceSets") as SourceSetContainer).getByName("main"))
14+
}
15+
val signature: Configuration by configurations
16+
dependencies {
17+
signature("net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature")
18+
signature("org.codehaus.mojo.signature:java17:1.0@signature")
19+
}
1820
}
1921
}
2022

docs/topics/cancellation-and-timeouts.md

+43-7
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,42 @@ job: I'm sleeping 4 ...
103103
main: Now I can quit.
104104
-->
105105

106+
The same problem can be observed by catching a [CancellationException] and not rethrowing it:
107+
108+
```kotlin
109+
import kotlinx.coroutines.*
110+
111+
fun main() = runBlocking {
112+
//sampleStart
113+
val job = launch(Dispatchers.Default) {
114+
repeat(5) { i ->
115+
try {
116+
// print a message twice a second
117+
println("job: I'm sleeping $i ...")
118+
delay(500)
119+
} catch (e: Exception) {
120+
// log the exception
121+
println(e)
122+
}
123+
}
124+
}
125+
delay(1300L) // delay a bit
126+
println("main: I'm tired of waiting!")
127+
job.cancelAndJoin() // cancels the job and waits for its completion
128+
println("main: Now I can quit.")
129+
//sampleEnd
130+
}
131+
```
132+
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
133+
134+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt).
135+
>
136+
{type="note"}
137+
138+
While catching `Exception` is an anti-pattern, this issue may surface in more subtle ways, like when using the
139+
[`runCatching`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run-catching.html) function,
140+
which does not know rethrow [CancellationException].
141+
106142
## Making computation code cancellable
107143

108144
There are two approaches to making computation code cancellable. The first one is to periodically
@@ -137,7 +173,7 @@ fun main() = runBlocking {
137173
```
138174
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
139175

140-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt).
176+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt).
141177
>
142178
{type="note"}
143179

@@ -182,7 +218,7 @@ fun main() = runBlocking {
182218
```
183219
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
184220

185-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt).
221+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt).
186222
>
187223
{type="note"}
188224

@@ -237,7 +273,7 @@ fun main() = runBlocking {
237273
```
238274
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
239275

240-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt).
276+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt).
241277
>
242278
{type="note"}
243279

@@ -275,7 +311,7 @@ fun main() = runBlocking {
275311
```
276312
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
277313

278-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt).
314+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt).
279315
>
280316
{type="note"}
281317

@@ -318,7 +354,7 @@ fun main() = runBlocking {
318354
```
319355
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
320356

321-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt).
357+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt).
322358
>
323359
{type="note"}
324360

@@ -378,7 +414,7 @@ fun main() {
378414
```
379415
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
380416

381-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-08.kt).
417+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt).
382418
>
383419
{type="note"}
384420

@@ -431,7 +467,7 @@ fun main() {
431467
```
432468
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
433469

434-
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-09.kt).
470+
> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-cancel-10.kt).
435471
>
436472
{type="note"}
437473

docs/topics/coroutine-context-and-dispatchers.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ fun main() = runBlocking<Unit> {
334334
}
335335
delay(500)
336336
request.cancel() // cancel processing of the request
337-
delay(1000) // delay a second to see what happens
338337
println("main: Who has survived request cancellation?")
338+
delay(1000) // delay the main thread for a second to see what happens
339339
//sampleEnd
340340
}
341341
```
@@ -350,8 +350,8 @@ The output of this code is:
350350
```text
351351
job1: I run in my own Job and execute independently!
352352
job2: I am a child of the request coroutine
353-
job1: I am not affected by cancellation of the request
354353
main: Who has survived request cancellation?
354+
job1: I am not affected by cancellation of the request
355355
```
356356

357357
<!--- TEST -->

0 commit comments

Comments
 (0)