Skip to content

Commit 271081d

Browse files
committed
Merge remote-tracking branch 'origin/master' into develop
2 parents 84a6ef9 + cd696d3 commit 271081d

18 files changed

+81
-63
lines changed

CHANGES.md

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

3+
## Version 1.8.1
4+
5+
* Remove the `@ExperimentalTime` annotation from usages of `TimeSource` (#4046). Thanks, @hfhbd!
6+
* Introduce a workaround for an Android bug that caused an occasional `NullPointerException` when setting the `StateFlow` value on old Android devices (#3820).
7+
* No longer use `kotlin.random.Random` as part of `Dispatchers.Default` and `Dispatchers.IO` initialization (#4051).
8+
* `Flow.timeout` throws the exception with which the channel was closed (#4071).
9+
* Small tweaks and documentation fixes.
10+
11+
### Changelog relative to version 1.8.1-Beta
12+
13+
* `Flow.timeout` throws the exception with which the channel was closed (#4071).
14+
* Small documentation fixes.
15+
316
## Version 1.8.1-Beta
417

518
* Remove the `@ExperimentalTime` annotation from usages of `TimeSource` (#4046). Thanks, @hfhbd!

README.md

+6-6
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.8.1-Beta)](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.8.1-Beta)
6+
[![Download](https://img.shields.io/maven-central/v/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.8.1)](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.8.1)
77
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.21-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

@@ -85,7 +85,7 @@ Add dependencies (you can also add other modules that you need):
8585
<dependency>
8686
<groupId>org.jetbrains.kotlinx</groupId>
8787
<artifactId>kotlinx-coroutines-core</artifactId>
88-
<version>1.8.1-Beta</version>
88+
<version>1.8.1</version>
8989
</dependency>
9090
```
9191

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

104104
```kotlin
105105
dependencies {
106-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1-Beta")
106+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
107107
}
108108
```
109109

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

135135
```kotlin
136-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1-Beta")
136+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
137137
```
138138

139139
This gives you access to the Android [Dispatchers.Main]
@@ -168,7 +168,7 @@ In common code that should get compiled for different platforms, you can add a d
168168
```kotlin
169169
commonMain {
170170
dependencies {
171-
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1-Beta")
171+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
172172
}
173173
}
174174
```
@@ -178,7 +178,7 @@ Platform-specific dependencies are recommended to be used only for non-multiplat
178178
#### JS
179179

180180
Kotlin/JS version of `kotlinx.coroutines` is published as
181-
[`kotlinx-coroutines-core-js`](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.8.1-Beta)
181+
[`kotlinx-coroutines-core-js`](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.8.1)
182182
(follow the link to get the dependency declaration snippet).
183183

184184
#### Native

docs/topics/channels.md

+16-15
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ fun main() = runBlocking {
1919
//sampleStart
2020
val channel = Channel<Int>()
2121
launch {
22-
// this might be heavy CPU-consuming computation or async logic, we'll just send five squares
22+
// this might be heavy CPU-consuming computation or async logic,
23+
// we'll just send five squares
2324
for (x in 1..5) channel.send(x * x)
2425
}
2526
// here we print five received integers:
@@ -103,12 +104,12 @@ and an extension function [consumeEach], that replaces a `for` loop on the consu
103104
import kotlinx.coroutines.*
104105
import kotlinx.coroutines.channels.*
105106

107+
//sampleStart
106108
fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
107109
for (x in 1..5) send(x * x)
108110
}
109111

110112
fun main() = runBlocking {
111-
//sampleStart
112113
val squares = produceSquares()
113114
squares.consumeEach { println(it) }
114115
println("Done!")
@@ -575,25 +576,25 @@ import kotlinx.coroutines.channels.*
575576

576577
//sampleStart
577578
fun main() = runBlocking<Unit> {
578-
val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
579+
val tickerChannel = ticker(delayMillis = 200, initialDelayMillis = 0) // create a ticker channel
579580
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
580581
println("Initial element is available immediately: $nextElement") // no initial delay
581582

582-
nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
583-
println("Next element is not ready in 50 ms: $nextElement")
583+
nextElement = withTimeoutOrNull(100) { tickerChannel.receive() } // all subsequent elements have 200ms delay
584+
println("Next element is not ready in 100 ms: $nextElement")
584585

585-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
586-
println("Next element is ready in 100 ms: $nextElement")
586+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
587+
println("Next element is ready in 200 ms: $nextElement")
587588

588589
// Emulate large consumption delays
589-
println("Consumer pauses for 150ms")
590-
delay(150)
590+
println("Consumer pauses for 300ms")
591+
delay(300)
591592
// Next element is available immediately
592593
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
593594
println("Next element is available immediately after large consumer delay: $nextElement")
594595
// Note that the pause between `receive` calls is taken into account and next element arrives faster
595-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
596-
println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
596+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
597+
println("Next element is ready in 100ms after consumer pause in 300ms: $nextElement")
597598

598599
tickerChannel.cancel() // indicate that no more elements are needed
599600
}
@@ -609,11 +610,11 @@ It prints following lines:
609610

610611
```text
611612
Initial element is available immediately: kotlin.Unit
612-
Next element is not ready in 50 ms: null
613-
Next element is ready in 100 ms: kotlin.Unit
614-
Consumer pauses for 150ms
613+
Next element is not ready in 100 ms: null
614+
Next element is ready in 200 ms: kotlin.Unit
615+
Consumer pauses for 300ms
615616
Next element is available immediately after large consumer delay: kotlin.Unit
616-
Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
617+
Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit
617618
```
618619

619620
<!--- TEST -->

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

+5-7
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ import kotlinx.coroutines.*
227227
fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
228228

229229
fun main() {
230-
//sampleStart
231230
newSingleThreadContext("Ctx1").use { ctx1 ->
232231
newSingleThreadContext("Ctx2").use { ctx2 ->
233232
runBlocking(ctx1) {
@@ -239,7 +238,6 @@ fun main() {
239238
}
240239
}
241240
}
242-
//sampleEnd
243241
}
244242
```
245243

@@ -420,14 +418,14 @@ fun main() = runBlocking(CoroutineName("main")) {
420418
val v1 = async(CoroutineName("v1coroutine")) {
421419
delay(500)
422420
log("Computing v1")
423-
252
421+
6
424422
}
425423
val v2 = async(CoroutineName("v2coroutine")) {
426424
delay(1000)
427425
log("Computing v2")
428-
6
426+
7
429427
}
430-
log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
428+
log("The answer for v1 * v2 = ${v1.await() * v2.await()}")
431429
//sampleEnd
432430
}
433431
```
@@ -443,7 +441,7 @@ The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar t
443441
[main @main#1] Started main coroutine
444442
[main @v1coroutine#2] Computing v1
445443
[main @v2coroutine#3] Computing v2
446-
[main @main#1] The answer for v1 / v2 = 42
444+
[main @main#1] The answer for v1 * v2 = 42
447445
```
448446

449447
<!--- TEST FLEXIBLE_THREAD -->
@@ -504,7 +502,7 @@ class Activity {
504502
// to be continued ...
505503
```
506504

507-
Now, we can launch coroutines in the scope of this `Activity` using the defined `scope`.
505+
Now, we can launch coroutines in the scope of this `Activity` using the defined `mainScope`.
508506
For the demo, we launch ten coroutines that delay for a different time:
509507

510508
```kotlin

docs/topics/coroutines-and-channels.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ This API is used by the `loadContributorsBlocking()` function to fetch the list
9191
1. Open `src/tasks/Request1Blocking.kt` to see its implementation:
9292

9393
```kotlin
94-
fun loadContributorsBlocking(service: GitHubService, req: RequestData): List<User> {
94+
fun loadContributorsBlocking(
95+
service: GitHubService,
96+
req: RequestData
97+
): List<User> {
9598
val repos = service
9699
.getOrgReposCall(req.org) // #1
97100
.execute() // #2
@@ -328,7 +331,8 @@ fun loadContributorsCallbacks(
328331
* The logic for handling the responses is extracted into callbacks: the corresponding lambdas start at lines `#1` and `#2`.
329332

330333
However, the provided solution doesn't work. If you run the program and load contributors by choosing the _CALLBACKS_
331-
option, you'll see that nothing is shown. However, the tests that immediately return the result pass.
334+
option, you'll see that nothing is shown. However, the test from `Request3CallbacksKtTest` immediately returns the result
335+
that it successfully passed.
332336

333337
Think about why the given code doesn't work as expected and try to fix it, or see the solutions below.
334338
@@ -1206,8 +1210,8 @@ When the channel is full, the next `send` call on it is suspended until more fre
12061210
<def title="Rendezvous channel">
12071211
<p>The "Rendezvous" channel is a channel without a buffer, the same as a buffered channel with zero size.
12081212
One of the functions (<code>send()</code> or <code>receive()</code>) is always suspended until the other is called. </p>
1209-
<p>If the <code>send()</code> function is called and there's no suspended <code>receive</code> call ready to process the element, then <code>send()</code>
1210-
is suspended. Similarly, if the <code>receive</code> function is called and the channel is empty or, in other words, there's no
1213+
<p>If the <code>send()</code> function is called and there's no suspended <code>receive()</code> call ready to process the element, then <code>send()</code>
1214+
is suspended. Similarly, if the <code>receive()</code> function is called and the channel is empty or, in other words, there's no
12111215
suspended <code>send()</code> call ready to send the element, the <code>receive()</code> call is suspended. </p>
12121216
<p>The "rendezvous" name ("a meeting at an agreed time and place") refers to the fact that <code>send()</code> and <code>receive()</code>
12131217
should "meet on time".</p>

docs/topics/exception-handling.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ The output of this code is (with [debug](https://github.com/Kotlin/kotlinx.corou
6060

6161
```text
6262
Throwing exception from launch
63-
Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
63+
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IndexOutOfBoundsException
6464
Joined failed job
6565
Throwing exception from async
6666
Caught ArithmeticException
@@ -73,7 +73,7 @@ Caught ArithmeticException
7373
It is possible to customize the default behavior of printing **uncaught** exceptions to the console.
7474
[CoroutineExceptionHandler] context element on a _root_ coroutine can be used as a generic `catch` block for
7575
this root coroutine and all its children where custom exception handling may take place.
76-
It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
76+
It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler-java.lang.Thread.UncaughtExceptionHandler-).
7777
You cannot recover from the exception in the `CoroutineExceptionHandler`. The coroutine had already completed
7878
with the corresponding exception when the handler is called. Normally, the handler is used to
7979
log the exception, show some kind of error message, terminate, and/or restart the application.

gradle.properties

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Kotlin
2-
version=1.8.1-Beta-SNAPSHOT
2+
version=1.8.1-SNAPSHOT
33
group=org.jetbrains.kotlinx
44
kotlin_version=1.9.21
55
# DO NOT rename this property without adapting kotlinx.train build chain:
@@ -11,9 +11,10 @@ junit5_version=5.7.0
1111
knit_version=0.5.0
1212
html_version=0.7.2
1313
lincheck_version=2.18.1
14-
dokka_version=1.9.10
14+
dokka_version=1.9.20
1515
byte_buddy_version=1.10.9
1616
reactor_version=3.4.1
17+
reactor_docs_version=3.4.5
1718
reactive_streams_version=1.0.3
1819
rxjava2_version=2.2.8
1920
rxjava3_version=3.0.2

integration-testing/gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
kotlin_version=1.9.21
2-
coroutines_version=1.8.1-Beta-SNAPSHOT
2+
coroutines_version=1.8.1-SNAPSHOT
33
asm_version=9.3
44

55
kotlin.code.style=official

kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import kotlinx.coroutines.channels.*
77
fun main() = runBlocking {
88
val channel = Channel<Int>()
99
launch {
10-
// this might be heavy CPU-consuming computation or async logic, we'll just send five squares
10+
// this might be heavy CPU-consuming computation or async logic,
11+
// we'll just send five squares
1112
for (x in 1..5) channel.send(x * x)
1213
}
1314
// here we print five received integers:

kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt

+9-9
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,25 @@ import kotlinx.coroutines.*
55
import kotlinx.coroutines.channels.*
66

77
fun main() = runBlocking<Unit> {
8-
val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
8+
val tickerChannel = ticker(delayMillis = 200, initialDelayMillis = 0) // create a ticker channel
99
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
1010
println("Initial element is available immediately: $nextElement") // no initial delay
1111

12-
nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
13-
println("Next element is not ready in 50 ms: $nextElement")
12+
nextElement = withTimeoutOrNull(100) { tickerChannel.receive() } // all subsequent elements have 200ms delay
13+
println("Next element is not ready in 100 ms: $nextElement")
1414

15-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
16-
println("Next element is ready in 100 ms: $nextElement")
15+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
16+
println("Next element is ready in 200 ms: $nextElement")
1717

1818
// Emulate large consumption delays
19-
println("Consumer pauses for 150ms")
20-
delay(150)
19+
println("Consumer pauses for 300ms")
20+
delay(300)
2121
// Next element is available immediately
2222
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
2323
println("Next element is available immediately after large consumer delay: $nextElement")
2424
// Note that the pause between `receive` calls is taken into account and next element arrives faster
25-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
26-
println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
25+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
26+
println("Next element is ready in 100ms after consumer pause in 300ms: $nextElement")
2727

2828
tickerChannel.cancel() // indicate that no more elements are needed
2929
}

kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ fun main() = runBlocking(CoroutineName("main")) {
1111
val v1 = async(CoroutineName("v1coroutine")) {
1212
delay(500)
1313
log("Computing v1")
14-
252
14+
6
1515
}
1616
val v2 = async(CoroutineName("v2coroutine")) {
1717
delay(1000)
1818
log("Computing v2")
19-
6
19+
7
2020
}
21-
log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
21+
log("The answer for v1 * v2 = ${v1.await() * v2.await()}")
2222
}

kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ class ChannelsGuideTest {
113113
fun testExampleChannel10() {
114114
test("ExampleChannel10") { kotlinx.coroutines.guide.exampleChannel10.main() }.verifyLines(
115115
"Initial element is available immediately: kotlin.Unit",
116-
"Next element is not ready in 50 ms: null",
117-
"Next element is ready in 100 ms: kotlin.Unit",
118-
"Consumer pauses for 150ms",
116+
"Next element is not ready in 100 ms: null",
117+
"Next element is ready in 200 ms: kotlin.Unit",
118+
"Consumer pauses for 300ms",
119119
"Next element is available immediately after large consumer delay: kotlin.Unit",
120-
"Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit"
120+
"Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit"
121121
)
122122
}
123123
}

kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class DispatcherGuideTest {
7777
"[main @main#1] Started main coroutine",
7878
"[main @v1coroutine#2] Computing v1",
7979
"[main @v2coroutine#3] Computing v2",
80-
"[main @main#1] The answer for v1 / v2 = 42"
80+
"[main @main#1] The answer for v1 * v2 = 42"
8181
)
8282
}
8383

kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class ExceptionsGuideTest {
99
fun testExampleExceptions01() {
1010
test("ExampleExceptions01") { kotlinx.coroutines.guide.exampleExceptions01.main() }.verifyExceptions(
1111
"Throwing exception from launch",
12-
"Exception in thread \"DefaultDispatcher-worker-2 @coroutine#2\" java.lang.IndexOutOfBoundsException",
12+
"Exception in thread \"DefaultDispatcher-worker-1 @coroutine#2\" java.lang.IndexOutOfBoundsException",
1313
"Joined failed job",
1414
"Throwing exception from async",
1515
"Caught ArithmeticException"

kotlinx-coroutines-debug/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ stacktraces will be dumped to the console.
6161
### Using as JVM agent
6262

6363
Debug module can also be used as a standalone JVM agent to enable debug probes on the application startup.
64-
You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.8.1-Beta.jar`.
64+
You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.8.1.jar`.
6565
Additionally, on Linux and Mac OS X you can use `kill -5 $pid` command in order to force your application to print all alive coroutines.
6666
When used as Java agent, `"kotlinx.coroutines.debug.enable.creation.stack.trace"` system property can be used to control
6767
[DebugProbes.enableCreationStackTraces] along with agent startup.

kotlinx-coroutines-test/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Provided [TestDispatcher] implementations:
2626
Add `kotlinx-coroutines-test` to your project test dependencies:
2727
```
2828
dependencies {
29-
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1-Beta'
29+
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1'
3030
}
3131
```
3232

0 commit comments

Comments
 (0)