Skip to content

Update develop to the new release #4126

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 12 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Change log for kotlinx.coroutines

## Version 1.8.1

* Remove the `@ExperimentalTime` annotation from usages of `TimeSource` (#4046). Thanks, @hfhbd!
* Introduce a workaround for an Android bug that caused an occasional `NullPointerException` when setting the `StateFlow` value on old Android devices (#3820).
* No longer use `kotlin.random.Random` as part of `Dispatchers.Default` and `Dispatchers.IO` initialization (#4051).
* `Flow.timeout` throws the exception with which the channel was closed (#4071).
* Small tweaks and documentation fixes.

### Changelog relative to version 1.8.1-Beta

* `Flow.timeout` throws the exception with which the channel was closed (#4071).
* Small documentation fixes.

## Version 1.8.1-Beta

* Remove the `@ExperimentalTime` annotation from usages of `TimeSource` (#4046). Thanks, @hfhbd!
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Kotlin Stable](https://kotl.in/badges/stable.svg)](https://kotlinlang.org/docs/components-stability.html)
[![JetBrains official 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.8.1-Beta)](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.8.1-Beta)
[![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)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.21-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/)

Expand Down Expand Up @@ -85,7 +85,7 @@ Add dependencies (you can also add other modules that you need):
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.8.1-Beta</version>
<version>1.8.1</version>
</dependency>
```

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

```kotlin
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1-Beta")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}
```

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

```kotlin
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1-Beta")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
```

This gives you access to the Android [Dispatchers.Main]
Expand Down Expand Up @@ -168,7 +168,7 @@ In common code that should get compiled for different platforms, you can add a d
```kotlin
commonMain {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1-Beta")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
}
}
```
Expand All @@ -178,7 +178,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://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.8.1-Beta)
[`kotlinx-coroutines-core-js`](https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.8.1)
(follow the link to get the dependency declaration snippet).

#### Native
Expand Down
31 changes: 16 additions & 15 deletions docs/topics/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ fun main() = runBlocking {
//sampleStart
val channel = Channel<Int>()
launch {
// this might be heavy CPU-consuming computation or async logic, we'll just send five squares
// this might be heavy CPU-consuming computation or async logic,
// we'll just send five squares
for (x in 1..5) channel.send(x * x)
}
// here we print five received integers:
Expand Down Expand Up @@ -103,12 +104,12 @@ and an extension function [consumeEach], that replaces a `for` loop on the consu
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

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

fun main() = runBlocking {
//sampleStart
val squares = produceSquares()
squares.consumeEach { println(it) }
println("Done!")
Expand Down Expand Up @@ -575,25 +576,25 @@ import kotlinx.coroutines.channels.*

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

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

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

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

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

```text
Initial element is available immediately: kotlin.Unit
Next element is not ready in 50 ms: null
Next element is ready in 100 ms: kotlin.Unit
Consumer pauses for 150ms
Next element is not ready in 100 ms: null
Next element is ready in 200 ms: kotlin.Unit
Consumer pauses for 300ms
Next element is available immediately after large consumer delay: kotlin.Unit
Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit
```

<!--- TEST -->
Expand Down
12 changes: 5 additions & 7 deletions docs/topics/coroutine-context-and-dispatchers.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ import kotlinx.coroutines.*
fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")

fun main() {
//sampleStart
newSingleThreadContext("Ctx1").use { ctx1 ->
newSingleThreadContext("Ctx2").use { ctx2 ->
runBlocking(ctx1) {
Expand All @@ -239,7 +238,6 @@ fun main() {
}
}
}
//sampleEnd
}
```

Expand Down Expand Up @@ -420,14 +418,14 @@ fun main() = runBlocking(CoroutineName("main")) {
val v1 = async(CoroutineName("v1coroutine")) {
delay(500)
log("Computing v1")
252
6
}
val v2 = async(CoroutineName("v2coroutine")) {
delay(1000)
log("Computing v2")
6
7
}
log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
log("The answer for v1 * v2 = ${v1.await() * v2.await()}")
//sampleEnd
}
```
Expand All @@ -443,7 +441,7 @@ The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar t
[main @main#1] Started main coroutine
[main @v1coroutine#2] Computing v1
[main @v2coroutine#3] Computing v2
[main @main#1] The answer for v1 / v2 = 42
[main @main#1] The answer for v1 * v2 = 42
```

<!--- TEST FLEXIBLE_THREAD -->
Expand Down Expand Up @@ -504,7 +502,7 @@ class Activity {
// to be continued ...
```

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

```kotlin
Expand Down
12 changes: 8 additions & 4 deletions docs/topics/coroutines-and-channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ This API is used by the `loadContributorsBlocking()` function to fetch the list
1. Open `src/tasks/Request1Blocking.kt` to see its implementation:

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

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

Think about why the given code doesn't work as expected and try to fix it, or see the solutions below.

Expand Down Expand Up @@ -1206,8 +1210,8 @@ When the channel is full, the next `send` call on it is suspended until more fre
<def title="Rendezvous channel">
<p>The "Rendezvous" channel is a channel without a buffer, the same as a buffered channel with zero size.
One of the functions (<code>send()</code> or <code>receive()</code>) is always suspended until the other is called. </p>
<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>
is suspended. Similarly, if the <code>receive</code> function is called and the channel is empty or, in other words, there's no
<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>
is suspended. Similarly, if the <code>receive()</code> function is called and the channel is empty or, in other words, there's no
suspended <code>send()</code> call ready to send the element, the <code>receive()</code> call is suspended. </p>
<p>The "rendezvous" name ("a meeting at an agreed time and place") refers to the fact that <code>send()</code> and <code>receive()</code>
should "meet on time".</p>
Expand Down
4 changes: 2 additions & 2 deletions docs/topics/exception-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ The output of this code is (with [debug](https://github.com/Kotlin/kotlinx.corou

```text
Throwing exception from launch
Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IndexOutOfBoundsException
Joined failed job
Throwing exception from async
Caught ArithmeticException
Expand All @@ -73,7 +73,7 @@ Caught ArithmeticException
It is possible to customize the default behavior of printing **uncaught** exceptions to the console.
[CoroutineExceptionHandler] context element on a _root_ coroutine can be used as a generic `catch` block for
this root coroutine and all its children where custom exception handling may take place.
It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)).
It is similar to [`Thread.uncaughtExceptionHandler`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setUncaughtExceptionHandler-java.lang.Thread.UncaughtExceptionHandler-).
You cannot recover from the exception in the `CoroutineExceptionHandler`. The coroutine had already completed
with the corresponding exception when the handler is called. Normally, the handler is used to
log the exception, show some kind of error message, terminate, and/or restart the application.
Expand Down
5 changes: 3 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Kotlin
version=1.8.1-Beta-SNAPSHOT
version=1.8.1-SNAPSHOT
group=org.jetbrains.kotlinx
kotlin_version=1.9.21
# DO NOT rename this property without adapting kotlinx.train build chain:
Expand All @@ -11,9 +11,10 @@ junit5_version=5.7.0
knit_version=0.5.0
html_version=0.7.2
lincheck_version=2.18.1
dokka_version=1.9.10
dokka_version=1.9.20
byte_buddy_version=1.10.9
reactor_version=3.4.1
reactor_docs_version=3.4.5
reactive_streams_version=1.0.3
rxjava2_version=2.2.8
rxjava3_version=3.0.2
Expand Down
2 changes: 1 addition & 1 deletion integration-testing/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
kotlin_version=1.9.21
coroutines_version=1.8.1-Beta-SNAPSHOT
coroutines_version=1.8.1-SNAPSHOT
asm_version=9.3

kotlin.code.style=official
Expand Down
3 changes: 2 additions & 1 deletion kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import kotlinx.coroutines.channels.*
fun main() = runBlocking {
val channel = Channel<Int>()
launch {
// this might be heavy CPU-consuming computation or async logic, we'll just send five squares
// this might be heavy CPU-consuming computation or async logic,
// we'll just send five squares
for (x in 1..5) channel.send(x * x)
}
// here we print five received integers:
Expand Down
18 changes: 9 additions & 9 deletions kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

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

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

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

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

tickerChannel.cancel() // indicate that no more elements are needed
}
6 changes: 3 additions & 3 deletions kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ fun main() = runBlocking(CoroutineName("main")) {
val v1 = async(CoroutineName("v1coroutine")) {
delay(500)
log("Computing v1")
252
6
}
val v2 = async(CoroutineName("v2coroutine")) {
delay(1000)
log("Computing v2")
6
7
}
log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
log("The answer for v1 * v2 = ${v1.await() * v2.await()}")
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ class ChannelsGuideTest {
fun testExampleChannel10() {
test("ExampleChannel10") { kotlinx.coroutines.guide.exampleChannel10.main() }.verifyLines(
"Initial element is available immediately: kotlin.Unit",
"Next element is not ready in 50 ms: null",
"Next element is ready in 100 ms: kotlin.Unit",
"Consumer pauses for 150ms",
"Next element is not ready in 100 ms: null",
"Next element is ready in 200 ms: kotlin.Unit",
"Consumer pauses for 300ms",
"Next element is available immediately after large consumer delay: kotlin.Unit",
"Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit"
"Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit"
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class DispatcherGuideTest {
"[main @main#1] Started main coroutine",
"[main @v1coroutine#2] Computing v1",
"[main @v2coroutine#3] Computing v2",
"[main @main#1] The answer for v1 / v2 = 42"
"[main @main#1] The answer for v1 * v2 = 42"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ExceptionsGuideTest {
fun testExampleExceptions01() {
test("ExampleExceptions01") { kotlinx.coroutines.guide.exampleExceptions01.main() }.verifyExceptions(
"Throwing exception from launch",
"Exception in thread \"DefaultDispatcher-worker-2 @coroutine#2\" java.lang.IndexOutOfBoundsException",
"Exception in thread \"DefaultDispatcher-worker-1 @coroutine#2\" java.lang.IndexOutOfBoundsException",
"Joined failed job",
"Throwing exception from async",
"Caught ArithmeticException"
Expand Down
2 changes: 1 addition & 1 deletion kotlinx-coroutines-debug/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ stacktraces will be dumped to the console.
### Using as JVM agent

Debug module can also be used as a standalone JVM agent to enable debug probes on the application startup.
You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.8.1-Beta.jar`.
You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.8.1.jar`.
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.
When used as Java agent, `"kotlinx.coroutines.debug.enable.creation.stack.trace"` system property can be used to control
[DebugProbes.enableCreationStackTraces] along with agent startup.
Expand Down
2 changes: 1 addition & 1 deletion kotlinx-coroutines-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Provided [TestDispatcher] implementations:
Add `kotlinx-coroutines-test` to your project test dependencies:
```
dependencies {
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1-Beta'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1'
}
```

Expand Down
Loading