diff --git a/.gitignore b/.gitignore index aed7103292..52843ca5b7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ !/.idea/copyright !/.idea/codeStyleSettings.xml !/.idea/codeStyles +!/.idea/dictionaries *.iml .gradle .gradletasknamecache diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml new file mode 100644 index 0000000000..3da8e22952 --- /dev/null +++ b/.idea/dictionaries/shared.xml @@ -0,0 +1,9 @@ + + + + kotlinx + lincheck + redirector + + + \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index aad312acda..b4c2a7bdd6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,31 @@ # Change log for kotlinx.coroutines +## Version 1.4.3 + +### General changes + +* Thread context is properly preserved and restored for coroutines without `ThreadContextElement` (#985) +* `ThreadContextElement`s are now restored in the opposite order from update (#2195) +* Improved performance of combine with 4 parameters, thanks to @alexvanyo (#2419) +* Debug agent sanitizer leaves at least one frame with source location (#1437) +* Update Reactor version in `kotlinx-coroutines-reactor` to `3.4.1`, thanks to @sokomishalov (#2432) +* `callInPlace` contract added to `ReceiveChannel.consume` (#941) +* `CoroutineStart.UNDISPATCHED` promoted to stable API (#1393) +* Kotlin updated to 1.4.30 +* `kotlinx.coroutines` are now released directly to MavenCentral +* Reduced the size of `DispatchedCoroutine` by a field +* Internal class `TimeSource` renamed to `SchedulerTimeSource` to prevent wildcard import issues (#2537) + +### Bug fixes + +* Fixed the problem that prevented implementation via delegation for `Job` interface (#2423) +* Fixed incorrect ProGuard rules that allowed shrinking volatile felds (#1564) +* Fixed `await/`asDeferred` for `MinimalState` implementations in jdk8 module (#2456) +* Fixed bug when `onUndeliveredElement` wasn't called for unlimited channels (#2435) +* Fixed a bug when `ListenableFuture.isCancelled` returned from `asListenableFuture` could have thrown an exception, thanks to @vadimsemenov (#2421) +* Coroutine in `callbackFlow` and `produce` is properly cancelled when the channel was closed separately (#2506) + + ## Version 1.4.2 * Fixed `StackOverflowError` in `Job.toString` when `Job` is observed in its intermediate state (#2371). diff --git a/README.md b/README.md index e2bd623788..08417dd0f5 100644 --- a/README.md +++ b/README.md @@ -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://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.4.2) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.4.2) -[![Kotlin](https://img.shields.io/badge/kotlin-1.4.0-blue.svg?logo=kotlin)](http://kotlinlang.org) +[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.4.3) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.4.3) +[![Kotlin](https://img.shields.io/badge/kotlin-1.4.30-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 Kotlin `1.4.0` release. +This is a companion version for Kotlin `1.4.30` release. ```kotlin suspend fun main() = coroutineScope { @@ -45,6 +45,7 @@ suspend fun main() = coroutineScope { * [debug](kotlinx-coroutines-debug/README.md) — debug utilities for coroutines: * [DebugProbes] API to probe, keep track of, print and dump active coroutines; * [CoroutinesTimeout] test rule to automatically dump coroutines on test timeout. + * Automatic integration with [BlockHound](https://github.com/reactor/BlockHound). * [reactive](reactive/README.md) — modules that provide builders and iteration support for various reactive streams libraries: * Reactive Streams ([Publisher.collect], [Publisher.awaitSingle], [kotlinx.coroutines.reactive.publish], etc), * Flow (JDK 9) (the same interface as for Reactive Streams), @@ -86,7 +87,7 @@ Add dependencies (you can also add other modules that you need): org.jetbrains.kotlinx kotlinx-coroutines-core - 1.4.2 + 1.4.3 ``` @@ -94,7 +95,7 @@ And make sure that you use the latest Kotlin version: ```xml - 1.4.0 + 1.4.30 ``` @@ -104,7 +105,7 @@ Add dependencies (you can also add other modules that you need): ```groovy dependencies { - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3' } ``` @@ -112,15 +113,15 @@ And make sure that you use the latest Kotlin version: ```groovy buildscript { - ext.kotlin_version = '1.4.0' + ext.kotlin_version = '1.4.30' } ``` -Make sure that you have either `jcenter()` or `mavenCentral()` in the list of repositories: +Make sure that you have `mavenCentral()` in the list of repositories: ``` repository { - jcenter() + mavenCentral() } ``` @@ -130,7 +131,7 @@ Add dependencies (you can also add other modules that you need): ```groovy dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3") } ``` @@ -138,24 +139,11 @@ And make sure that you use the latest Kotlin version: ```groovy plugins { - kotlin("jvm") version "1.4.0" + kotlin("jvm") version "1.4.30" } ``` -Make sure that you have either `jcenter()` or `mavenCentral()` in the list of repositories. - -### Multiplatform - -Core modules of `kotlinx.coroutines` are also available for -[Kotlin/JS](#js) and [Kotlin/Native](#native). -In common code that should get compiled for different platforms, you can add dependency to `kotlinx-coroutines-core` right to the `commonMain` source set: -```groovy -commonMain { - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") - } -} -``` +Make sure that you have `mavenCentral()` in the list of repositories. ### Android @@ -163,18 +151,18 @@ Add [`kotlinx-coroutines-android`](ui/kotlinx-coroutines-android) module as dependency when using `kotlinx.coroutines` on Android: ```groovy -implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' +implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3' ``` This gives you access to Android [Dispatchers.Main] coroutine dispatcher and also makes sure that in case of crashed coroutine with unhandled exception this -exception is logged before crashing Android application, similarly to the way uncaught exceptions in -threads are handled by Android runtime. +exception is logged before crashing Android application, similarly to the way uncaught exceptions in +threads are handled by Android runtime. #### R8 and ProGuard R8 and ProGuard rules are bundled into the [`kotlinx-coroutines-android`](ui/kotlinx-coroutines-android) module. -For more details see ["Optimization" section for Android](ui/kotlinx-coroutines-android/README.md#optimization). +For more details see ["Optimization" section for Android](ui/kotlinx-coroutines-android/README.md#optimization). #### Avoiding including the debug infrastructure in the resulting APK @@ -187,27 +175,40 @@ packagingOptions { } ``` -### JS +### Multiplatform -[Kotlin/JS](https://kotlinlang.org/docs/js-overview.html) 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.2/jar) -(follow the link to get the dependency declaration snippet). - -You can also use [`kotlinx-coroutines-core`](https://www.npmjs.com/package/kotlinx-coroutines-core) package via NPM. +Core modules of `kotlinx.coroutines` are also available for +[Kotlin/JS](https://kotlinlang.org/docs/reference/js-overview.html) and [Kotlin/Native](https://kotlinlang.org/docs/reference/native-overview.html). -### Native +In common code that should get compiled for different platforms, you can add dependency to `kotlinx-coroutines-core` right to the `commonMain` source set: +```groovy +commonMain { + dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3") + } +} +``` -[Kotlin/Native](https://kotlinlang.org/docs/native-overview.html) version of `kotlinx.coroutines` is published as -[`kotlinx-coroutines-core-native`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-native/1.4.2/jar) -(follow the link to get the dependency declaration snippet). +No more additional dependencies is needed, platform-specific artifacts will be resolved automatically via Gradle metadata available since Gradle 5.3. -Only single-threaded code (JS-style) on Kotlin/Native is currently supported. -Kotlin/Native supports only Gradle version 4.10 and you need to enable Gradle metadata in your -`settings.gradle` file: +Platform-specific dependencies are recommended to be used only for non-multiplatform projects that are compiled only for target platform. -```groovy -enableFeaturePreview('GRADLE_METADATA') -``` +#### 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) +(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 + +Kotlin/Native version of `kotlinx.coroutines` is published as +[`kotlinx-coroutines-core-$platform`](https://mvnrepository.com/search?q=kotlinx-coroutines-core-) where `$platform` is +the target Kotlin/Native platform. [List of currently supported targets](https://github.com/Kotlin/kotlinx.coroutines/blob/master/gradle/compile-native-multiplatform.gradle#L16). + + +Only single-threaded code (JS-style) on Kotlin/Native is supported in stable versions. +Additionally, special `-native-mt` version is released on a regular basis, for the state of multi-threaded coroutines support +please follow the [corresponding issue](https://github.com/Kotlin/kotlinx.coroutines/issues/462) for the additional details. Since Kotlin/Native does not generally provide binary compatibility between versions, you should use the same version of Kotlin/Native compiler as was used to build `kotlinx.coroutines`. @@ -218,6 +219,7 @@ See [Contributing Guidelines](CONTRIBUTING.md). + [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html [async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html @@ -239,52 +241,81 @@ See [Contributing Guidelines](CONTRIBUTING.md). [Promise.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/kotlin.js.-promise/await.html [promise]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/promise.html [Window.asCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/org.w3c.dom.-window/as-coroutine-dispatcher.html + + [Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html [_flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow.html [filter]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/filter.html [map]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/map.html + + [Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/index.html + + [select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html + + [Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html [Semaphore]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-semaphore/index.html + + [Dispatchers.setMain]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/kotlinx.coroutines.-dispatchers/set-main.html [TestCoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-scope/index.html + + [DebugProbes]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/index.html + + [CoroutinesTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug.junit4/-coroutines-timeout/index.html + + [MDCContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-slf4j/kotlinx.coroutines.slf4j/-m-d-c-context/index.html + + [CompletionStage.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/java.util.concurrent.-completion-stage/await.html + + [ListenableFuture.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-guava/kotlinx.coroutines.guava/com.google.common.util.concurrent.-listenable-future/await.html + + [Task.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-play-services/kotlinx.coroutines.tasks/com.google.android.gms.tasks.-task/await.html + + [Publisher.collect]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/org.reactivestreams.-publisher/collect.html [Publisher.awaitSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/org.reactivestreams.-publisher/await-single.html [kotlinx.coroutines.reactive.publish]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/publish.html + + [rxFlowable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/rx-flowable.html [rxSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/rx-single.html + + [flux]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/flux.html [mono]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/mono.html + diff --git a/RELEASE.md b/RELEASE.md index b2a08b6757..c9fd83fb8e 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -18,9 +18,7 @@ To release new `` of `kotlinx-coroutines`: * [`kotlinx-coroutines-test/README.md`](kotlinx-coroutines-test/README.md) * [`coroutines-guide-ui.md`](ui/coroutines-guide-ui.md) * Properties - * [`gradle.properties`](gradle.properties) - * [`ui/kotlinx-coroutines-android/example-app/gradle.properties`](ui/kotlinx-coroutines-android/example-app/gradle.properties) - * [`ui/kotlinx-coroutines-android/animation-app/gradle.properties`](ui/kotlinx-coroutines-android/animation-app/gradle.properties) + * [`gradle.properties`](gradle.properties) * Make sure to **exclude** `CHANGES.md` from replacements. As an alternative approach you can use `./bump-version.sh old_version new_version` @@ -61,10 +59,9 @@ To release new `` of `kotlinx-coroutines`: (make sure you have [Docker](https://www.docker.com/) installed first):
`site/deploy.sh push` -4. In [Bintray](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines) admin interface: - * Publish artifacts of the new version. - * Wait until newly published version becomes the most recent. - * Sync to Maven Central. +4. In [Nexus](https://oss.sonatype.org/#stagingRepositories) admin interface: + * Close the repository and wait for it to verify. + * Release the repository. 5. Announce new release in [Slack](https://kotlinlang.slack.com) diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index b60dcbc8f4..ce0bff1cdf 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UnstableApiUsage") diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java index 04f7210381..6d9169d3d6 100644 --- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java +++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble; diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java index 71c7604d0c..2d900cad87 100644 --- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java +++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble; diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java index 5f93b4ee88..0acf98d0d2 100644 --- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java +++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableCharSequence.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble.optimizations; diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java index af8696c802..1c78f5eca0 100644 --- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java +++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/FlowableSplit.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble.optimizations; diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java index cf6cc79b79..f51112b45f 100644 --- a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java +++ b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/optimizations/StringFlowable.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble.optimizations; diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt index deeea77af9..0fa5048983 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt index 6c5b623191..f706d3aa03 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks @@ -10,7 +10,7 @@ import org.openjdk.jmh.annotations.* import java.util.concurrent.* import kotlin.coroutines.* -@Warmup(iterations = 5, time = 1) +@Warmup(iterations = 7, time = 1) @Measurement(iterations = 5, time = 1) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @@ -41,7 +41,7 @@ open class ChannelSinkBenchmark { private suspend inline fun run(context: CoroutineContext): Int { return Channel - .range(1, 1_000_000, context) + .range(1, 10_000, context) .filter(context) { it % 4 == 0 } .fold(0) { a, b -> a + b } } diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt new file mode 100644 index 0000000000..d3f6be6770 --- /dev/null +++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkDepthBenchmark.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package benchmarks + +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* +import org.openjdk.jmh.annotations.* +import java.util.concurrent.* +import kotlin.coroutines.* + +@Warmup(iterations = 7, time = 1) +@Measurement(iterations = 5, time = 1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +@Fork(2) +open class ChannelSinkDepthBenchmark { + private val tl = ThreadLocal.withInitial({ 42 }) + + private val unconfinedOneElement = Dispatchers.Unconfined + tl.asContextElement() + + @Benchmark + fun depth1(): Int = runBlocking { + run(1, unconfinedOneElement) + } + + @Benchmark + fun depth10(): Int = runBlocking { + run(10, unconfinedOneElement) + } + + @Benchmark + fun depth100(): Int = runBlocking { + run(100, unconfinedOneElement) + } + + @Benchmark + fun depth1000(): Int = runBlocking { + run(1000, unconfinedOneElement) + } + + private suspend inline fun run(callTraceDepth: Int, context: CoroutineContext): Int { + return Channel + .range(1, 10_000, context) + .filter(callTraceDepth, context) { it % 4 == 0 } + .fold(0) { a, b -> a + b } + } + + private fun Channel.Factory.range(start: Int, count: Int, context: CoroutineContext) = + GlobalScope.produce(context) { + for (i in start until (start + count)) + send(i) + } + + // Migrated from deprecated operators, are good only for stressing channels + + private fun ReceiveChannel.filter( + callTraceDepth: Int, + context: CoroutineContext = Dispatchers.Unconfined, + predicate: suspend (Int) -> Boolean + ): ReceiveChannel = + GlobalScope.produce(context, onCompletion = { cancel() }) { + deeplyNestedFilter(this, callTraceDepth, predicate) + } + + private suspend fun ReceiveChannel.deeplyNestedFilter( + sink: ProducerScope, + depth: Int, + predicate: suspend (Int) -> Boolean + ) { + if (depth <= 1) { + for (e in this) { + if (predicate(e)) sink.send(e) + } + } else { + deeplyNestedFilter(sink, depth - 1, predicate) + require(true) // tail-call + } + } + + private suspend inline fun ReceiveChannel.fold(initial: R, operation: (acc: R, E) -> R): R { + var accumulator = initial + consumeEach { + accumulator = operation(accumulator, it) + } + return accumulator + } +} + diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt b/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt index b635d1ef2c..9948a371bc 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks diff --git a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt index 5da5dc8920..40ddc8ec36 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks diff --git a/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt index ea9aeca94d..df94075258 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.akka diff --git a/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt index 5cfb86dda0..fef641ae7b 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.akka diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt index 4725ceda91..be371548fe 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineFlowsBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt index f7fbc6cf23..bc8d8687a4 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/CombineTwoFlowsBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt index f3b2082ae1..32d35475db 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt index 149898881b..09d841eb75 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt index 8453f5c7f9..636b334dbf 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt index 258df9b03e..d957bdbe0e 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt index 1e12e2c33e..a0a2decced 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt index fd3d3cdb96..7501e2c419 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/TakeWhileBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt index 3501bdfed3..b8e1f4509a 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt index 2573d30da0..cd27cca0ed 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt index 32c0d4c8fa..e78d7bd080 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt index 2283d6c3fb..1db4dae09e 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt index ad97dfa373..533bc5e6db 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt index fa944fac84..e7bd1f5fb9 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt index 7beb54cc3d..006d36c04b 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt index 3012b9178a..1fe709266d 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/DispatchersContextSwitchBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt index 724a5909b9..20bdfa349a 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/ForkJoinBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt index a0de6016c4..d64fdd2f7d 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt index f829573c87..c5b34eda90 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt index 6ac97ad3e7..1ffb5207f0 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler.actors diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt index 71018abcbc..cd212cc17b 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/CycledActorsBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler.actors diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt index 4c6ae7754c..d696c64ffc 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongActorBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler.actors diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt index dcbda090e8..a6f0a473c1 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler.actors diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt index 01691a2d77..eebcec0152 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/StatefulActorBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler.actors diff --git a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt b/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt index d961dab8d9..1f71d8dc19 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.tailcall diff --git a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt index 7bb962b3b8..9654b6dabe 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.tailcall diff --git a/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt b/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt index 27bc6b7d85..858ecfad67 100644 --- a/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt +++ b/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.common diff --git a/build.gradle b/build.gradle index 938d42e7a1..80124e7ea0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import org.jetbrains.kotlin.konan.target.HostManager import org.gradle.util.VersionNumber @@ -7,7 +7,6 @@ import org.gradle.util.VersionNumber apply plugin: 'jdk-convention' apply from: rootProject.file("gradle/experimental.gradle") -def rootModule = "kotlinx.coroutines" def coreModule = "kotlinx-coroutines-core" // Not applicable for Kotlin plugin def sourceless = ['kotlinx.coroutines', 'site', 'kotlinx-coroutines-bom', 'integration-testing'] @@ -54,14 +53,7 @@ buildscript { } repositories { - jcenter() - maven { - url "https://kotlin.bintray.com/kotlinx" - credentials { - username = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') ?: "" - password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') ?: "" - } - } + 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 { @@ -71,7 +63,6 @@ buildscript { password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') ?: "" } } - maven { url "https://kotlin.bintray.com/kotlin-eap" } maven { url "https://jetbrains.bintray.com/kotlin-native-dependencies" } maven { url "https://plugins.gradle.org/m2/" } } @@ -158,25 +149,10 @@ allprojects { * transitive dependencies was removed from jcenter, thus breaking gradle dependency resolution */ google() - jcenter() + 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/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') ?: "" - } - } - maven { url "https://kotlin.bintray.com/kotlin-eap" } - maven { - url "https://kotlin.bintray.com/kotlinx" - credentials { - username = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') ?: "" - password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') ?: "" - } - } - mavenLocal() + maven { url "https://kotlin.bintray.com/kotlinx" } } } @@ -184,10 +160,10 @@ allprojects { configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != coreModule }) { evaluationDependsOn(":$coreModule") def platform = PlatformKt.platformOf(it) - apply from: rootProject.file("gradle/compile-${platform}.gradle") + apply plugin: "kotlin-${platform}-conventions" dependencies { // See comment below for rationale, it will be replaced with "project" dependency - compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" + compile project(":$coreModule") // the only way IDEA can resolve test classes testCompile project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs } @@ -203,6 +179,8 @@ configure(subprojects.findAll { !sourceless.contains(it.name) }) { kotlinOptions.freeCompilerArgs += experimentalAnnotations.collect { "-Xuse-experimental=" + it } kotlinOptions.freeCompilerArgs += "-progressive" kotlinOptions.freeCompilerArgs += "-XXLanguage:+InlineClasses" + // Disable KT-36770 for RxJava2 integration + kotlinOptions.freeCompilerArgs += "-XXLanguage:-ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated" // Remove null assertions to get smaller bytecode on Android kotlinOptions.freeCompilerArgs += ["-Xno-param-assertions", "-Xno-receiver-assertions", "-Xno-call-assertions"] } @@ -241,22 +219,6 @@ if (build_snapshot_train) { } } -/* - * Hack to trick nmpp plugin: we are renaming artifacts in order to provide backward compatibility for dependencies, - * but publishing plugin does not re-read artifact names for kotlin-jvm projects, so renaming is not applied in pom files - * for JVM-only projects. - * - * We artificially replace "project" dependency with "module" one to have proper names in pom files, but then substitute it - * to have out "project" dependency back. - */ -configure(subprojects.findAll { it.name != coreModule && it.name != rootModule }) { - configurations.all { - resolutionStrategy.dependencySubstitution { - substitute module("org.jetbrains.kotlinx:kotlinx-coroutines-core:$version") with project(':kotlinx-coroutines-core') - } - } -} - // Redefine source sets because we are not using 'kotlin/main/fqn' folder convention configure(subprojects.findAll { !sourceless.contains(it.name) && @@ -335,4 +297,4 @@ if (jvm_ir_enabled) { enabled = enabled && jvm_ir_api_check_enabled } } -} \ No newline at end of file +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index adcbd90fe1..6c373a01f4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import java.util.* @@ -14,11 +14,9 @@ val buildSnapshotTrain = properties["build_snapshot_train"]?.toString()?.toBoole repositories { if (cacheRedirectorEnabled) { maven("https://cache-redirector.jetbrains.com/plugins.gradle.org/m2") - maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-eap") maven("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-dev") } else { maven("https://plugins.gradle.org/m2") - maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlin-dev") } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index a6da8fdbc1..c2e859f65d 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ pluginManagement { val build_snapshot_train: String? by settings diff --git a/buildSrc/src/main/kotlin/CacheRedirector.kt b/buildSrc/src/main/kotlin/CacheRedirector.kt index 7cf01d8e76..9f6efd2cdc 100644 --- a/buildSrc/src/main/kotlin/CacheRedirector.kt +++ b/buildSrc/src/main/kotlin/CacheRedirector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import org.gradle.api.* diff --git a/buildSrc/src/main/kotlin/Dokka.kt b/buildSrc/src/main/kotlin/Dokka.kt index dd5f1ea48d..f37aa7c151 100644 --- a/buildSrc/src/main/kotlin/Dokka.kt +++ b/buildSrc/src/main/kotlin/Dokka.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import org.gradle.api.Project diff --git a/buildSrc/src/main/kotlin/Idea.kt b/buildSrc/src/main/kotlin/Idea.kt index 615b8aad74..28b4aa555e 100644 --- a/buildSrc/src/main/kotlin/Idea.kt +++ b/buildSrc/src/main/kotlin/Idea.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + object Idea { @JvmStatic // for Gradle val active: Boolean diff --git a/buildSrc/src/main/kotlin/MavenCentral.kt b/buildSrc/src/main/kotlin/MavenCentral.kt deleted file mode 100644 index 3efaf33f1c..0000000000 --- a/buildSrc/src/main/kotlin/MavenCentral.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:Suppress("UnstableApiUsage") - -import org.gradle.api.Project -import org.gradle.api.publish.maven.MavenPom - -// Pom configuration - -fun MavenPom.configureMavenCentralMetadata(project: Project) { - name by project.name - description by "Coroutines support libraries for Kotlin" - url by "https://github.com/Kotlin/kotlinx.coroutines" - - licenses { - license { - name by "The Apache Software License, Version 2.0" - url by "https://www.apache.org/licenses/LICENSE-2.0.txt" - distribution by "repo" - } - } - - developers { - developer { - id by "JetBrains" - name by "JetBrains Team" - organization by "JetBrains" - organizationUrl by "https://www.jetbrains.com" - } - } - - scm { - url by "https://github.com/Kotlin/kotlinx.coroutines" - } -} diff --git a/buildSrc/src/main/kotlin/Platform.kt b/buildSrc/src/main/kotlin/Platform.kt index b667a138a8..f22c161b6e 100644 --- a/buildSrc/src/main/kotlin/Platform.kt +++ b/buildSrc/src/main/kotlin/Platform.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + import org.gradle.api.Project // Use from Groovy for now diff --git a/buildSrc/src/main/kotlin/Projects.kt b/buildSrc/src/main/kotlin/Projects.kt index 109311e876..dd284b6132 100644 --- a/buildSrc/src/main/kotlin/Projects.kt +++ b/buildSrc/src/main/kotlin/Projects.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + import org.gradle.api.Project fun Project.version(target: String): String = diff --git a/buildSrc/src/main/kotlin/Properties.kt b/buildSrc/src/main/kotlin/Properties.kt index a0968ee699..34314502fe 100644 --- a/buildSrc/src/main/kotlin/Properties.kt +++ b/buildSrc/src/main/kotlin/Properties.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UnstableApiUsage") diff --git a/buildSrc/src/main/kotlin/Publishing.kt b/buildSrc/src/main/kotlin/Publishing.kt new file mode 100644 index 0000000000..5b191bfa38 --- /dev/null +++ b/buildSrc/src/main/kotlin/Publishing.kt @@ -0,0 +1,93 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("UnstableApiUsage") + +import org.gradle.api.Project +import org.gradle.api.artifacts.dsl.* +import org.gradle.api.publish.maven.* +import org.gradle.plugins.signing.* +import java.net.* + +// Pom configuration + +fun MavenPom.configureMavenCentralMetadata(project: Project) { + name by project.name + description by "Coroutines support libraries for Kotlin" + url by "https://github.com/Kotlin/kotlinx.coroutines" + + licenses { + license { + name by "The Apache Software License, Version 2.0" + url by "https://www.apache.org/licenses/LICENSE-2.0.txt" + distribution by "repo" + } + } + + developers { + developer { + id by "JetBrains" + name by "JetBrains Team" + organization by "JetBrains" + organizationUrl by "https://www.jetbrains.com" + } + } + + scm { + url by "https://github.com/Kotlin/kotlinx.coroutines" + } +} + +fun mavenRepositoryUri(): URI { + // TODO -SNAPSHOT detection can be made here as well + val repositoryId: String? = System.getenv("libs.repository.id") + return if (repositoryId == null) { + // Using implicitly created staging, for MPP it's likely to be a mistake because + // publication on TeamCity will create 3 independent staging repositories + System.err.println("Warning: using an implicitly created staging for coroutines") + URI("https://oss.sonatype.org/service/local/staging/deploy/maven2/") + } else { + URI("https://oss.sonatype.org/service/local/staging/deployByRepositoryId/$repositoryId") + } +} + +fun configureMavenPublication(rh: RepositoryHandler, project: Project) { + rh.maven { + url = mavenRepositoryUri() + credentials { + username = project.getSensitiveProperty("libs.sonatype.user") + password = project.getSensitiveProperty("libs.sonatype.password") + } + } +} + +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") + val signingKeyPassphrase = project.getSensitiveProperty("libs.sign.passphrase") + if (!signingKey.isNullOrBlank()) { + project.extensions.configure("signing") { + useInMemoryPgpKeys(keyId, signingKey, signingKeyPassphrase) + sign(publication) + } + } +} + +private fun Project.getSensitiveProperty(name: String): String? { + return project.findProperty(name) as? String ?: System.getenv(name) +} diff --git a/buildSrc/src/main/kotlin/RunR8.kt b/buildSrc/src/main/kotlin/RunR8.kt index d9eba79bd4..b0fccf89fc 100644 --- a/buildSrc/src/main/kotlin/RunR8.kt +++ b/buildSrc/src/main/kotlin/RunR8.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.JavaExec diff --git a/buildSrc/src/main/kotlin/UnpackAar.kt b/buildSrc/src/main/kotlin/UnpackAar.kt index c7d0b53d04..b3152d7ab0 100644 --- a/buildSrc/src/main/kotlin/UnpackAar.kt +++ b/buildSrc/src/main/kotlin/UnpackAar.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs diff --git a/buildSrc/src/main/kotlin/jdk-convention.gradle.kts b/buildSrc/src/main/kotlin/jdk-convention.gradle.kts index 8bc1abf17d..64bd90dc31 100644 --- a/buildSrc/src/main/kotlin/jdk-convention.gradle.kts +++ b/buildSrc/src/main/kotlin/jdk-convention.gradle.kts @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + import org.gradle.api.JavaVersion if (!JavaVersion.current().isJava11Compatible) { diff --git a/buildSrc/src/main/kotlin/kotlin-js-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-js-conventions.gradle.kts new file mode 100644 index 0000000000..c1897ca749 --- /dev/null +++ b/buildSrc/src/main/kotlin/kotlin-js-conventions.gradle.kts @@ -0,0 +1,40 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// Platform-specific configuration to compile JS modules + +import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile + +plugins { + kotlin("js") +} + +dependencies { + testImplementation(kotlin("test-js")) +} + +kotlin { + js(LEGACY) { + moduleName = project.name.removeSuffix("-js") + } + + sourceSets { + main { + kotlin.srcDirs("src") + resources.srcDirs("resources") + } + test { + kotlin.srcDirs("test") + resources.srcDirs("test-resources") + } + } +} + +tasks.withType { + kotlinOptions { + moduleKind = "umd" + sourceMap = true + metaInfo = true + } +} diff --git a/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts new file mode 100644 index 0000000000..89007718c8 --- /dev/null +++ b/buildSrc/src/main/kotlin/kotlin-jvm-conventions.gradle.kts @@ -0,0 +1,46 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// Platform-specific configuration to compile JVM modules + +import org.gradle.api.* + +plugins { + kotlin("jvm") +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 +} + +if (rootProject.extra.get("jvm_ir_enabled") as Boolean) { + kotlin.target.compilations.configureEach { + kotlinOptions.useIR = true + } +} + +dependencies { + testCompile(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")}") +} + +tasks.compileKotlin { + kotlinOptions { + freeCompilerArgs += listOf("-Xexplicit-api=strict") + } +} + +tasks.withType { + testLogging { + showStandardStreams = true + events("passed", "failed") + } + val stressTest = project.properties["stressTest"] + if (stressTest != null) systemProperties["stressTest"] = stressTest +} diff --git a/bump-version.sh b/bump-version.sh index 00930cbd49..ae0fc0b02c 100755 --- a/bump-version.sh +++ b/bump-version.sh @@ -20,8 +20,6 @@ update_version "kotlinx-coroutines-core/README.md" update_version "kotlinx-coroutines-debug/README.md" update_version "kotlinx-coroutines-test/README.md" update_version "ui/coroutines-guide-ui.md" -update_version "ui/kotlinx-coroutines-android/example-app/gradle.properties" -update_version "ui/kotlinx-coroutines-android/animation-app/gradle.properties" update_version "gradle.properties" # Escape dots, e.g. 1.0.0 -> 1\.0\.0 diff --git a/docs/basics.md b/docs/basics.md index 424820383f..a18bf3dddb 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -1,3 +1,3 @@ The documentation has been moved to the [https://kotlinlang.org/docs/coroutines-basics.html](https://kotlinlang.org/docs/coroutines-basics.html) page. -To edit the documentation, open the [topics/coroutines-basics.md](topics/coroutines-basics.md) page. \ No newline at end of file +To edit the documentation, open the [topics/coroutines-basics.md](topics/coroutines-basics.md) page. diff --git a/docs/kc.tree b/docs/kc.tree index 6f726210c7..9cc0a28c5b 100644 --- a/docs/kc.tree +++ b/docs/kc.tree @@ -23,4 +23,4 @@ - \ No newline at end of file + diff --git a/docs/topics/debugging.md b/docs/topics/debugging.md index c0df045ed5..d18df7f465 100644 --- a/docs/topics/debugging.md +++ b/docs/topics/debugging.md @@ -46,6 +46,10 @@ It is easy to demonstrate with actual stacktraces of the same program that await The only downside of this approach is losing referential transparency of the exception. +> Note that suppressed exceptions are not copied and are left intact in the cause +> in order to prevent cycles in the exceptions chain, obscure`[CIRCULAR REFERENCE]` messages +> and even [crashes](https://jira.qos.ch/browse/LOGBACK-1027) in some frameworks + ### Stacktrace recovery machinery This section explains the inner mechanism of stacktrace recovery and can be skipped. diff --git a/docs/topics/knit.properties b/docs/topics/knit.properties index 7db4da66e6..562b4121b0 100644 --- a/docs/topics/knit.properties +++ b/docs/topics/knit.properties @@ -1,5 +1,5 @@ # -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # knit.package=kotlinx.coroutines.guide @@ -7,4 +7,3 @@ knit.dir=../../kotlinx-coroutines-core/jvm/test/guide/ test.package=kotlinx.coroutines.guide.test test.dir=../../kotlinx-coroutines-core/jvm/test/guide/test/ - diff --git a/gradle.properties b/gradle.properties index 9163cf5af1..40b1596105 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,27 +1,27 @@ # -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # # Kotlin -version=1.4.2-SNAPSHOT +version=1.4.3-SNAPSHOT group=org.jetbrains.kotlinx -kotlin_version=1.4.0 +kotlin_version=1.4.30 # Dependencies junit_version=4.12 -atomicfu_version=0.14.4 -knit_version=0.2.2 +atomicfu_version=0.15.1 +knit_version=0.2.3 html_version=0.6.8 -lincheck_version=2.7.1 +lincheck_version=2.10 dokka_version=0.9.16-rdev-2-mpp-hacks byte_buddy_version=1.10.9 -reactor_version=3.2.5.RELEASE +reactor_version=3.4.1 reactive_streams_version=1.0.2 rxjava2_version=2.2.8 rxjava3_version=3.0.2 javafx_version=11.0.2 javafx_plugin_version=0.0.8 -binary_compatibility_validator_version=0.2.2 +binary_compatibility_validator_version=0.4.0 blockhound_version=1.0.2.RELEASE jna_version=5.5.0 @@ -55,7 +55,7 @@ jekyll_version=4.0 org.gradle.jvmargs=-Xmx2g # Workaround for Bintray treating .sha512 files as artifacts -# https://github.com/gradle/gradle/issues/11412 +# https://github.com/gradle/gradle/issues/1.4.3 systemProp.org.gradle.internal.publish.checksums.insecure=true # todo:KLUDGE: This is commented out, and the property is set conditionally in build.gradle, because IDEA doesn't work with it. diff --git a/gradle/compile-common.gradle b/gradle/compile-common.gradle index 0dc1b5c014..6c3777b163 100644 --- a/gradle/compile-common.gradle +++ b/gradle/compile-common.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ kotlin.sourceSets { diff --git a/gradle/compile-js-multiplatform.gradle b/gradle/compile-js-multiplatform.gradle index b52cfc5230..1e885db0c5 100644 --- a/gradle/compile-js-multiplatform.gradle +++ b/gradle/compile-js-multiplatform.gradle @@ -1,23 +1,18 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply from: rootProject.file('gradle/node-js.gradle') kotlin { js { - // In 1.3.7x js() has not member `moduleName` - // In 1.4.x it has and allow to safety set compiler output file name and does not break test integration - if (it.hasProperty("moduleName")) { - moduleName = project.name - } + moduleName = project.name - // In 1.3.7x js() has not member `irTarget` // In 1.4.x it has in `both` and `legacy` mode and js() is of type `KotlinJsTarget` // `irTarget` is non-null in `both` mode // and contains appropriate `irTarget` with type `KotlinJsIrTarget` // `irTarget` is null in `legacy` mode - if (it.hasProperty("irTarget") && it.irTarget != null) { + if (it.irTarget != null) { irTarget.nodejs() irTarget.compilations['main']?.dependencies { api "org.jetbrains.kotlinx:atomicfu-js:$atomicfu_version" diff --git a/gradle/compile-js.gradle b/gradle/compile-js.gradle deleted file mode 100644 index 55c81fe56e..0000000000 --- a/gradle/compile-js.gradle +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -// Platform-specific configuration to compile JS modules - -apply plugin: 'org.jetbrains.kotlin.js' - -dependencies { - testImplementation "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version" -} - -kotlin { - js(LEGACY) { - moduleName = project.name - "-js" - } - - sourceSets { - main.kotlin.srcDirs = ['src'] - test.kotlin.srcDirs = ['test'] - main.resources.srcDirs = ['resources'] - test.resources.srcDirs = ['test-resources'] - } -} - -tasks.withType(compileKotlinJs.getClass()) { - kotlinOptions { - moduleKind = "umd" - sourceMap = true - metaInfo = true - } -} diff --git a/gradle/compile-jvm-multiplatform.gradle b/gradle/compile-jvm-multiplatform.gradle index 44b0cbedba..1f861f800c 100644 --- a/gradle/compile-jvm-multiplatform.gradle +++ b/gradle/compile-jvm-multiplatform.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ sourceCompatibility = 1.6 diff --git a/gradle/compile-jvm.gradle b/gradle/compile-jvm.gradle deleted file mode 100644 index bd2ae14775..0000000000 --- a/gradle/compile-jvm.gradle +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -// Platform-specific configuration to compile JVM modules - -apply plugin: 'org.jetbrains.kotlin.jvm' - -sourceCompatibility = 1.6 -targetCompatibility = 1.6 - -if (rootProject.ext.jvm_ir_enabled) { - kotlin.target.compilations.all { - kotlinOptions.useIR = true - } -} - -dependencies { - testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" - // Workaround to make addSuppressed work in tests - testCompile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" - testCompile "junit:junit:$junit_version" -} - -compileKotlin { - kotlinOptions { - freeCompilerArgs += ['-Xexplicit-api=strict'] - } -} - -tasks.withType(Test) { - testLogging { - showStandardStreams = true - events "passed", "failed" - } - def stressTest = project.properties['stressTest'] - if (stressTest != null) systemProperties['stressTest'] = stressTest -} diff --git a/gradle/compile-native-multiplatform.gradle b/gradle/compile-native-multiplatform.gradle index 4487446799..50ddf975f7 100644 --- a/gradle/compile-native-multiplatform.gradle +++ b/gradle/compile-native-multiplatform.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ project.ext.nativeMainSets = [] diff --git a/gradle/dokka.gradle b/gradle/dokka.gradle index 559ec8b668..f0cad15442 100644 --- a/gradle/dokka.gradle +++ b/gradle/dokka.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // Configures generation of JavaDoc & Dokka artifacts diff --git a/gradle/experimental.gradle b/gradle/experimental.gradle index b045a1f630..11aeb6d8a6 100644 --- a/gradle/experimental.gradle +++ b/gradle/experimental.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // For new mpp diff --git a/gradle/node-js.gradle b/gradle/node-js.gradle index d4bd86ca56..42f101c5f4 100644 --- a/gradle/node-js.gradle +++ b/gradle/node-js.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: 'com.moowork.node' diff --git a/gradle/publish-bintray.gradle b/gradle/publish-bintray.gradle index b36c79763d..e6f0423451 100644 --- a/gradle/publish-bintray.gradle +++ b/gradle/publish-bintray.gradle @@ -1,19 +1,19 @@ -import org.gradle.util.VersionNumber - /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +import org.gradle.util.VersionNumber + // Configures publishing of Maven artifacts to Bintray apply plugin: 'maven' apply plugin: 'maven-publish' +apply plugin: 'signing' // ------------- tasks def isMultiplatform = project.name == "kotlinx-coroutines-core" def isBom = project.name == "kotlinx-coroutines-bom" -def isKotlin137x = VersionNumber.parse(kotlin_version) <= VersionNumber.parse("1.3.79") if (!isBom) { apply plugin: "com.github.johnrengelman.shadow" @@ -37,16 +37,11 @@ if (!isMultiplatform && !isBom) { publishing { repositories { - maven { - def user = 'kotlin' - def repo = 'kotlinx' - def name = 'kotlinx.coroutines' - url = "https://api.bintray.com/maven/$user/$repo/$name/;publish=0" - - credentials { - username = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') - password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') - } + def bintrayUpload = System.getenv("libs.bintray.upload") != null + if (bintrayUpload) { + PublishingKt.configureBintrayPublication(delegate, project) + } else { + PublishingKt.configureMavenPublication(delegate, project) } } @@ -65,46 +60,32 @@ publishing { } publications.all { - MavenCentralKt.configureMavenCentralMetadata(pom, project) - + PublishingKt.configureMavenCentralMetadata(pom, project) + def bintrayUpload = System.getenv("libs.bintray.upload") != null + if (!bintrayUpload) { + PublishingKt.signPublicationIfKeyPresent(project, it) + } // add empty javadocs if (!isBom && it.name != "kotlinMultiplatform") { it.artifact(javadocJar) } - // Rename MPP artifacts for backward compatibility def type = it.name switch (type) { case 'kotlinMultiplatform': // With Kotlin 1.4 & HMPP, the root module should have no suffix in the ID, but for compatibility with // the consumers who can't read Gradle module metadata, we publish the JVM artifacts in it, too - it.artifactId = isKotlin137x ? "$project.name-native" : project.name - if (!isKotlin137x) { - apply from: "$rootDir/gradle/publish-mpp-root-module-in-platform.gradle" - publishPlatformArtifactsInRootModule(publications["jvm"]) - } + it.artifactId = project.name + apply from: "$rootDir/gradle/publish-mpp-root-module-in-platform.gradle" + publishPlatformArtifactsInRootModule(publications["jvm"]) break case 'metadata': - // As the old -common dependencies will fail to resolve with Gradle module metadata, rename the module - // to '*-metadata' so that the resolution failure are more clear - it.artifactId = isKotlin137x ? "$project.name-common" : "$project.name-metadata" - break case 'jvm': - it.artifactId = isKotlin137x ? project.name : "$project.name-jvm" - break case 'js': case 'native': it.artifactId = "$project.name-$type" break } - // Hierarchical project structures are not fully supported in 1.3.7x MPP - if (isKotlin137x) { - // disable metadata everywhere, but in native and js modules - if (type == 'maven' || type == 'metadata' || type == 'jvm') { - moduleDescriptorGenerator = null - } - } - } } @@ -112,12 +93,5 @@ tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication"}. dependsOn(tasks["generatePomFileForJvmPublication"]) } -task publishDevelopSnapshot() { - def branch = System.getenv('currentBranch') - if (branch == "develop") { - dependsOn(":publish") - } -} - // Compatibility with old TeamCity configurations that perform :kotlinx-coroutines-core:bintrayUpload task bintrayUpload(dependsOn: publish) diff --git a/gradle/publish-mpp-root-module-in-platform.gradle b/gradle/publish-mpp-root-module-in-platform.gradle index 8bc0b502db..8036bea030 100644 --- a/gradle/publish-mpp-root-module-in-platform.gradle +++ b/gradle/publish-mpp-root-module-in-platform.gradle @@ -1,39 +1,42 @@ /* - * Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -/* - * Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module metadata - * can still get the platform artifact and transitive dependencies from the POM. - * - * See the full rationale here https://youtrack.jetbrains.com/issue/KMM-237#focus=streamItem-27-4115233.0-0 - */ -project.ext.publishPlatformArtifactsInRootModule = { platformPublication -> - def platformPomBuilder = null +/** Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module + metadata can still get the platform artifact and transitive dependencies from the POM: */ +project.ext.publishPlatformArtifactsInRootModule = { MavenPublication platformPublication -> - platformPublication.pom.withXml { platformPomBuilder = asString() } + XmlProvider platformXml = null - publishing.publications.kotlinMultiplatform { - platformPublication.artifacts.forEach { - artifact(it) - } + platformPublication.pom.withXml { platformXml = it } + publishing.publications.kotlinMultiplatform { pom.withXml { - def pomStringBuilder = asString() - pomStringBuilder.setLength(0) - // The platform POM needs its artifact ID replaced with the artifact ID of the root module: - def platformPomString = platformPomBuilder.toString() - platformPomString.eachLine { line -> - if (!line.contains(" + [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html + + [future]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-guava/kotlinx.coroutines.guava/kotlinx.coroutines.-coroutine-scope/future.html [com.google.common.util.concurrent.ListenableFuture]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-guava/kotlinx.coroutines.guava/com.google.common.util.concurrent.-listenable-future/index.html [com.google.common.util.concurrent.ListenableFuture.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-guava/kotlinx.coroutines.guava/com.google.common.util.concurrent.-listenable-future/await.html [kotlinx.coroutines.Deferred.asListenableFuture]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-guava/kotlinx.coroutines.guava/kotlinx.coroutines.-deferred/as-listenable-future.html + diff --git a/integration/kotlinx-coroutines-guava/build.gradle.kts b/integration/kotlinx-coroutines-guava/build.gradle.kts index 53e91add44..12a6ca70b7 100644 --- a/integration/kotlinx-coroutines-guava/build.gradle.kts +++ b/integration/kotlinx-coroutines-guava/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ val guavaVersion = "28.0-jre" diff --git a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt index 6d1fab3d69..53019c4bbe 100644 --- a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt +++ b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.guava @@ -302,7 +302,8 @@ private class ListenableFutureCoroutine( ) : AbstractCoroutine(context) { // JobListenableFuture propagates external cancellation to `this` coroutine. See JobListenableFuture. - @JvmField val future = JobListenableFuture(this) + @JvmField + val future = JobListenableFuture(this) override fun onCompleted(value: T) { future.complete(value) @@ -347,6 +348,17 @@ private class JobListenableFuture(private val jobToCancel: Job): ListenableFu */ private val auxFuture = SettableFuture.create() + /** + * `true` if [auxFuture.get][ListenableFuture.get] throws [ExecutionException]. + * + * Note: this is eventually consistent with the state of [auxFuture]. + * + * Unfortunately, there's no API to figure out if [ListenableFuture] throws [ExecutionException] + * apart from calling [ListenableFuture.get] on it. To avoid unnecessary [ExecutionException] allocation + * we use this field as an optimization. + */ + private var auxFutureIsFailed: Boolean = false + /** * When the attached coroutine [isCompleted][Job.isCompleted] successfully * its outcome should be passed to this method. @@ -366,7 +378,8 @@ private class JobListenableFuture(private val jobToCancel: Job): ListenableFu // CancellationException is wrapped into `Cancelled` to preserve original cause and message. // All the other exceptions are delegated to SettableFuture.setException. fun completeExceptionallyOrCancel(t: Throwable): Boolean = - if (t is CancellationException) auxFuture.set(Cancelled(t)) else auxFuture.setException(t) + if (t is CancellationException) auxFuture.set(Cancelled(t)) + else auxFuture.setException(t).also { if (it) auxFutureIsFailed = true } /** * Returns cancellation _in the sense of [Future]_. This is _not_ equivalent to @@ -385,7 +398,16 @@ private class JobListenableFuture(private val jobToCancel: Job): ListenableFu // this Future hasn't itself been successfully cancelled, the Future will return // isCancelled() == false. This is the only discovered way to reconcile the two different // cancellation contracts. - return auxFuture.isCancelled || (isDone && Uninterruptibles.getUninterruptibly(auxFuture) is Cancelled) + return auxFuture.isCancelled || isDone && !auxFutureIsFailed && try { + Uninterruptibles.getUninterruptibly(auxFuture) is Cancelled + } catch (e: CancellationException) { + // `auxFuture` got cancelled right after `auxFuture.isCancelled` returned false. + true + } catch (e: ExecutionException) { + // `auxFutureIsFailed` hasn't been updated yet. + auxFutureIsFailed = true + false + } } /** @@ -455,7 +477,7 @@ private class JobListenableFuture(private val jobToCancel: Job): ListenableFu try { when (val result = Uninterruptibles.getUninterruptibly(auxFuture)) { is Cancelled -> append("CANCELLED, cause=[${result.exception}]") - else -> append("SUCCESS, result=[$result") + else -> append("SUCCESS, result=[$result]") } } catch (e: CancellationException) { // `this` future was cancelled by `Future.cancel`. In this case there's no cause or message. @@ -469,6 +491,7 @@ private class JobListenableFuture(private val jobToCancel: Job): ListenableFu } else { append("PENDING, delegate=[$auxFuture]") } + append(']') } } diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt index dc2d99d7f7..9dca9e9b46 100644 --- a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt +++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt @@ -680,6 +680,50 @@ class ListenableFutureTest : TestBase() { finish(5) } + @Test + fun testFutureCompletedExceptionally() = runTest { + val testException = TestException() + // NonCancellable to not propagate error to this scope. + val future = future(context = NonCancellable) { + throw testException + } + yield() + assertTrue(future.isDone) + assertFalse(future.isCancelled) + val thrown = assertFailsWith { future.get() } + assertEquals(testException, thrown.cause) + } + + @Test + fun testAsListenableFutureCompletedExceptionally() = runTest { + val testException = TestException() + val deferred = CompletableDeferred().apply { + completeExceptionally(testException) + } + val asListenableFuture = deferred.asListenableFuture() + assertTrue(asListenableFuture.isDone) + assertFalse(asListenableFuture.isCancelled) + val thrown = assertFailsWith { asListenableFuture.get() } + assertEquals(testException, thrown.cause) + } + + @Test + fun stressTestJobListenableFutureIsCancelledDoesNotThrow() = runTest { + repeat(1000) { + val deferred = CompletableDeferred() + val asListenableFuture = deferred.asListenableFuture() + // We heed two threads to test a race condition. + withContext(Dispatchers.Default) { + val cancellationJob = launch { + asListenableFuture.cancel(false) + } + while (!cancellationJob.isCompleted) { + asListenableFuture.isCancelled // Shouldn't throw. + } + } + } + } + private inline fun ListenableFuture<*>.checkFutureException() { val e = assertFailsWith { get() } val cause = e.cause!! diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt new file mode 100644 index 0000000000..13ac299088 --- /dev/null +++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.guava + +import kotlinx.coroutines.* +import org.junit.Test +import kotlin.test.* + +class ListenableFutureToStringTest : TestBase() { + @Test + fun testSuccessfulFuture() = runTest { + val deferred = CompletableDeferred("OK") + val succeededFuture = deferred.asListenableFuture() + val toString = succeededFuture.toString() + assertTrue(message = "Unexpected format: $toString") { + toString.matches(Regex("""kotlinx\.coroutines\.guava\.JobListenableFuture@[^\[]*\[status=SUCCESS, result=\[OK]]""")) + } + } + + @Test + fun testFailedFuture() = runTest { + val exception = TestRuntimeException("test") + val deferred = CompletableDeferred().apply { + completeExceptionally(exception) + } + val failedFuture = deferred.asListenableFuture() + val toString = failedFuture.toString() + assertTrue(message = "Unexpected format: $toString") { + toString.matches(Regex("""kotlinx\.coroutines\.guava\.JobListenableFuture@[^\[]*\[status=FAILURE, cause=\[$exception]]""")) + } + } + + @Test + fun testPendingFuture() = runTest { + val deferred = CompletableDeferred() + val pendingFuture = deferred.asListenableFuture() + val toString = pendingFuture.toString() + assertTrue(message = "Unexpected format: $toString") { + toString.matches(Regex("""kotlinx\.coroutines\.guava\.JobListenableFuture@[^\[]*\[status=PENDING, delegate=\[.*]]""")) + } + } + + @Test + fun testCancelledCoroutineAsListenableFuture() = runTest { + val exception = CancellationException("test") + val deferred = CompletableDeferred().apply { + cancel(exception) + } + val cancelledFuture = deferred.asListenableFuture() + val toString = cancelledFuture.toString() + assertTrue(message = "Unexpected format: $toString") { + toString.matches(Regex("""kotlinx\.coroutines\.guava\.JobListenableFuture@[^\[]*\[status=CANCELLED, cause=\[$exception]]""")) + } + } + + @Test + fun testCancelledFuture() = runTest { + val deferred = CompletableDeferred() + val cancelledFuture = deferred.asListenableFuture().apply { + cancel(false) + } + val toString = cancelledFuture.toString() + assertTrue(message = "Unexpected format: $toString") { + toString.matches(Regex("""kotlinx\.coroutines\.guava\.JobListenableFuture@[^\[]*\[status=CANCELLED]""")) + } + } +} diff --git a/integration/kotlinx-coroutines-jdk8/README.md b/integration/kotlinx-coroutines-jdk8/README.md index 3a204416bf..aebd90f06a 100644 --- a/integration/kotlinx-coroutines-jdk8/README.md +++ b/integration/kotlinx-coroutines-jdk8/README.md @@ -53,12 +53,16 @@ Integration with JDK8 [CompletableFuture] (Android API level 24). + [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html + + [future]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/kotlinx.coroutines.-coroutine-scope/future.html [java.util.concurrent.CompletionStage.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/java.util.concurrent.-completion-stage/await.html [java.util.concurrent.CompletionStage.asDeferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/java.util.concurrent.-completion-stage/as-deferred.html [kotlinx.coroutines.Deferred.asCompletableFuture]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-jdk8/kotlinx.coroutines.future/kotlinx.coroutines.-deferred/as-completable-future.html + diff --git a/integration/kotlinx-coroutines-jdk8/build.gradle.kts b/integration/kotlinx-coroutines-jdk8/build.gradle.kts index 099159292e..791bd95024 100644 --- a/integration/kotlinx-coroutines-jdk8/build.gradle.kts +++ b/integration/kotlinx-coroutines-jdk8/build.gradle.kts @@ -1,4 +1,4 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ diff --git a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt index f7fdba5f69..b3b45e9dbc 100644 --- a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt +++ b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.future @@ -105,16 +105,19 @@ private fun Job.setupCancellation(future: CompletableFuture<*>) { } /** - * Converts this completion stage to an instance of [Deferred]. - * When this completion stage is an instance of [Future], then it is cancelled when - * the resulting deferred is cancelled. + * Converts this [CompletionStage] to an instance of [Deferred]. + * + * The [CompletableFuture] that corresponds to this [CompletionStage] (see [CompletionStage.toCompletableFuture]) + * is cancelled when the resulting deferred is cancelled. */ +@Suppress("DeferredIsResult") public fun CompletionStage.asDeferred(): Deferred { + val future = toCompletableFuture() // retrieve the future // Fast path if already completed - if (this is Future<*> && isDone()){ + if (future.isDone) { return try { @Suppress("UNCHECKED_CAST") - CompletableDeferred(get() as T) + CompletableDeferred(future.get() as T) } catch (e: Throwable) { // unwrap original cause from ExecutionException val original = (e as? ExecutionException)?.cause ?: e @@ -132,25 +135,28 @@ public fun CompletionStage.asDeferred(): Deferred { result.completeExceptionally((exception as? CompletionException)?.cause ?: exception) } } - if (this is Future<*>) result.cancelFutureOnCompletion(this) + result.cancelFutureOnCompletion(future) return result } /** - * Awaits for completion of the completion stage without blocking a thread. + * Awaits for completion of [CompletionStage] without blocking a thread. * * This suspending function is cancellable. * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function * stops waiting for the completion stage and immediately resumes with [CancellationException][kotlinx.coroutines.CancellationException]. - * This method is intended to be used with one-shot futures, so on coroutine cancellation completion stage is cancelled as well if it is instance of [CompletableFuture]. - * If cancelling given stage is undesired, `stage.asDeferred().await()` should be used instead. + * + * This method is intended to be used with one-shot futures, so on coroutine cancellation the [CompletableFuture] that + * corresponds to this [CompletionStage] (see [CompletionStage.toCompletableFuture]) + * is cancelled. If cancelling the given stage is undesired, `stage.asDeferred().await()` should be used instead. */ public suspend fun CompletionStage.await(): T { + val future = toCompletableFuture() // retrieve the future // fast path when CompletableFuture is already done (does not suspend) - if (this is Future<*> && isDone()) { + if (future.isDone) { try { - @Suppress("UNCHECKED_CAST") - return get() as T + @Suppress("UNCHECKED_CAST", "BlockingMethodInNonBlockingContext") + return future.get() as T } catch (e: ExecutionException) { throw e.cause ?: e // unwrap original cause from ExecutionException } @@ -160,8 +166,7 @@ public suspend fun CompletionStage.await(): T { val consumer = ContinuationConsumer(cont) whenComplete(consumer) cont.invokeOnCancellation { - // mayInterruptIfRunning is not used - (this as? CompletableFuture)?.cancel(false) + future.cancel(false) consumer.cont = null // shall clear reference to continuation to aid GC } } diff --git a/integration/kotlinx-coroutines-jdk8/src/stream/Stream.kt b/integration/kotlinx-coroutines-jdk8/src/stream/Stream.kt index 641a83a682..1d804e5950 100644 --- a/integration/kotlinx-coroutines-jdk8/src/stream/Stream.kt +++ b/integration/kotlinx-coroutines-jdk8/src/stream/Stream.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.stream diff --git a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt index acff1d21cb..78cf6e5305 100644 --- a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt +++ b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:OptIn(ExperimentalContracts::class) diff --git a/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt b/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt index f75c96746c..998aaa0835 100644 --- a/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt +++ b/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt @@ -490,4 +490,81 @@ class FutureTest : TestBase() { } } } + + /** + * https://github.com/Kotlin/kotlinx.coroutines/issues/2456 + */ + @Test + fun testCompletedStageAwait() = runTest { + val stage = CompletableFuture.completedStage("OK") + assertEquals("OK", stage.await()) + } + + /** + * https://github.com/Kotlin/kotlinx.coroutines/issues/2456 + */ + @Test + fun testCompletedStageAsDeferredAwait() = runTest { + val stage = CompletableFuture.completedStage("OK") + val deferred = stage.asDeferred() + assertEquals("OK", deferred.await()) + } + + @Test + fun testCompletedStateThenApplyAwait() = runTest { + expect(1) + val cf = CompletableFuture() + launch { + expect(3) + cf.complete("O") + } + expect(2) + val stage = cf.thenApply { it + "K" } + assertEquals("OK", stage.await()) + finish(4) + } + + @Test + fun testCompletedStateThenApplyAwaitCancel() = runTest { + expect(1) + val cf = CompletableFuture() + launch { + expect(3) + cf.cancel(false) + } + expect(2) + val stage = cf.thenApply { it + "K" } + assertFailsWith { stage.await() } + finish(4) + } + + @Test + fun testCompletedStateThenApplyAsDeferredAwait() = runTest { + expect(1) + val cf = CompletableFuture() + launch { + expect(3) + cf.complete("O") + } + expect(2) + val stage = cf.thenApply { it + "K" } + val deferred = stage.asDeferred() + assertEquals("OK", deferred.await()) + finish(4) + } + + @Test + fun testCompletedStateThenApplyAsDeferredAwaitCancel() = runTest { + expect(1) + val cf = CompletableFuture() + expect(2) + val stage = cf.thenApply { it + "K" } + val deferred = stage.asDeferred() + launch { + expect(3) + deferred.cancel() // cancel the deferred! + } + assertFailsWith { stage.await() } + finish(4) + } } diff --git a/integration/kotlinx-coroutines-play-services/build.gradle b/integration/kotlinx-coroutines-play-services/build.gradle deleted file mode 100644 index 29ce3d606f..0000000000 --- a/integration/kotlinx-coroutines-play-services/build.gradle +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -ext.tasks_version = '16.0.1' - -def artifactType = Attribute.of("artifactType", String) -def unpackedAar = Attribute.of("unpackedAar", Boolean) - -configurations.all { - afterEvaluate { - if (canBeResolved) { - attributes.attribute(unpackedAar, true) // request all AARs to be unpacked - } - } -} - -dependencies { - attributesSchema { - attribute(unpackedAar) - } - - artifactTypes { - aar { - attributes.attribute(unpackedAar, false) - } - } - - registerTransform(UnpackAar) { - from.attribute(unpackedAar, false).attribute(artifactType, "aar") - to.attribute(unpackedAar, true).attribute(artifactType, "jar") - } - - api("com.google.android.gms:play-services-tasks:$tasks_version") { - exclude group: 'com.android.support' - } -} - -tasks.withType(dokka.getClass()) { - externalDocumentationLink { - url = new URL("https://developers.google.com/android/reference/") - // This is workaround for missing package list in Google API - packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL() - } -} diff --git a/integration/kotlinx-coroutines-play-services/build.gradle.kts b/integration/kotlinx-coroutines-play-services/build.gradle.kts new file mode 100644 index 0000000000..59f3b0bd5a --- /dev/null +++ b/integration/kotlinx-coroutines-play-services/build.gradle.kts @@ -0,0 +1,41 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +val tasksVersion = "16.0.1" + +val artifactType = Attribute.of("artifactType", String::class.java) +val unpackedAar = Attribute.of("unpackedAar", Boolean::class.javaObjectType) + +configurations.configureEach { + afterEvaluate { + if (isCanBeResolved) { + attributes.attribute(unpackedAar, true) // request all AARs to be unpacked + } + } +} + +dependencies { + attributesSchema { + attribute(unpackedAar) + } + + artifactTypes { + create("aar") { + attributes.attribute(unpackedAar, false) + } + } + + registerTransform(UnpackAar::class.java) { + from.attribute(unpackedAar, false).attribute(artifactType, "aar") + to.attribute(unpackedAar, true).attribute(artifactType, "jar") + } + + api("com.google.android.gms:play-services-tasks:$tasksVersion") { + exclude(group="com.android.support") + } +} + +externalDocumentationLink( + url = "https://developers.google.com/android/reference/" +) diff --git a/integration/kotlinx-coroutines-play-services/src/Tasks.kt b/integration/kotlinx-coroutines-play-services/src/Tasks.kt index f9b9a60419..d89d1aec7c 100644 --- a/integration/kotlinx-coroutines-play-services/src/Tasks.kt +++ b/integration/kotlinx-coroutines-play-services/src/Tasks.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("RedundantVisibilityModifier") diff --git a/integration/kotlinx-coroutines-slf4j/README.md b/integration/kotlinx-coroutines-slf4j/README.md index ee5fb320e9..e23d390703 100644 --- a/integration/kotlinx-coroutines-slf4j/README.md +++ b/integration/kotlinx-coroutines-slf4j/README.md @@ -20,5 +20,7 @@ Integration with SLF4J [MDC](https://logback.qos.ch/manual/mdc.html). + [MDCContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-slf4j/kotlinx.coroutines.slf4j/-m-d-c-context/index.html + diff --git a/integration/kotlinx-coroutines-slf4j/build.gradle.kts b/integration/kotlinx-coroutines-slf4j/build.gradle.kts index c7d0d82d62..a341eefe13 100644 --- a/integration/kotlinx-coroutines-slf4j/build.gradle.kts +++ b/integration/kotlinx-coroutines-slf4j/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ dependencies { diff --git a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt index 078800d0ee..9528f2b22d 100644 --- a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt +++ b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.slf4j diff --git a/js/example-frontend-js/build.gradle b/js/example-frontend-js/build.gradle deleted file mode 100644 index 7abde63964..0000000000 --- a/js/example-frontend-js/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -project.kotlin { - js(LEGACY) { - binaries.executable() - browser { - distribution { - directory = new File(directory.parentFile, "dist") - } - webpackTask { - cssSupport.enabled = true - } - runTask { - cssSupport.enabled = true - } - testTask { - useKarma { - useChromeHeadless() - webpackConfig.cssSupport.enabled = true - } - } - } - } - - sourceSets { - main.dependencies { - implementation "org.jetbrains.kotlinx:kotlinx-html-js:$html_version" - implementation(npm("html-webpack-plugin", "3.2.0")) - } - } -} diff --git a/js/example-frontend-js/build.gradle.kts b/js/example-frontend-js/build.gradle.kts new file mode 100644 index 0000000000..5b18966fcd --- /dev/null +++ b/js/example-frontend-js/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +kotlin { + js(LEGACY) { + binaries.executable() + browser { + distribution { + directory = directory.parentFile.resolve("dist") + } + commonWebpackConfig { + cssSupport.enabled = true + } + testTask { + useKarma { + useChromeHeadless() + } + } + } + } +} + +dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-html-js:${version("html")}") + implementation(devNpm("html-webpack-plugin", "3.2.0")) +} diff --git a/js/example-frontend-js/src/ExampleMain.kt b/js/example-frontend-js/src/ExampleMain.kt index da6e4196a6..d4e530b04a 100644 --- a/js/example-frontend-js/src/ExampleMain.kt +++ b/js/example-frontend-js/src/ExampleMain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import kotlinx.coroutines.* diff --git a/js/example-frontend-js/src/main/web/style.css b/js/example-frontend-js/src/main/web/style.css index 31d0ebc058..e2e777a576 100644 --- a/js/example-frontend-js/src/main/web/style.css +++ b/js/example-frontend-js/src/main/web/style.css @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ #scene { diff --git a/js/js-stub/build.gradle.kts b/js/js-stub/build.gradle.kts index 6b9d65555a..201ac43cb0 100644 --- a/js/js-stub/build.gradle.kts +++ b/js/js-stub/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile diff --git a/js/js-stub/src/Performance.kt b/js/js-stub/src/Performance.kt index 0b85c93df0..eefb1d749b 100644 --- a/js/js-stub/src/Performance.kt +++ b/js/js-stub/src/Performance.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package org.w3c.performance diff --git a/js/js-stub/src/Promise.kt b/js/js-stub/src/Promise.kt index 7413a872be..243d0c9e33 100644 --- a/js/js-stub/src/Promise.kt +++ b/js/js-stub/src/Promise.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin.js diff --git a/js/js-stub/src/Window.kt b/js/js-stub/src/Window.kt index f54ed0d7bb..8b2bb8000b 100644 --- a/js/js-stub/src/Window.kt +++ b/js/js-stub/src/Window.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package org.w3c.dom diff --git a/knit.properties b/knit.properties index bc177ce44c..45b2216db4 100644 --- a/knit.properties +++ b/knit.properties @@ -1,5 +1,5 @@ # -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # knit.include=docs/knit.code.include @@ -13,4 +13,4 @@ test.mode.FLEXIBLE_TIME=verifyLinesFlexibleTime test.mode.FLEXIBLE_THREAD=verifyLinesFlexibleThread test.mode.LINES_START_UNORDERED=verifyLinesStartUnordered test.mode.LINES_START=verifyLinesStart -test.mode.EXCEPTION=verifyExceptions \ No newline at end of file +test.mode.EXCEPTION=verifyExceptions diff --git a/kotlinx-coroutines-bom/build.gradle b/kotlinx-coroutines-bom/build.gradle index e39c9229c9..ef87f3f760 100644 --- a/kotlinx-coroutines-bom/build.gradle +++ b/kotlinx-coroutines-bom/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ plugins { id 'java-platform' diff --git a/kotlinx-coroutines-core/README.md b/kotlinx-coroutines-core/README.md index 5fe3298173..bc5587623a 100644 --- a/kotlinx-coroutines-core/README.md +++ b/kotlinx-coroutines-core/README.md @@ -90,6 +90,7 @@ Obsolete and deprecated module to test coroutines. Replaced with `kotlinx-corout + [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html @@ -114,12 +115,16 @@ Obsolete and deprecated module to test coroutines. Replaced with `kotlinx-corout [Job.isCompleted]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/is-completed.html [Deferred.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/await.html [Deferred.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/on-await.html + + [kotlinx.coroutines.sync.Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html [kotlinx.coroutines.sync.Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/lock.html [kotlinx.coroutines.sync.Mutex.onLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/on-lock.html [kotlinx.coroutines.sync.Mutex.tryLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/try-lock.html + + [kotlinx.coroutines.channels.produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html [kotlinx.coroutines.channels.ReceiveChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/index.html [kotlinx.coroutines.channels.ProducerScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-producer-scope/index.html @@ -133,8 +138,11 @@ Obsolete and deprecated module to test coroutines. Replaced with `kotlinx-corout [kotlinx.coroutines.channels.ReceiveChannel.poll]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/poll.html [kotlinx.coroutines.channels.receiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/receive-or-null.html [kotlinx.coroutines.channels.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/on-receive-or-null.html + + [kotlinx.coroutines.selects.select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html [kotlinx.coroutines.selects.SelectBuilder.onTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/-select-builder/on-timeout.html + diff --git a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api index dcd837f7b2..1d16d31086 100644 --- a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api +++ b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api @@ -270,7 +270,7 @@ public final class kotlinx/coroutines/Delay$DefaultImpls { public final class kotlinx/coroutines/DelayKt { public static final fun awaitCancellation (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun delay (JLkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun delay-p9JZ4hM (DLkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun delay-VtjQ1oo (DLkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class kotlinx/coroutines/Dispatchers { @@ -535,9 +535,9 @@ public final class kotlinx/coroutines/TimeoutCancellationException : java/util/c public final class kotlinx/coroutines/TimeoutKt { public static final fun withTimeout (JLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withTimeout-lwyi7ZQ (DLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withTimeout-KLykuaI (DLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun withTimeoutOrNull (JLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withTimeoutOrNull-lwyi7ZQ (DLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withTimeoutOrNull-KLykuaI (DLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class kotlinx/coroutines/YieldKt { @@ -796,7 +796,7 @@ public abstract interface class kotlinx/coroutines/channels/ReceiveChannel { public abstract fun iterator ()Lkotlinx/coroutines/channels/ChannelIterator; public abstract fun poll ()Ljava/lang/Object; public abstract fun receive (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun receiveOrClosed-ZYPwvRU (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun receiveOrClosed-WVj179g (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun receiveOrNull (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -861,10 +861,6 @@ public final class kotlinx/coroutines/debug/internal/DebugCoroutineInfo { public final fun lastObservedStackTrace ()Ljava/util/List; } -public synthetic class kotlinx/coroutines/debug/internal/DebugProbesImplSequenceNumberRefVolatile { - public fun (J)V -} - public final class kotlinx/coroutines/debug/internal/DebuggerInfo : java/io/Serializable { public fun (Lkotlinx/coroutines/debug/internal/DebugCoroutineInfoImpl;Lkotlin/coroutines/CoroutineContext;)V public final fun getCoroutineId ()Ljava/lang/Long; @@ -943,7 +939,7 @@ public final class kotlinx/coroutines/flow/FlowKt { public static final fun count (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun debounce (Lkotlinx/coroutines/flow/Flow;J)Lkotlinx/coroutines/flow/Flow; public static final fun debounce (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; - public static final fun debounce-8GFy2Ro (Lkotlinx/coroutines/flow/Flow;D)Lkotlinx/coroutines/flow/Flow; + public static final fun debounce-HG0u8IE (Lkotlinx/coroutines/flow/Flow;D)Lkotlinx/coroutines/flow/Flow; public static final fun debounceDuration (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; public static final fun delayEach (Lkotlinx/coroutines/flow/Flow;J)Lkotlinx/coroutines/flow/Flow; public static final fun delayFlow (Lkotlinx/coroutines/flow/Flow;J)Lkotlinx/coroutines/flow/Flow; @@ -1019,7 +1015,7 @@ public final class kotlinx/coroutines/flow/FlowKt { public static final fun retryWhen (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function4;)Lkotlinx/coroutines/flow/Flow; public static final fun runningReduce (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow; public static final fun sample (Lkotlinx/coroutines/flow/Flow;J)Lkotlinx/coroutines/flow/Flow; - public static final fun sample-8GFy2Ro (Lkotlinx/coroutines/flow/Flow;D)Lkotlinx/coroutines/flow/Flow; + public static final fun sample-HG0u8IE (Lkotlinx/coroutines/flow/Flow;D)Lkotlinx/coroutines/flow/Flow; public static final fun scan (Lkotlinx/coroutines/flow/Flow;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow; public static final fun scanFold (Lkotlinx/coroutines/flow/Flow;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow; public static final fun scanReduce (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;)Lkotlinx/coroutines/flow/Flow; @@ -1106,8 +1102,8 @@ public final class kotlinx/coroutines/flow/SharingStarted$Companion { } public final class kotlinx/coroutines/flow/SharingStartedKt { - public static final fun WhileSubscribed-9tZugJw (Lkotlinx/coroutines/flow/SharingStarted$Companion;DD)Lkotlinx/coroutines/flow/SharingStarted; - public static synthetic fun WhileSubscribed-9tZugJw$default (Lkotlinx/coroutines/flow/SharingStarted$Companion;DDILjava/lang/Object;)Lkotlinx/coroutines/flow/SharingStarted; + public static final fun WhileSubscribed-5qebJ5I (Lkotlinx/coroutines/flow/SharingStarted$Companion;DD)Lkotlinx/coroutines/flow/SharingStarted; + public static synthetic fun WhileSubscribed-5qebJ5I$default (Lkotlinx/coroutines/flow/SharingStarted$Companion;DDILjava/lang/Object;)Lkotlinx/coroutines/flow/SharingStarted; } public abstract interface class kotlinx/coroutines/flow/StateFlow : kotlinx/coroutines/flow/SharedFlow { @@ -1238,7 +1234,7 @@ public abstract interface class kotlinx/coroutines/selects/SelectInstance { } public final class kotlinx/coroutines/selects/SelectKt { - public static final fun onTimeout-0lHKgQg (Lkotlinx/coroutines/selects/SelectBuilder;DLkotlin/jvm/functions/Function1;)V + public static final fun onTimeout-8Mi8wO0 (Lkotlinx/coroutines/selects/SelectBuilder;DLkotlin/jvm/functions/Function1;)V public static final fun select (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index 314eea350b..c2a57f9d9e 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: 'org.jetbrains.kotlin.multiplatform' @@ -184,13 +184,22 @@ jvmTest { minHeapSize = '1g' maxHeapSize = '1g' enableAssertions = true - systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager' + if (!Idea.active) { + // We should not set this security manager when `jvmTest` + // is invoked by IntelliJ IDEA since we need to pass + // system properties for Lincheck and stress tests. + // TODO Remove once IDEA is smart enough to select between `jvmTest`/`jvmStressTest`/`jvmLincheckTest` #KTIJ-599 + systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager' + } // 'stress' is required to be able to run all subpackage tests like ":jvmTests --tests "*channels*" -Pstress=true" if (!Idea.active && rootProject.properties['stress'] == null) { + exclude '**/*LincheckTest.*' exclude '**/*StressTest.*' } - systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test - + if (Idea.active) { + // Configure the IDEA runner for Lincheck + configureJvmForLincheck(jvmTest) + } // TODO: JVM IR generates different stacktrace so temporary disable stacktrace tests if (rootProject.ext.jvm_ir_enabled) { filter { @@ -219,23 +228,41 @@ task jvmStressTest(type: Test, dependsOn: compileTestKotlinJvm) { systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '10' } +task jvmLincheckTest(type: Test, dependsOn: compileTestKotlinJvm) { + classpath = files { jvmTest.classpath } + testClassesDirs = files { jvmTest.testClassesDirs } + include '**/*LincheckTest.*' + enableAssertions = true + testLogging.showStandardStreams = true + configureJvmForLincheck(jvmLincheckTest) +} + +static void configureJvmForLincheck(task) { + task.minHeapSize = '1g' + task.maxHeapSize = '6g' // we may need more space for building an interleaving tree in the model checking mode + task.jvmArgs = ['--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED', // required for transformation + '--add-exports', 'java.base/jdk.internal.util=ALL-UNNAMED'] // in the model checking mode + task.systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '2' + task.systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '1' // better for the model checking mode +} + task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) { classpath = files { jvmTest.classpath } testClassesDirs = files { jvmTest.testClassesDirs } executable = "$System.env.JDK_16/bin/java" exclude '**/*LFStressTest.*' // lock-freedom tests use LockFreedomTestEnvironment which needs JDK8 - exclude '**/*LCStressTest.*' // lin-check tests use LinChecker which needs JDK8 + exclude '**/*LincheckTest.*' // Lincheck tests use LinChecker which needs JDK8 exclude '**/exceptions/**' // exceptions tests check suppressed exception which needs JDK8 exclude '**/ExceptionsGuideTest.*' exclude '**/RunInterruptibleStressTest.*' // fails on JDK 1.6 due to JDK bug } -// Run these tests only during nightly stress test +// Run jdk16Test test only during nightly stress test jdk16Test.onlyIf { project.properties['stressTest'] != null } -// Always run those tests -task moreTest(dependsOn: [jvmStressTest, jdk16Test]) -build.dependsOn moreTest +// Always check additional test sets +task moreTest(dependsOn: [jvmStressTest, jvmLincheckTest, jdk16Test]) +check.dependsOn moreTest task testsJar(type: Jar, dependsOn: jvmTestClasses) { classifier = 'tests' diff --git a/kotlinx-coroutines-core/common/README.md b/kotlinx-coroutines-core/common/README.md index e59392ee66..6712648ae8 100644 --- a/kotlinx-coroutines-core/common/README.md +++ b/kotlinx-coroutines-core/common/README.md @@ -97,6 +97,7 @@ Low-level primitives for finer-grained control of coroutines. + [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html @@ -125,12 +126,16 @@ Low-level primitives for finer-grained control of coroutines. [Deferred.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/on-await.html [newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/new-coroutine-context.html [DEBUG_PROPERTY_NAME]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-d-e-b-u-g_-p-r-o-p-e-r-t-y_-n-a-m-e.html + + [kotlinx.coroutines.sync.Mutex]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/index.html [kotlinx.coroutines.sync.Mutex.lock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/lock.html [kotlinx.coroutines.sync.Mutex.onLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/on-lock.html [kotlinx.coroutines.sync.Mutex.tryLock]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/try-lock.html + + [kotlinx.coroutines.channels.produce]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/produce.html [kotlinx.coroutines.channels.ReceiveChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/index.html [kotlinx.coroutines.channels.ProducerScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-producer-scope/index.html @@ -146,9 +151,14 @@ Low-level primitives for finer-grained control of coroutines. [kotlinx.coroutines.channels.ReceiveChannel.poll]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/poll.html [kotlinx.coroutines.channels.receiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/receive-or-null.html [kotlinx.coroutines.channels.onReceiveOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/on-receive-or-null.html + + [kotlinx.coroutines.selects.select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html [kotlinx.coroutines.selects.SelectBuilder.onTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/-select-builder/on-timeout.html + + [kotlinx.coroutines.test.TestCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.test/-test-coroutine-context/index.html + diff --git a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt index 742c9670b7..af392b63f5 100644 --- a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("DEPRECATION_ERROR") diff --git a/kotlinx-coroutines-core/common/src/Annotations.kt b/kotlinx-coroutines-core/common/src/Annotations.kt index 5475c6b10e..70adad9b97 100644 --- a/kotlinx-coroutines-core/common/src/Annotations.kt +++ b/kotlinx-coroutines-core/common/src/Annotations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Await.kt b/kotlinx-coroutines-core/common/src/Await.kt index 7189349024..e06ed33025 100644 --- a/kotlinx-coroutines-core/common/src/Await.kt +++ b/kotlinx-coroutines-core/common/src/Await.kt @@ -1,11 +1,10 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines import kotlinx.atomicfu.* -import kotlinx.coroutines.channels.* import kotlin.coroutines.* /** @@ -75,7 +74,7 @@ private class AwaitAll(private val deferreds: Array>) { val nodes = Array(deferreds.size) { i -> val deferred = deferreds[i] deferred.start() // To properly await lazily started deferreds - AwaitAllNode(cont, deferred).apply { + AwaitAllNode(cont).apply { handle = deferred.invokeOnCompletion(asHandler) } } @@ -101,7 +100,7 @@ private class AwaitAll(private val deferreds: Array>) { override fun toString(): String = "DisposeHandlersOnCancel[$nodes]" } - private inner class AwaitAllNode(private val continuation: CancellableContinuation>, job: Job) : JobNode(job) { + private inner class AwaitAllNode(private val continuation: CancellableContinuation>) : JobNode() { lateinit var handle: DisposableHandle private val _disposer = atomic(null) diff --git a/kotlinx-coroutines-core/common/src/Builders.common.kt b/kotlinx-coroutines-core/common/src/Builders.common.kt index 6ef1a8daea..93b3ee4849 100644 --- a/kotlinx-coroutines-core/common/src/Builders.common.kt +++ b/kotlinx-coroutines-core/common/src/Builders.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -207,25 +207,17 @@ private class LazyStandaloneCoroutine( } // Used by withContext when context changes, but dispatcher stays the same -private class UndispatchedCoroutine( +internal expect class UndispatchedCoroutine( context: CoroutineContext, uCont: Continuation -) : ScopeCoroutine(context, uCont) { - override fun afterResume(state: Any?) { - // resume undispatched -- update context by stay on the same dispatcher - val result = recoverResult(state, uCont) - withCoroutineContext(uCont.context, null) { - uCont.resumeWith(result) - } - } -} +) : ScopeCoroutine private const val UNDECIDED = 0 private const val SUSPENDED = 1 private const val RESUMED = 2 // Used by withContext when context dispatcher changes -private class DispatchedCoroutine( +internal class DispatchedCoroutine( context: CoroutineContext, uCont: Continuation ) : ScopeCoroutine(context, uCont) { diff --git a/kotlinx-coroutines-core/common/src/CancellableContinuation.kt b/kotlinx-coroutines-core/common/src/CancellableContinuation.kt index 7d9315afbf..8f589912a0 100644 --- a/kotlinx-coroutines-core/common/src/CancellableContinuation.kt +++ b/kotlinx-coroutines-core/common/src/CancellableContinuation.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt index cdb1b78882..1a8f35663a 100644 --- a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt +++ b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -85,6 +85,13 @@ internal open class CancellableContinuationImpl( public override val isCancelled: Boolean get() = state is CancelledContinuation + // We cannot invoke `state.toString()` since it may cause a circular dependency + private val stateDebugRepresentation get() = when(state) { + is NotCompleted -> "Active" + is CancelledContinuation -> "Cancelled" + else -> "Completed" + } + public override fun initCancellability() { setupCancellation() } @@ -122,7 +129,7 @@ internal open class CancellableContinuationImpl( val parent = delegate.context[Job] ?: return // fast path 3 -- don't do anything without parent val handle = parent.invokeOnCompletion( onCancelling = true, - handler = ChildContinuation(parent, this).asHandler + handler = ChildContinuation(this).asHandler ) parentHandle = handle // now check our state _after_ registering (could have completed while we were registering) @@ -503,7 +510,7 @@ internal open class CancellableContinuationImpl( // For nicer debugging public override fun toString(): String = - "${nameString()}(${delegate.toDebugString()}){$state}@$hexAddress" + "${nameString()}(${delegate.toDebugString()}){$stateDebugRepresentation}@$hexAddress" protected open fun nameString(): String = "CancellableContinuation" diff --git a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt index 2f00847298..c80737968e 100644 --- a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt +++ b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("DEPRECATION_ERROR") diff --git a/kotlinx-coroutines-core/common/src/CompletableJob.kt b/kotlinx-coroutines-core/common/src/CompletableJob.kt index 74a92e36e5..f986d78760 100644 --- a/kotlinx-coroutines-core/common/src/CompletableJob.kt +++ b/kotlinx-coroutines-core/common/src/CompletableJob.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt b/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt index bf6900087d..e712ff1fc1 100644 --- a/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt +++ b/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CompletionState.kt b/kotlinx-coroutines-core/common/src/CompletionState.kt index f09aa3ccd9..b9042874cd 100644 --- a/kotlinx-coroutines-core/common/src/CompletionState.kt +++ b/kotlinx-coroutines-core/common/src/CompletionState.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt b/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt index 51374603c3..68b4b1a393 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -19,5 +19,6 @@ internal expect val DefaultDelay: Delay // countOrElement -- pre-cached value for ThreadContext.kt internal expect inline fun withCoroutineContext(context: CoroutineContext, countOrElement: Any?, block: () -> T): T +internal expect inline fun withContinuationContext(continuation: Continuation<*>, countOrElement: Any?, block: () -> T): T internal expect fun Continuation<*>.toDebugString(): String internal expect val CoroutineContext.coroutineName: String? diff --git a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt index ab1e814b8a..b2b887988d 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt b/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt index b49a6faa35..49923a92e7 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CoroutineName.kt b/kotlinx-coroutines-core/common/src/CoroutineName.kt index 7f09a5897c..dc3f1c0cea 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineName.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineName.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/CoroutineScope.kt b/kotlinx-coroutines-core/common/src/CoroutineScope.kt index 0dde6c9352..e7c243a42d 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineScope.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineScope.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:OptIn(ExperimentalContracts::class) diff --git a/kotlinx-coroutines-core/common/src/CoroutineStart.kt b/kotlinx-coroutines-core/common/src/CoroutineStart.kt index d5791c79fe..6059829c23 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineStart.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineStart.kt @@ -1,7 +1,6 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE") package kotlinx.coroutines import kotlinx.coroutines.CoroutineStart.* @@ -59,8 +58,8 @@ public enum class CoroutineStart { ATOMIC, /** - * Immediately executes the coroutine until its first suspension point _in the current thread_ as if the - * coroutine was started using [Dispatchers.Unconfined]. However, when the coroutine is resumed from suspension + * Immediately executes the coroutine until its first suspension point _in the current thread_ similarly to + * the coroutine being started using [Dispatchers.Unconfined]. However, when the coroutine is resumed from suspension * it is dispatched according to the [CoroutineDispatcher] in its context. * * This is similar to [ATOMIC] in the sense that coroutine starts executing even if it was already cancelled, @@ -69,9 +68,11 @@ public enum class CoroutineStart { * Cancellability of coroutine at suspension points depends on the particular implementation details of * suspending functions as in [DEFAULT]. * - * **Note: This is an experimental api.** Execution semantics of coroutines may change in the future when this mode is used. + * ### Unconfined event loop + * + * Unlike [Dispatchers.Unconfined] and [MainCoroutineDispatcher.immediate], nested undispatched coroutines do not form + * an event loop that otherwise prevents potential stack overflow in case of unlimited nesting. */ - @ExperimentalCoroutinesApi // Since 1.0.0, no ETA on stability UNDISPATCHED; /** diff --git a/kotlinx-coroutines-core/common/src/Debug.common.kt b/kotlinx-coroutines-core/common/src/Debug.common.kt index 949b05c63f..1381ecd882 100644 --- a/kotlinx-coroutines-core/common/src/Debug.common.kt +++ b/kotlinx-coroutines-core/common/src/Debug.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -35,6 +35,7 @@ public interface CopyableThrowable where T : Throwable, T : CopyableThrowable * For better debuggability, it is recommended to use original exception as [cause][Throwable.cause] of the resulting one. * Stacktrace of copied exception will be overwritten by stacktrace recovery machinery by [Throwable.setStackTrace] call. * An exception can opt-out of copying by returning `null` from this function. + * Suppressed exceptions of the original exception should not be copied in order to avoid circular exceptions. */ public fun createCopy(): T? } diff --git a/kotlinx-coroutines-core/common/src/Deferred.kt b/kotlinx-coroutines-core/common/src/Deferred.kt index ff996756a3..595700e2c7 100644 --- a/kotlinx-coroutines-core/common/src/Deferred.kt +++ b/kotlinx-coroutines-core/common/src/Deferred.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Delay.kt b/kotlinx-coroutines-core/common/src/Delay.kt index aae623d5df..53dadf9730 100644 --- a/kotlinx-coroutines-core/common/src/Delay.kt +++ b/kotlinx-coroutines-core/common/src/Delay.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Dispatchers.common.kt b/kotlinx-coroutines-core/common/src/Dispatchers.common.kt index dba57abc88..8681b182d8 100644 --- a/kotlinx-coroutines-core/common/src/Dispatchers.common.kt +++ b/kotlinx-coroutines-core/common/src/Dispatchers.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/EventLoop.common.kt b/kotlinx-coroutines-core/common/src/EventLoop.common.kt index 69ea9fe312..e6a57c927a 100644 --- a/kotlinx-coroutines-core/common/src/EventLoop.common.kt +++ b/kotlinx-coroutines-core/common/src/EventLoop.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Exceptions.common.kt b/kotlinx-coroutines-core/common/src/Exceptions.common.kt index 64f8911e9d..6d5442dfdc 100644 --- a/kotlinx-coroutines-core/common/src/Exceptions.common.kt +++ b/kotlinx-coroutines-core/common/src/Exceptions.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt index 2e05635a29..31e2ef22b2 100644 --- a/kotlinx-coroutines-core/common/src/Job.kt +++ b/kotlinx-coroutines-core/common/src/Job.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -490,7 +490,7 @@ public interface ChildHandle : DisposableHandle { * ``` */ internal fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle = - invokeOnCompletion(handler = DisposeOnCompletion(this, handle).asHandler) + invokeOnCompletion(handler = DisposeOnCompletion(handle).asHandler) /** * Cancels the job and suspends the invoking coroutine until the cancelled job is complete. diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index 5f21299e58..5b516ae27f 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("DEPRECATION_ERROR") @@ -287,7 +287,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren // fast-path method to finalize normally completed coroutines without children // returns true if complete, and afterCompletion(update) shall be called private fun tryFinalizeSimpleState(state: Incomplete, update: Any?): Boolean { - assert { state is Empty || state is JobNode<*> } // only simple state without lists where children can concurrently add + assert { state is Empty || state is JobNode } // only simple state without lists where children can concurrently add assert { update !is CompletedExceptionally } // only for normal completion if (!_state.compareAndSet(state, update.boxIncomplete())) return false onCancelling(null) // simple state is not a failure @@ -313,7 +313,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * 2) Invoke completion handlers: .join(), callbacks etc. * It's important to invoke them only AFTER exception handling and everything else, see #208 */ - if (state is JobNode<*>) { // SINGLE/SINGLE+ state -- one completion handler (common case) + if (state is JobNode) { // SINGLE/SINGLE+ state -- one completion handler (common case) try { state.invoke(cause) } catch (ex: Throwable) { @@ -327,7 +327,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren private fun notifyCancelling(list: NodeList, cause: Throwable) { // first cancel our own children onCancelling(cause) - notifyHandlers>(list, cause) + notifyHandlers(list, cause) // then cancel parent cancelParent(cause) // tentative cancellation -- does not matter if there is no parent } @@ -359,9 +359,9 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } private fun NodeList.notifyCompletion(cause: Throwable?) = - notifyHandlers>(this, cause) + notifyHandlers(this, cause) - private inline fun > notifyHandlers(list: NodeList, cause: Throwable?) { + private inline fun notifyHandlers(list: NodeList, cause: Throwable?) { var exception: Throwable? = null list.forEach { node -> try { @@ -453,13 +453,14 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren invokeImmediately: Boolean, handler: CompletionHandler ): DisposableHandle { - var nodeCache: JobNode<*>? = null + // Create node upfront -- for common cases it just initializes JobNode.job field, + // for user-defined handlers it allocates a JobNode object that we might not need, but this is Ok. + val node: JobNode = makeNode(handler, onCancelling) loopOnState { state -> when (state) { is Empty -> { // EMPTY_X state -- no completion handlers if (state.isActive) { // try move to SINGLE state - val node = nodeCache ?: makeNode(handler, onCancelling).also { nodeCache = it } if (_state.compareAndSet(state, node)) return node } else promoteEmptyToNodeList(state) // that way we can add listener for non-active coroutine @@ -467,7 +468,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren is Incomplete -> { val list = state.list if (list == null) { // SINGLE/SINGLE+ - promoteSingleToNodeList(state as JobNode<*>) + promoteSingleToNodeList(state as JobNode) } else { var rootCause: Throwable? = null var handle: DisposableHandle = NonDisposableHandle @@ -479,7 +480,6 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren // or we are adding a child to a coroutine that is not completing yet if (rootCause == null || handler.isHandlerOf() && !state.isCompleting) { // Note: add node the list while holding lock on state (make sure it cannot change) - val node = nodeCache ?: makeNode(handler, onCancelling).also { nodeCache = it } if (!addLastAtomic(state, list, node)) return@loopOnState // retry // just return node if we don't have to invoke handler (not cancelling yet) if (rootCause == null) return node @@ -493,7 +493,6 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren if (invokeImmediately) handler.invokeIt(rootCause) return handle } else { - val node = nodeCache ?: makeNode(handler, onCancelling).also { nodeCache = it } if (addLastAtomic(state, list, node)) return node } } @@ -508,16 +507,20 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } } - private fun makeNode(handler: CompletionHandler, onCancelling: Boolean): JobNode<*> { - return if (onCancelling) - (handler as? JobCancellingNode<*>)?.also { assert { it.job === this } } - ?: InvokeOnCancelling(this, handler) - else - (handler as? JobNode<*>)?.also { assert { it.job === this && it !is JobCancellingNode } } - ?: InvokeOnCompletion(this, handler) + private fun makeNode(handler: CompletionHandler, onCancelling: Boolean): JobNode { + val node = if (onCancelling) { + (handler as? JobCancellingNode) + ?: InvokeOnCancelling(handler) + } else { + (handler as? JobNode) + ?.also { assert { it !is JobCancellingNode } } + ?: InvokeOnCompletion(handler) + } + node.job = this + return node } - private fun addLastAtomic(expect: Any, list: NodeList, node: JobNode<*>) = + private fun addLastAtomic(expect: Any, list: NodeList, node: JobNode) = list.addLastIf(node) { this.state === expect } private fun promoteEmptyToNodeList(state: Empty) { @@ -527,7 +530,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren _state.compareAndSet(state, update) } - private fun promoteSingleToNodeList(state: JobNode<*>) { + private fun promoteSingleToNodeList(state: JobNode) { // try to promote it to list (SINGLE+ state) state.addOneIfEmpty(NodeList()) // it must be in SINGLE+ state or state has changed (node could have need removed from state) @@ -553,7 +556,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren private suspend fun joinSuspend() = suspendCancellableCoroutine { cont -> // We have to invoke join() handler only on cancellation, on completion we will be resumed regularly without handlers - cont.disposeOnCancellation(invokeOnCompletion(handler = ResumeOnCompletion(this, cont).asHandler)) + cont.disposeOnCancellation(invokeOnCompletion(handler = ResumeOnCompletion(cont).asHandler)) } public final override val onJoin: SelectClause0 @@ -573,7 +576,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } if (startInternal(state) == 0) { // slow-path -- register waiter for completion - select.disposeOnSelect(invokeOnCompletion(handler = SelectJoinOnCompletion(this, select, block).asHandler)) + select.disposeOnSelect(invokeOnCompletion(handler = SelectJoinOnCompletion(select, block).asHandler)) return } } @@ -582,11 +585,11 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren /** * @suppress **This is unstable API and it is subject to change.** */ - internal fun removeNode(node: JobNode<*>) { + internal fun removeNode(node: JobNode) { // remove logic depends on the state of the job loopOnState { state -> when (state) { - is JobNode<*> -> { // SINGE/SINGLE+ state -- one completion handler + is JobNode -> { // SINGE/SINGLE+ state -- one completion handler if (state !== node) return // a different job node --> we were already removed // try remove and revert back to empty state if (_state.compareAndSet(state, EMPTY_ACTIVE)) return @@ -770,7 +773,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren private fun getOrPromoteCancellingList(state: Incomplete): NodeList? = state.list ?: when (state) { is Empty -> NodeList() // we can allocate new empty list that'll get integrated into Cancelling state - is JobNode<*> -> { + is JobNode -> { // SINGLE/SINGLE+ must be promoted to NodeList first, because otherwise we cannot // correctly capture a reference to it promoteSingleToNodeList(state) @@ -849,7 +852,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * Otherwise, there can be a race between (completed state -> handled exception and newly attached child/join) * which may miss unhandled exception. */ - if ((state is Empty || state is JobNode<*>) && state !is ChildHandleNode && proposedUpdate !is CompletedExceptionally) { + if ((state is Empty || state is JobNode) && state !is ChildHandleNode && proposedUpdate !is CompletedExceptionally) { if (tryFinalizeSimpleState(state, proposedUpdate)) { // Completed successfully on fast path -- return updated state return proposedUpdate @@ -964,7 +967,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * If child is attached when the job is already being cancelled, such child will receive immediate notification on * cancellation, but parent *will* wait for that child before completion and will handle its exception. */ - return invokeOnCompletion(onCancelling = true, handler = ChildHandleNode(this, child).asHandler) as ChildHandle + return invokeOnCompletion(onCancelling = true, handler = ChildHandleNode(child).asHandler) as ChildHandle } /** @@ -1147,7 +1150,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren private val state: Finishing, private val child: ChildHandleNode, private val proposedUpdate: Any? - ) : JobNode(child.childJob) { + ) : JobNode() { override fun invoke(cause: Throwable?) { parent.continueCompleting(state, child, proposedUpdate) } @@ -1225,7 +1228,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * thrown and not a JobCancellationException. */ val cont = AwaitContinuation(uCont.intercepted(), this) - cont.disposeOnCancellation(invokeOnCompletion(ResumeAwaitOnCompletion(this, cont).asHandler)) + cont.disposeOnCancellation(invokeOnCompletion(ResumeAwaitOnCompletion(cont).asHandler)) cont.getResult() } @@ -1252,7 +1255,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } if (startInternal(state) == 0) { // slow-path -- register waiter for completion - select.disposeOnSelect(invokeOnCompletion(handler = SelectAwaitOnCompletion(this, select, block).asHandler)) + select.disposeOnSelect(invokeOnCompletion(handler = SelectAwaitOnCompletion(select, block).asHandler)) return } } @@ -1342,12 +1345,14 @@ internal interface Incomplete { val list: NodeList? // is null only for Empty and JobNode incomplete state objects } -internal abstract class JobNode( - @JvmField val job: J -) : CompletionHandlerBase(), DisposableHandle, Incomplete { +internal abstract class JobNode : CompletionHandlerBase(), DisposableHandle, Incomplete { + /** + * Initialized by [JobSupport.makeNode]. + */ + lateinit var job: JobSupport override val isActive: Boolean get() = true override val list: NodeList? get() = null - override fun dispose() = (job as JobSupport).removeNode(this) + override fun dispose() = job.removeNode(this) override fun toString() = "$classSimpleName@$hexAddress[job@${job.hexAddress}]" } @@ -1360,7 +1365,7 @@ internal class NodeList : LockFreeLinkedListHead(), Incomplete { append(state) append("}[") var first = true - this@NodeList.forEach> { node -> + this@NodeList.forEach { node -> if (first) first = false else append(", ") append(node) } @@ -1379,23 +1384,20 @@ internal class InactiveNodeList( } private class InvokeOnCompletion( - job: Job, private val handler: CompletionHandler -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) = handler.invoke(cause) } private class ResumeOnCompletion( - job: Job, private val continuation: Continuation -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) = continuation.resume(Unit) } private class ResumeAwaitOnCompletion( - job: JobSupport, private val continuation: CancellableContinuationImpl -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) { val state = job.state assert { state !is Incomplete } @@ -1411,17 +1413,15 @@ private class ResumeAwaitOnCompletion( } internal class DisposeOnCompletion( - job: Job, private val handle: DisposableHandle -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) = handle.dispose() } private class SelectJoinOnCompletion( - job: JobSupport, private val select: SelectInstance, private val block: suspend () -> R -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) { if (select.trySelect()) block.startCoroutineCancellable(select.completion) @@ -1429,10 +1429,9 @@ private class SelectJoinOnCompletion( } private class SelectAwaitOnCompletion( - job: JobSupport, private val select: SelectInstance, private val block: suspend (T) -> R -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) { if (select.trySelect()) job.selectAwaitCompletion(select, block) @@ -1445,12 +1444,11 @@ private class SelectAwaitOnCompletion( * Marker for node that shall be invoked on in _cancelling_ state. * **Note: may be invoked multiple times.** */ -internal abstract class JobCancellingNode(job: J) : JobNode(job) +internal abstract class JobCancellingNode : JobNode() private class InvokeOnCancelling( - job: Job, private val handler: CompletionHandler -) : JobCancellingNode(job) { +) : JobCancellingNode() { // delegate handler shall be invoked at most once, so here is an additional flag private val _invoked = atomic(0) // todo: replace with atomic boolean after migration to recent atomicFu override fun invoke(cause: Throwable?) { @@ -1459,18 +1457,16 @@ private class InvokeOnCancelling( } internal class ChildHandleNode( - parent: JobSupport, @JvmField val childJob: ChildJob -) : JobCancellingNode(parent), ChildHandle { +) : JobCancellingNode(), ChildHandle { override fun invoke(cause: Throwable?) = childJob.parentCancelled(job) override fun childCancelled(cause: Throwable): Boolean = job.childCancelled(cause) } // Same as ChildHandleNode, but for cancellable continuation internal class ChildContinuation( - parent: Job, @JvmField val child: CancellableContinuationImpl<*> -) : JobCancellingNode(parent) { +) : JobCancellingNode() { override fun invoke(cause: Throwable?) { child.parentCancelled(child.getContinuationCancellationCause(job)) } diff --git a/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt index daba38f0fd..602da6e0b5 100644 --- a/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt +++ b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/NonCancellable.kt b/kotlinx-coroutines-core/common/src/NonCancellable.kt index 45803cf945..a9c68f090a 100644 --- a/kotlinx-coroutines-core/common/src/NonCancellable.kt +++ b/kotlinx-coroutines-core/common/src/NonCancellable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("DEPRECATION_ERROR") diff --git a/kotlinx-coroutines-core/common/src/Runnable.common.kt b/kotlinx-coroutines-core/common/src/Runnable.common.kt index 692c700b50..5a7f6678a4 100644 --- a/kotlinx-coroutines-core/common/src/Runnable.common.kt +++ b/kotlinx-coroutines-core/common/src/Runnable.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt b/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt index dbdf45ead5..45e2542b20 100644 --- a/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt +++ b/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Supervisor.kt b/kotlinx-coroutines-core/common/src/Supervisor.kt index 542e4fef48..01a8e70522 100644 --- a/kotlinx-coroutines-core/common/src/Supervisor.kt +++ b/kotlinx-coroutines-core/common/src/Supervisor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:OptIn(ExperimentalContracts::class) @file:Suppress("DEPRECATION_ERROR") diff --git a/kotlinx-coroutines-core/common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt index 4bfff118e8..264a2b9d1b 100644 --- a/kotlinx-coroutines-core/common/src/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/Timeout.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:OptIn(ExperimentalContracts::class) diff --git a/kotlinx-coroutines-core/common/src/Unconfined.kt b/kotlinx-coroutines-core/common/src/Unconfined.kt index a0997a51d3..4f48645895 100644 --- a/kotlinx-coroutines-core/common/src/Unconfined.kt +++ b/kotlinx-coroutines-core/common/src/Unconfined.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/common/src/Yield.kt b/kotlinx-coroutines-core/common/src/Yield.kt index 0d8bd3bc2f..975a48935c 100644 --- a/kotlinx-coroutines-core/common/src/Yield.kt +++ b/kotlinx-coroutines-core/common/src/Yield.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -9,7 +9,8 @@ import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* /** - * Yields the thread (or thread pool) of the current coroutine dispatcher to other coroutines to run if possible. + * Yields the thread (or thread pool) of the current coroutine dispatcher + * to other coroutines on the same dispatcher to run if possible. * * This suspending function is cancellable. * If the [Job] of the current coroutine is cancelled or completed when this suspending function is invoked or while diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt index 87bd43714d..9721583e83 100644 --- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -477,7 +477,14 @@ internal abstract class AbstractSendChannel( override val pollResult: Any? get() = element override fun tryResumeSend(otherOp: PrepareOp?): Symbol? = RESUME_TOKEN.also { otherOp?.finishPrepare() } override fun completeResumeSend() {} - override fun resumeSendClosed(closed: Closed<*>) {} + + /** + * This method should be never called, see special logic in [LinkedListChannel.onCancelIdempotentList]. + */ + override fun resumeSendClosed(closed: Closed<*>) { + assert { false } + } + override fun toString(): String = "SendBuffered@$hexAddress($element)" } } @@ -635,7 +642,13 @@ internal abstract class AbstractChannel( cancelInternal(cause) final override fun cancel(cause: CancellationException?) { - if (isClosedForReceive) return // Do not create an exception if channel is already cancelled + /* + * Do not create an exception if channel is already cancelled. + * Channel is closed for receive when either it is cancelled (then we are free to bail out) + * or was closed and elements were received. + * Then `onCancelIdempotent` does nothing for all implementations. + */ + if (isClosedForReceive) return cancelInternal(cause ?: CancellationException("$classSimpleName was cancelled")) } @@ -669,6 +682,13 @@ internal abstract class AbstractChannel( // Add to the list only **after** successful removal list += previous as Send } + onCancelIdempotentList(list, closed) + } + + /** + * This method is overridden by [LinkedListChannel] to handle cancellation of [SendBuffered] elements from the list. + */ + protected open fun onCancelIdempotentList(list: InlineList, closed: Closed<*>) { list.forEachReversed { it.resumeSendClosed(closed) } } diff --git a/kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt index 91b5473c41..600eb6a951 100644 --- a/kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt index 80cb8aa011..4569ec72fa 100644 --- a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -298,7 +298,7 @@ internal open class ArrayChannel( } // then clean all queued senders super.onCancelIdempotent(wasClosed) - undeliveredElementException?.let { throw it } // throw cancel exception at the end if there was one + undeliveredElementException?.let { throw it } // throw UndeliveredElementException at the end if there was one } // ------ debug ------ diff --git a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt index 0193ed06b2..07e7597627 100644 --- a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt +++ b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt index d356566f17..6cd79373b2 100644 --- a/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("FunctionName") diff --git a/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt b/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt index a89c633fe6..48b89ce6fe 100644 --- a/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt +++ b/kotlinx-coroutines-core/common/src/channels/BufferOverflow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 196739e114..b8b81aac53 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("FunctionName") diff --git a/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt index 9ceb77ddc2..b2b257def2 100644 --- a/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -26,7 +26,7 @@ internal open class ChannelCoroutine( } final override fun cancel(cause: CancellationException?) { - if (isClosedForReceive) return // Do not create an exception if channel is already cancelled + if (isCancelled) return // Do not create an exception if the coroutine (-> the channel) is already cancelled cancelInternal(cause ?: defaultCancellationException()) } diff --git a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt index 398d5ca44b..e3567e3107 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt @@ -1,14 +1,16 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @file:JvmName("ChannelsKt") @file:Suppress("DEPRECATION_ERROR") +@file:OptIn(ExperimentalContracts::class) package kotlinx.coroutines.channels import kotlinx.coroutines.* import kotlinx.coroutines.selects.* +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.jvm.* @@ -88,6 +90,19 @@ public suspend inline fun BroadcastChannel.consumeEach(action: (E) -> Uni // -------- Operations on ReceiveChannel -------- +/** + * Returns a [List] containing all elements. + * + * The operation is _terminal_. + * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel]. + */ +@OptIn(ExperimentalStdlibApi::class) +public suspend fun ReceiveChannel.toList(): List = buildList { + consumeEach { + add(it) + } +} + /** * Returns a [CompletionHandler] that invokes [cancel][ReceiveChannel.cancel] on the [ReceiveChannel] * with the corresponding cause. See also [ReceiveChannel.consume]. @@ -151,6 +166,9 @@ public fun consumesAll(vararg channels: ReceiveChannel<*>): CompletionHandler = * The operation is _terminal_. */ public inline fun ReceiveChannel.consume(block: ReceiveChannel.() -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } var cause: Throwable? = null try { return block() @@ -1189,15 +1207,6 @@ public suspend fun > ReceiveChannel.toCollecti return destination } -/** - * Returns a [List] containing all elements. - * - * The operation is _terminal_. - * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel]. - */ -public suspend fun ReceiveChannel.toList(): List = - this.toMutableList() - /** * Returns a [Map] filled with all elements of this channel. * diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt index 5986dae3d4..f1d092e34b 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt index 75e421c6e7..0e686447c1 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -120,7 +120,7 @@ internal open class ConflatedChannel(onUndeliveredElement: OnUndeliveredEleme undeliveredElementException = updateValueLocked(EMPTY) } super.onCancelIdempotent(wasClosed) - undeliveredElementException?.let { throw it } // throw exception at the end if there was one + undeliveredElementException?.let { throw it } // throw UndeliveredElementException at the end if there was one } private fun updateValueLocked(element: Any?): UndeliveredElementException? { diff --git a/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt b/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt index 2f46421344..831752739c 100644 --- a/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -58,5 +58,19 @@ internal open class LinkedListChannel(onUndeliveredElement: OnUndeliveredElem } } } + + override fun onCancelIdempotentList(list: InlineList, closed: Closed<*>) { + var undeliveredElementException: UndeliveredElementException? = null + list.forEachReversed { + when (it) { + is SendBuffered<*> -> { + @Suppress("UNCHECKED_CAST") + undeliveredElementException = onUndeliveredElement?.callUndeliveredElementCatchingException(it.element as E, undeliveredElementException) + } + else -> it.resumeSendClosed(closed) + } + } + undeliveredElementException?.let { throw it } // throw UndeliveredElementException at the end if there was one + } } diff --git a/kotlinx-coroutines-core/common/src/channels/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt index 10a15e2a93..3c183587f3 100644 --- a/kotlinx-coroutines-core/common/src/channels/Produce.kt +++ b/kotlinx-coroutines-core/common/src/channels/Produce.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/common/src/channels/RendezvousChannel.kt b/kotlinx-coroutines-core/common/src/channels/RendezvousChannel.kt index 857a97938f..e8ade513f5 100644 --- a/kotlinx-coroutines-core/common/src/channels/RendezvousChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/RendezvousChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/common/src/flow/Builders.kt b/kotlinx-coroutines-core/common/src/flow/Builders.kt index 7d84cd2105..10dd3aefb2 100644 --- a/kotlinx-coroutines-core/common/src/flow/Builders.kt +++ b/kotlinx-coroutines-core/common/src/flow/Builders.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/Channels.kt b/kotlinx-coroutines-core/common/src/flow/Channels.kt index 63b285abc3..e883c3b468 100644 --- a/kotlinx-coroutines-core/common/src/flow/Channels.kt +++ b/kotlinx-coroutines-core/common/src/flow/Channels.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/Flow.kt b/kotlinx-coroutines-core/common/src/flow/Flow.kt index dd56d2d80d..0ccd343ead 100644 --- a/kotlinx-coroutines-core/common/src/flow/Flow.kt +++ b/kotlinx-coroutines-core/common/src/flow/Flow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow diff --git a/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt b/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt index 8c6208bfd2..d1c1565cb0 100644 --- a/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt +++ b/kotlinx-coroutines-core/common/src/flow/FlowCollector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow diff --git a/kotlinx-coroutines-core/common/src/flow/Migration.kt b/kotlinx-coroutines-core/common/src/flow/Migration.kt index 11969a48fa..57749523d4 100644 --- a/kotlinx-coroutines-core/common/src/flow/Migration.kt +++ b/kotlinx-coroutines-core/common/src/flow/Migration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt b/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt index 75f9e710f7..048cd8b364 100644 --- a/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt +++ b/kotlinx-coroutines-core/common/src/flow/SharedFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow diff --git a/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt b/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt index 2691d4bd87..ce568fb46d 100644 --- a/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt +++ b/kotlinx-coroutines-core/common/src/flow/SharingStarted.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow diff --git a/kotlinx-coroutines-core/common/src/flow/StateFlow.kt b/kotlinx-coroutines-core/common/src/flow/StateFlow.kt index 45641ca92d..fc8aa02f20 100644 --- a/kotlinx-coroutines-core/common/src/flow/StateFlow.kt +++ b/kotlinx-coroutines-core/common/src/flow/StateFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow diff --git a/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt index ccb5343084..7114cc08d3 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal @@ -98,4 +98,4 @@ internal abstract class AbstractSharedFlow> : Sync if (slot != null) block(slot) } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt index f3730cc7fa..bf82cf9ae9 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt b/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt index 7bccc80f75..7fde06362a 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/Combine.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UNCHECKED_CAST", "NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE") // KT-32203 diff --git a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt index acc6ca04ec..b395525620 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt b/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt index 3064ed260b..6a6c369c75 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/FlowExceptions.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt b/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt index 530bcc1e5a..9eca8aa0c2 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/Merge.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt b/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt index 62a20a07c3..a2d7f04f20 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/NopCollector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt index f20deb2d38..c7327bd35e 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt index c89e94f592..006da41f1a 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt b/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt index c2abafd2fd..5188a969ca 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/SendingCollector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Context.kt b/kotlinx-coroutines-core/common/src/flow/operators/Context.kt index d2a289d8b1..cbbb4196d5 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Context.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Context.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt b/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt index c95b4be940..6381c467a4 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Delay.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt b/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt index 1a34af776f..0d67f88944 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -83,4 +83,4 @@ private class DistinctFlowImpl( } } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt index 244af9a7f5..e0d3aebceb 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt b/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt index c73ded9eea..608221e09f 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Errors.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt b/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt index 1d7ffd1db6..8fbf1a2b0e 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Limit.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt b/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt index 9aa240d8a9..2f7bc358e8 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Lint.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt b/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt index fae0a160ab..0427537558 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Share.kt b/kotlinx-coroutines-core/common/src/flow/operators/Share.kt index fe737a5bd1..fe1d7216b0 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Share.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Share.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt b/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt index e3552d2893..d163d9c09e 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Transform.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt b/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt index 790c0895e4..ed6f572226 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Zip.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -153,7 +153,7 @@ public fun combine( flow3: Flow, flow4: Flow, transform: suspend (T1, T2, T3, T4) -> R -): Flow = combine(flow, flow2, flow3, flow4) { args: Array<*> -> +): Flow = combineUnsafe(flow, flow2, flow3, flow4) { args: Array<*> -> transform( args[0] as T1, args[1] as T2, diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt index 103713aed2..42c662962b 100644 --- a/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt +++ b/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt index 6b05ca1840..c973da8973 100644 --- a/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt +++ b/kotlinx-coroutines-core/common/src/flow/terminal/Collection.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt index d50c027268..5eb99fc8ef 100644 --- a/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt +++ b/kotlinx-coroutines-core/common/src/flow/terminal/Count.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt index 83f5498e4d..a937adcc8a 100644 --- a/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt +++ b/kotlinx-coroutines-core/common/src/flow/terminal/Reduce.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/common/src/internal/ArrayQueue.kt b/kotlinx-coroutines-core/common/src/internal/ArrayQueue.kt index 09806cd22b..6b994b68e7 100644 --- a/kotlinx-coroutines-core/common/src/internal/ArrayQueue.kt +++ b/kotlinx-coroutines-core/common/src/internal/ArrayQueue.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/Atomic.kt b/kotlinx-coroutines-core/common/src/internal/Atomic.kt index a27d5491d1..cf43764c72 100644 --- a/kotlinx-coroutines-core/common/src/internal/Atomic.kt +++ b/kotlinx-coroutines-core/common/src/internal/Atomic.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE") diff --git a/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt index 1836a5284d..9f2699ae48 100644 --- a/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt b/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt index 128a1998ef..0e765838ab 100644 --- a/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt +++ b/kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -237,4 +237,4 @@ internal inline class SegmentOrClosed>(private val value: Any?) { private const val POINTERS_SHIFT = 16 @SharedImmutable -private val CLOSED = Symbol("CLOSED") \ No newline at end of file +private val CLOSED = Symbol("CLOSED") diff --git a/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt index b7b2954f6a..2874e7d592 100644 --- a/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt +++ b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -23,7 +23,7 @@ internal class DispatchedContinuation( @JvmField @Suppress("PropertyName") internal var _state: Any? = UNDEFINED - override val callerFrame: CoroutineStackFrame? = continuation as? CoroutineStackFrame + override val callerFrame: CoroutineStackFrame? get() = continuation as? CoroutineStackFrame override fun getStackTraceElement(): StackTraceElement? = null @JvmField // pre-cached value to avoid ctx.fold on every resumption internal val countOrElement = threadContextElements(context) @@ -235,7 +235,7 @@ internal class DispatchedContinuation( @Suppress("NOTHING_TO_INLINE") // we need it inline to save us an entry on the stack inline fun resumeUndispatchedWith(result: Result) { - withCoroutineContext(context, countOrElement) { + withContinuationContext(continuation, countOrElement) { continuation.resumeWith(result) } } diff --git a/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt index caf87f143e..d982f95bdf 100644 --- a/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt +++ b/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -85,9 +85,9 @@ internal abstract class DispatchedTask( try { val delegate = delegate as DispatchedContinuation val continuation = delegate.continuation - val context = continuation.context - val state = takeState() // NOTE: Must take state in any case, even if cancelled - withCoroutineContext(context, delegate.countOrElement) { + withContinuationContext(continuation, delegate.countOrElement) { + val context = continuation.context + val state = takeState() // NOTE: Must take state in any case, even if cancelled val exception = getExceptionalResult(state) /* * Check whether continuation was originally resumed with an exception. @@ -134,7 +134,7 @@ internal abstract class DispatchedTask( * Fatal exception handling can be intercepted with [CoroutineExceptionHandler] element in the context of * a failed coroutine, but such exceptions should be reported anyway. */ - internal fun handleFatalException(exception: Throwable?, finallyException: Throwable?) { + public fun handleFatalException(exception: Throwable?, finallyException: Throwable?) { if (exception === null && finallyException === null) return if (exception !== null && finallyException !== null) { exception.addSuppressedThrowable(finallyException) diff --git a/kotlinx-coroutines-core/common/src/internal/InlineList.kt b/kotlinx-coroutines-core/common/src/internal/InlineList.kt index bac8610c1a..34c1e893ee 100644 --- a/kotlinx-coroutines-core/common/src/internal/InlineList.kt +++ b/kotlinx-coroutines-core/common/src/internal/InlineList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UNCHECKED_CAST") diff --git a/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt b/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt index bcfb932de3..74848b2d7e 100644 --- a/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/LocalAtomics.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt index 8508e39239..0e1d1b473a 100644 --- a/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE") diff --git a/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt index dfee8e9f2b..10c5c830ac 100644 --- a/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt +++ b/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt b/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt index c3587af6e1..0b8638687b 100644 --- a/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt +++ b/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt b/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt index 1744359e93..0701d686c1 100644 --- a/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt +++ b/kotlinx-coroutines-core/common/src/internal/OnUndeliveredElement.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt b/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt index 763c1ca364..a6d813619b 100644 --- a/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/Scopes.kt b/kotlinx-coroutines-core/common/src/internal/Scopes.kt index f9362cff11..98db37de8d 100644 --- a/kotlinx-coroutines-core/common/src/internal/Scopes.kt +++ b/kotlinx-coroutines-core/common/src/internal/Scopes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt b/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt index 15ba40f2f4..b91f30d319 100644 --- a/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/Symbol.kt b/kotlinx-coroutines-core/common/src/internal/Symbol.kt index 4fa8f540af..84db2ef6cc 100644 --- a/kotlinx-coroutines-core/common/src/internal/Symbol.kt +++ b/kotlinx-coroutines-core/common/src/internal/Symbol.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -10,7 +10,7 @@ package kotlinx.coroutines.internal * @suppress **This is unstable API and it is subject to change.** */ internal class Symbol(val symbol: String) { - override fun toString(): String = symbol + override fun toString(): String = "<$symbol>" @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") inline fun unbox(value: Any?): T = if (value === this) null as T else value as T diff --git a/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt b/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt index 3afc7e1802..059b234d8f 100644 --- a/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt index 4cb629e9df..ca84809b4c 100644 --- a/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmName("SystemPropsKt") diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt index 94695e8a05..6d14e59230 100644 --- a/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt index 0f4ec342df..890ae4e3de 100644 --- a/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt b/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt index df55c28f13..43b7e9de51 100644 --- a/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt +++ b/kotlinx-coroutines-core/common/src/internal/ThreadSafeHeap.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt b/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt index f814b152b2..173f0afb65 100644 --- a/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt +++ b/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.intrinsics diff --git a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt index 525e322f08..1273634efa 100644 --- a/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt +++ b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.intrinsics diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt index 81d3745e62..0d97400717 100644 --- a/kotlinx-coroutines-core/common/src/selects/Select.kt +++ b/kotlinx-coroutines-core/common/src/selects/Select.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:OptIn(ExperimentalContracts::class) @@ -327,13 +327,13 @@ internal class SelectBuilderImpl( private fun initCancellability() { val parent = context[Job] ?: return val newRegistration = parent.invokeOnCompletion( - onCancelling = true, handler = SelectOnCancelling(parent).asHandler) + onCancelling = true, handler = SelectOnCancelling().asHandler) parentHandle = newRegistration // now check our state _after_ registering if (isSelected) newRegistration.dispose() } - private inner class SelectOnCancelling(job: Job) : JobCancellingNode(job) { + private inner class SelectOnCancelling : JobCancellingNode() { // Note: may be invoked multiple times, but only the first trySelect succeeds anyway override fun invoke(cause: Throwable?) { if (trySelect()) @@ -552,7 +552,7 @@ internal class SelectBuilderImpl( return decision } - override val atomicOp: AtomicOp<*>? + override val atomicOp: AtomicOp<*> get() = otherOp.atomicOp } diff --git a/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt b/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt index d691c725b5..c33c5b1f2c 100644 --- a/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt +++ b/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.selects diff --git a/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt b/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt index 33d4d7ec16..98a9c67238 100644 --- a/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt +++ b/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.selects diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index 707c4640bc..7d0a343d95 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.sync diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt index c342bb3009..e8b28bc15c 100644 --- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt +++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.sync diff --git a/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt b/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt index c763faf225..a41013779a 100644 --- a/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt +++ b/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -31,6 +31,38 @@ class AtomicCancellationCommonTest : TestBase() { expect(3) } + @Test + fun testUndispatchedLaunch() = runTest { + expect(1) + assertFailsWith { + withContext(Job()) { + cancel() + launch(start = CoroutineStart.UNDISPATCHED) { + expect(2) + yield() + expectUnreached() + } + } + } + finish(3) + } + + @Test + fun testUndispatchedLaunchWithUnconfinedContext() = runTest { + expect(1) + assertFailsWith { + withContext(Dispatchers.Unconfined + Job()) { + cancel() + launch(start = CoroutineStart.UNDISPATCHED) { + expect(2) + yield() + expectUnreached() + } + } + } + finish(3) + } + @Test fun testDeferredAwaitCancellable() = runTest { expect(1) @@ -122,4 +154,4 @@ class AtomicCancellationCommonTest : TestBase() { yield() // now yield finish(4) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/test/AwaitTest.kt b/kotlinx-coroutines-core/common/test/AwaitTest.kt index 0949b62c8c..10d5b91995 100644 --- a/kotlinx-coroutines-core/common/test/AwaitTest.kt +++ b/kotlinx-coroutines-core/common/test/AwaitTest.kt @@ -351,4 +351,32 @@ class AwaitTest : TestBase() { async(NonCancellable) { throw TestException() } joinAll(job, job, job) } + + @Test + fun testAwaitAllDelegates() = runTest { + expect(1) + val deferred = CompletableDeferred() + val delegate = object : Deferred by deferred {} + launch { + expect(3) + deferred.complete("OK") + } + expect(2) + awaitAll(delegate) + finish(4) + } + + @Test + fun testCancelAwaitAllDelegate() = runTest { + expect(1) + val deferred = CompletableDeferred() + val delegate = object : Deferred by deferred {} + launch { + expect(3) + deferred.cancel() + } + expect(2) + assertFailsWith { awaitAll(delegate) } + finish(4) + } } diff --git a/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt b/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt index b20dd6b1d2..5a96c54460 100644 --- a/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt +++ b/kotlinx-coroutines-core/common/test/BuilderContractsTest.kt @@ -1,9 +1,10 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines +import kotlinx.coroutines.channels.* import kotlinx.coroutines.selects.* import kotlin.test.* @@ -44,9 +45,22 @@ class BuilderContractsTest : TestBase() { Job().apply { complete() }.onJoin {} } consume(s) + + + val ch: Int + val i = Channel() + i.consume { + ch = 321 + } + consume(ch) } private fun consume(a: Int) { - a.hashCode() // BE codegen verification + /* + * Verify the value is actually set correctly + * (non-zero, VerificationError is not triggered, can be read) + */ + assertNotEquals(0, a) + assertEquals(a.hashCode(), a) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt index 0391e00033..5513dab782 100644 --- a/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementTest.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.channels import kotlinx.atomicfu.* @@ -50,6 +54,20 @@ class ChannelUndeliveredElementTest : TestBase() { assertTrue(resA.isCancelled) // now cancelled in buffer } + @Test + fun testUnlimitedChannelCancelled() = runTest { + val channel = Channel(Channel.UNLIMITED) { it.cancel() } + val resA = Resource("A") + val resB = Resource("B") + channel.send(resA) // goes to buffer + channel.send(resB) // goes to buffer + assertFalse(resA.isCancelled) // it is in buffer, not cancelled + assertFalse(resB.isCancelled) // it is in buffer, not cancelled + channel.cancel() // now cancel the channel + assertTrue(resA.isCancelled) // now cancelled in buffer + assertTrue(resB.isCancelled) // now cancelled in buffer + } + @Test fun testConflatedResourceCancelled() = runTest { val channel = Channel(Channel.CONFLATED) { it.cancel() } @@ -101,4 +119,4 @@ class ChannelUndeliveredElementTest : TestBase() { check(!_cancelled.getAndSet(true)) { "Already cancelled" } } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt index 6ddde001e2..194504e713 100644 --- a/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -95,6 +95,27 @@ class ProduceTest : TestBase() { cancelOnCompletion(coroutineContext) } + @Test + fun testCancelWhenTheChannelIsClosed() = runTest { + val channel = produce { + send(1) + close() + expect(2) + launch { + expect(3) + hang { expect(5) } + } + } + + expect(1) + channel.receive() + yield() + expect(4) + channel.cancel() + (channel as Job).join() + finish(6) + } + @Test fun testAwaitConsumerCancellation() = runTest { val parent = Job() diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt index b115150a0b..31a929b2d8 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow @@ -194,4 +194,17 @@ class ChannelFlowTest : TestBase() { assertEquals(listOf(1), flow.toList()) finish(3) } + + @Test + fun testCancelledOnCompletion() = runTest { + val myFlow = callbackFlow { + expect(2) + close() + hang { expect(3) } + } + + expect(1) + myFlow.collect() + finish(4) + } } diff --git a/kotlinx-coroutines-core/js/src/CompletionHandler.kt b/kotlinx-coroutines-core/js/src/CompletionHandler.kt index e81e43511a..2ff1070222 100644 --- a/kotlinx-coroutines-core/js/src/CompletionHandler.kt +++ b/kotlinx-coroutines-core/js/src/CompletionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/CoroutineContext.kt b/kotlinx-coroutines-core/js/src/CoroutineContext.kt index c0b0c511f9..e08345a1d2 100644 --- a/kotlinx-coroutines-core/js/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/js/src/CoroutineContext.kt @@ -1,9 +1,10 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines +import kotlinx.coroutines.internal.* import kotlin.browser.* import kotlin.coroutines.* @@ -49,5 +50,13 @@ public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): // No debugging facilities on JS internal actual inline fun withCoroutineContext(context: CoroutineContext, countOrElement: Any?, block: () -> T): T = block() +internal actual inline fun withContinuationContext(continuation: Continuation<*>, countOrElement: Any?, block: () -> T): T = block() internal actual fun Continuation<*>.toDebugString(): String = toString() internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on JS + +internal actual class UndispatchedCoroutine actual constructor( + context: CoroutineContext, + uCont: Continuation +) : ScopeCoroutine(context, uCont) { + override fun afterResume(state: Any?) = uCont.resumeWith(recoverResult(state, uCont)) +} diff --git a/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt index 524d4b5543..54a65e10a6 100644 --- a/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/Debug.kt b/kotlinx-coroutines-core/js/src/Debug.kt index 7cd9bedd2f..7655b54389 100644 --- a/kotlinx-coroutines-core/js/src/Debug.kt +++ b/kotlinx-coroutines-core/js/src/Debug.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/Dispatchers.kt b/kotlinx-coroutines-core/js/src/Dispatchers.kt index 06b938d41a..8d3bac3209 100644 --- a/kotlinx-coroutines-core/js/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/js/src/Dispatchers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/EventLoop.kt b/kotlinx-coroutines-core/js/src/EventLoop.kt index 0039678a93..b3a1364107 100644 --- a/kotlinx-coroutines-core/js/src/EventLoop.kt +++ b/kotlinx-coroutines-core/js/src/EventLoop.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/Exceptions.kt b/kotlinx-coroutines-core/js/src/Exceptions.kt index c82199a429..7c76bc6d2c 100644 --- a/kotlinx-coroutines-core/js/src/Exceptions.kt +++ b/kotlinx-coroutines-core/js/src/Exceptions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/JSDispatcher.kt b/kotlinx-coroutines-core/js/src/JSDispatcher.kt index e1b3dcd7a9..6ad7d41b15 100644 --- a/kotlinx-coroutines-core/js/src/JSDispatcher.kt +++ b/kotlinx-coroutines-core/js/src/JSDispatcher.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/Promise.kt b/kotlinx-coroutines-core/js/src/Promise.kt index ab2003236a..336a3883b3 100644 --- a/kotlinx-coroutines-core/js/src/Promise.kt +++ b/kotlinx-coroutines-core/js/src/Promise.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/Runnable.kt b/kotlinx-coroutines-core/js/src/Runnable.kt index 19710f971b..b8e6980b22 100644 --- a/kotlinx-coroutines-core/js/src/Runnable.kt +++ b/kotlinx-coroutines-core/js/src/Runnable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/SchedulerTask.kt b/kotlinx-coroutines-core/js/src/SchedulerTask.kt index 29a92cfb24..c0ecc4f2da 100644 --- a/kotlinx-coroutines-core/js/src/SchedulerTask.kt +++ b/kotlinx-coroutines-core/js/src/SchedulerTask.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/Window.kt b/kotlinx-coroutines-core/js/src/Window.kt index 8284daef8d..dad0c04b39 100644 --- a/kotlinx-coroutines-core/js/src/Window.kt +++ b/kotlinx-coroutines-core/js/src/Window.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt index f818bfbb37..000395ea7b 100644 --- a/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt +++ b/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt index ace633ccc6..b74b547d31 100644 --- a/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt +++ b/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/js/src/internal/Concurrent.kt b/kotlinx-coroutines-core/js/src/internal/Concurrent.kt index 5555137f7f..0a1b03104e 100644 --- a/kotlinx-coroutines-core/js/src/internal/Concurrent.kt +++ b/kotlinx-coroutines-core/js/src/internal/Concurrent.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt index 8f42160b55..335e35d3b7 100644 --- a/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt +++ b/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/LinkedList.kt b/kotlinx-coroutines-core/js/src/internal/LinkedList.kt index b69850576e..f2711f50af 100644 --- a/kotlinx-coroutines-core/js/src/internal/LinkedList.kt +++ b/kotlinx-coroutines-core/js/src/internal/LinkedList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused", "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE", "NO_EXPLICIT_VISIBILITY_IN_API_MODE") diff --git a/kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt b/kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt index fffd76c452..643fe85d36 100644 --- a/kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt +++ b/kotlinx-coroutines-core/js/src/internal/LocalAtomics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt index a13a141f4d..47d3fdbac9 100644 --- a/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt +++ b/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt index 234bbcadc2..06107b8f49 100644 --- a/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt +++ b/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/Synchronized.kt b/kotlinx-coroutines-core/js/src/internal/Synchronized.kt index 0911dbe115..dcbb20217d 100644 --- a/kotlinx-coroutines-core/js/src/internal/Synchronized.kt +++ b/kotlinx-coroutines-core/js/src/internal/Synchronized.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt index 564630f623..4fb334ed16 100644 --- a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt +++ b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt index 4a9513ab9e..2370e42ff4 100644 --- a/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt +++ b/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt index 09f501a4f5..e1825d67b8 100644 --- a/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt +++ b/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin b/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin index 76ee41159d..ea8c9da4c2 100644 Binary files a/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin and b/kotlinx-coroutines-core/jvm/resources/DebugProbesKt.bin differ diff --git a/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro b/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro index 60c8d61243..1a9ae1c7ff 100644 --- a/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro +++ b/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro @@ -3,12 +3,12 @@ -keepnames class kotlinx.coroutines.CoroutineExceptionHandler {} # Most of volatile fields are updated with AFU and should not be mangled --keepclassmembernames class kotlinx.** { +-keepclassmembers class kotlinx.coroutines.** { volatile ; } # Same story for the standard library's SafeContinuation that also uses AtomicReferenceFieldUpdater --keepclassmembernames class kotlin.coroutines.SafeContinuation { +-keepclassmembers class kotlin.coroutines.SafeContinuation { volatile ; } diff --git a/kotlinx-coroutines-core/jvm/src/Builders.kt b/kotlinx-coroutines-core/jvm/src/Builders.kt index e4504ccdd4..c1b878ce2c 100644 --- a/kotlinx-coroutines-core/jvm/src/Builders.kt +++ b/kotlinx-coroutines-core/jvm/src/Builders.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -69,7 +69,7 @@ private class BlockingCoroutine( override fun afterCompletion(state: Any?) { // wake up blocked thread if (Thread.currentThread() != blockedThread) - LockSupport.unpark(blockedThread) + unpark(blockedThread) } @Suppress("UNCHECKED_CAST") diff --git a/kotlinx-coroutines-core/jvm/src/CommonPool.kt b/kotlinx-coroutines-core/jvm/src/CommonPool.kt index 2203313120..502630b010 100644 --- a/kotlinx-coroutines-core/jvm/src/CommonPool.kt +++ b/kotlinx-coroutines-core/jvm/src/CommonPool.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -28,7 +28,7 @@ internal object CommonPool : ExecutorCoroutineDispatcher() { * Note that until Java 10, if an application is run within a container, * `Runtime.getRuntime().availableProcessors()` is not aware of container constraints and will return the real number of cores. */ - public const val DEFAULT_PARALLELISM_PROPERTY_NAME = "kotlinx.coroutines.default.parallelism" + private const val DEFAULT_PARALLELISM_PROPERTY_NAME = "kotlinx.coroutines.default.parallelism" override val executor: Executor get() = pool ?: getOrCreatePoolSync() @@ -62,7 +62,7 @@ internal object CommonPool : ExecutorCoroutineDispatcher() { ?: return createPlainPool() // Fallback to plain thread pool // Try to use commonPool unless parallelism was explicitly specified or in debug privatePool mode if (!usePrivatePool && requestedParallelism < 0) { - Try { fjpClass.getMethod("commonPool")?.invoke(null) as? ExecutorService } + Try { fjpClass.getMethod("commonPool").invoke(null) as? ExecutorService } ?.takeIf { isGoodCommonPool(fjpClass, it) } ?.let { return it } } diff --git a/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt b/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt index 706f6c498e..4835f7968e 100644 --- a/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt +++ b/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt index 5a69d48aac..e91bb9fd21 100644 --- a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt @@ -1,13 +1,13 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines import kotlinx.coroutines.internal.* import kotlinx.coroutines.scheduling.* -import java.util.concurrent.atomic.* import kotlin.coroutines.* +import kotlin.coroutines.jvm.internal.CoroutineStackFrame internal const val COROUTINES_SCHEDULER_PROPERTY_NAME = "kotlinx.coroutines.scheduler" @@ -48,6 +48,102 @@ internal actual inline fun withCoroutineContext(context: CoroutineContext, c } } +/** + * Executes a block using a context of a given continuation. + */ +internal actual inline fun withContinuationContext(continuation: Continuation<*>, countOrElement: Any?, block: () -> T): T { + val context = continuation.context + val oldValue = updateThreadContext(context, countOrElement) + val undispatchedCompletion = if (oldValue !== NO_THREAD_ELEMENTS) { + // Only if some values were replaced we'll go to the slow path of figuring out where/how to restore them + continuation.updateUndispatchedCompletion(context, oldValue) + } else { + null // fast path -- don't even try to find undispatchedCompletion as there's nothing to restore in the context + } + try { + return block() + } finally { + if (undispatchedCompletion == null || undispatchedCompletion.clearThreadContext()) { + restoreThreadContext(context, oldValue) + } + } +} + +internal fun Continuation<*>.updateUndispatchedCompletion(context: CoroutineContext, oldValue: Any?): UndispatchedCoroutine<*>? { + if (this !is CoroutineStackFrame) return null + /* + * Fast-path to detect whether we have unispatched coroutine at all in our stack. + * + * Implementation note. + * If we ever find that stackwalking for thread-locals is way too slow, here is another idea: + * 1) Store undispatched coroutine right in the `UndispatchedMarker` instance + * 2) To avoid issues with cross-dispatch boundary, remove `UndispatchedMarker` + * from the context when creating dispatched coroutine in `withContext`. + * Another option is to "unmark it" instead of removing to save an allocation. + * Both options should work, but it requires more careful studying of the performance + * and, mostly, maintainability impact. + */ + val potentiallyHasUndispatchedCorotuine = context[UndispatchedMarker] !== null + if (!potentiallyHasUndispatchedCorotuine) return null + val completion = undispatchedCompletion() + completion?.saveThreadContext(context, oldValue) + return completion +} + +internal tailrec fun CoroutineStackFrame.undispatchedCompletion(): UndispatchedCoroutine<*>? { + // Find direct completion of this continuation + val completion: CoroutineStackFrame = when (this) { + is DispatchedCoroutine<*> -> return null + else -> callerFrame ?: return null // something else -- not supported + } + if (completion is UndispatchedCoroutine<*>) return completion // found UndispatchedCoroutine! + return completion.undispatchedCompletion() // walk up the call stack with tail call +} + +/** + * Marker indicating that [UndispatchedCoroutine] exists somewhere up in the stack. + * Used as a performance optimization to avoid stack walking where it is not nesessary. + */ +private object UndispatchedMarker: CoroutineContext.Element, CoroutineContext.Key { + override val key: CoroutineContext.Key<*> + get() = this +} + +// Used by withContext when context changes, but dispatcher stays the same +internal actual class UndispatchedCoroutineactual constructor ( + context: CoroutineContext, + uCont: Continuation +) : ScopeCoroutine(if (context[UndispatchedMarker] == null) context + UndispatchedMarker else context, uCont) { + + private var savedContext: CoroutineContext? = null + private var savedOldValue: Any? = null + + fun saveThreadContext(context: CoroutineContext, oldValue: Any?) { + savedContext = context + savedOldValue = oldValue + } + + fun clearThreadContext(): Boolean { + if (savedContext == null) return false + savedContext = null + savedOldValue = null + return true + } + + override fun afterResume(state: Any?) { + savedContext?.let { context -> + restoreThreadContext(context, savedOldValue) + savedContext = null + savedOldValue = null + } + // resume undispatched -- update context but stay on the same dispatcher + val result = recoverResult(state, uCont) + withContinuationContext(uCont, null) { + uCont.resumeWith(result) + } + } +} + internal actual val CoroutineContext.coroutineName: String? get() { if (!DEBUG) return null val coroutineId = this[CoroutineId] ?: return null diff --git a/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt index af37e73c39..6d06969293 100644 --- a/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/Debug.kt b/kotlinx-coroutines-core/jvm/src/Debug.kt index 8108d235c1..911914a0f9 100644 --- a/kotlinx-coroutines-core/jvm/src/Debug.kt +++ b/kotlinx-coroutines-core/jvm/src/Debug.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // Need InlineOnly for efficient bytecode on Android diff --git a/kotlinx-coroutines-core/jvm/src/DebugStrings.kt b/kotlinx-coroutines-core/jvm/src/DebugStrings.kt index 2ccfebc6d3..32bd07a72d 100644 --- a/kotlinx-coroutines-core/jvm/src/DebugStrings.kt +++ b/kotlinx-coroutines-core/jvm/src/DebugStrings.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt b/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt index 787cbf9c44..fe020276e5 100644 --- a/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt +++ b/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/Dispatchers.kt b/kotlinx-coroutines-core/jvm/src/Dispatchers.kt index 8033fb38e5..25c0fbe9b0 100644 --- a/kotlinx-coroutines-core/jvm/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/jvm/src/Dispatchers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused") @@ -8,7 +8,6 @@ package kotlinx.coroutines import kotlinx.coroutines.internal.* import kotlinx.coroutines.scheduling.* -import java.util.* import kotlin.coroutines.* /** diff --git a/kotlinx-coroutines-core/jvm/src/EventLoop.kt b/kotlinx-coroutines-core/jvm/src/EventLoop.kt index d86f632a69..e49c7dc7e1 100644 --- a/kotlinx-coroutines-core/jvm/src/EventLoop.kt +++ b/kotlinx-coroutines-core/jvm/src/EventLoop.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/Exceptions.kt b/kotlinx-coroutines-core/jvm/src/Exceptions.kt index 0684ce2397..007a0c98fa 100644 --- a/kotlinx-coroutines-core/jvm/src/Exceptions.kt +++ b/kotlinx-coroutines-core/jvm/src/Exceptions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("FunctionName") diff --git a/kotlinx-coroutines-core/jvm/src/Executors.kt b/kotlinx-coroutines-core/jvm/src/Executors.kt index 8ffc22d8bb..394304f231 100644 --- a/kotlinx-coroutines-core/jvm/src/Executors.kt +++ b/kotlinx-coroutines-core/jvm/src/Executors.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/Future.kt b/kotlinx-coroutines-core/jvm/src/Future.kt index 58792ced31..948ef6065c 100644 --- a/kotlinx-coroutines-core/jvm/src/Future.kt +++ b/kotlinx-coroutines-core/jvm/src/Future.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -20,7 +20,7 @@ import java.util.concurrent.* */ @InternalCoroutinesApi public fun Job.cancelFutureOnCompletion(future: Future<*>): DisposableHandle = - invokeOnCompletion(handler = CancelFutureOnCompletion(this, future)) // TODO make it work only on cancellation as well? + invokeOnCompletion(handler = CancelFutureOnCompletion(future)) // TODO make it work only on cancellation as well? /** * Cancels a specified [future] when this job is cancelled. @@ -33,9 +33,8 @@ public fun CancellableContinuation<*>.cancelFutureOnCancellation(future: Future< invokeOnCancellation(handler = CancelFutureOnCancel(future)) private class CancelFutureOnCompletion( - job: Job, private val future: Future<*> -) : JobNode(job) { +) : JobNode() { override fun invoke(cause: Throwable?) { // Don't interrupt when cancelling future on completion, because no one is going to reset this // interruption flag and it will cause spurious failures elsewhere diff --git a/kotlinx-coroutines-core/jvm/src/Interruptible.kt b/kotlinx-coroutines-core/jvm/src/Interruptible.kt index 070aa62497..b873eadf4a 100644 --- a/kotlinx-coroutines-core/jvm/src/Interruptible.kt +++ b/kotlinx-coroutines-core/jvm/src/Interruptible.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/Runnable.kt b/kotlinx-coroutines-core/jvm/src/Runnable.kt index 14d011053d..844f9fcab9 100644 --- a/kotlinx-coroutines-core/jvm/src/Runnable.kt +++ b/kotlinx-coroutines-core/jvm/src/Runnable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt b/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt index 478df822f4..6a00f45f13 100644 --- a/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt +++ b/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt index 1fd851104d..37fd70a23e 100644 --- a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt +++ b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt b/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt index aa18cd38d6..44a79d42ed 100644 --- a/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt +++ b/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt @@ -1,13 +1,11 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines -import kotlinx.coroutines.internal.* import java.util.concurrent.* import java.util.concurrent.atomic.AtomicInteger -import kotlin.coroutines.* /** * Creates a coroutine execution context using a single thread with built-in [yield] support. diff --git a/kotlinx-coroutines-core/jvm/src/TimeSource.kt b/kotlinx-coroutines-core/jvm/src/TimeSource.kt index 4b6fd9915c..8d6dea2fb7 100644 --- a/kotlinx-coroutines-core/jvm/src/TimeSource.kt +++ b/kotlinx-coroutines-core/jvm/src/TimeSource.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // Need InlineOnly for efficient bytecode on Android diff --git a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt index a905426585..0212d740bb 100644 --- a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt +++ b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/jvm/src/channels/Channels.kt b/kotlinx-coroutines-core/jvm/src/channels/Channels.kt index 2c9499597f..081a0583d1 100644 --- a/kotlinx-coroutines-core/jvm/src/channels/Channels.kt +++ b/kotlinx-coroutines-core/jvm/src/channels/Channels.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt b/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt index 1e6797accc..099e70b3b9 100644 --- a/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt +++ b/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels diff --git a/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt b/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt index 5a1a1ed1b7..8ef0c18217 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt index 79f024cc93..ffb9c2dae6 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/ConcurrentWeakMap.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.internal diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt index 9d9fa3fbb2..6c35392909 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.internal @@ -27,4 +27,4 @@ internal class DebugCoroutineInfo( public val lastObservedFrame: CoroutineStackFrame? = source.lastObservedFrame // field is used as of 1.4-M3 @get:JvmName("lastObservedStackTrace") // method with this name is used as of 1.4-M3 public val lastObservedStackTrace: List = source.lastObservedStackTrace() -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt index cf007bb978..07b9419f1b 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugCoroutineInfoImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.internal @@ -72,7 +72,7 @@ internal class DebugCoroutineInfoImpl( private fun creationStackTrace(): List { val bottom = creationStackBottom ?: return emptyList() // Skip "Coroutine creation stacktrace" frame - return sequence { yieldFrames(bottom.callerFrame) }.toList() + return sequence { yieldFrames(bottom.callerFrame) }.toList() } private tailrec suspend fun SequenceScope.yieldFrames(frame: CoroutineStackFrame?) { diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt index 83bc02c6d6..4c88cc976a 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.internal @@ -477,33 +477,40 @@ internal object DebugProbesImpl { /* * Trim intervals of internal methods from the stacktrace (bounds are excluded from trimming) - * E.g. for sequence [e, i1, i2, i3, e, i4, e, i5, i6, e7] + * E.g. for sequence [e, i1, i2, i3, e, i4, e, i5, i6, i7] * output will be [e, i1, i3, e, i4, e, i5, i7] + * + * If an interval of internal methods ends in a synthetic method, the outermost non-synthetic method in that + * interval will also be included. */ val result = ArrayList(size - probeIndex + 1) result += createArtificialFrame(ARTIFICIAL_FRAME_MESSAGE) - var includeInternalFrame = true - for (i in (probeIndex + 1) until size - 1) { - val element = stackTrace[i] - if (!element.isInternalMethod) { - includeInternalFrame = true - result += element - continue - } - - if (includeInternalFrame) { - result += element - includeInternalFrame = false - } else if (stackTrace[i + 1].isInternalMethod) { - continue + var i = probeIndex + 1 + while (i < size) { + if (stackTrace[i].isInternalMethod) { + result += stackTrace[i] // we include the boundary of the span in any case + // first index past the end of the span of internal methods that starts from `i` + var j = i + 1 + while (j < size && stackTrace[j].isInternalMethod) { + ++j + } + // index of the last non-synthetic internal methods in this span, or `i` if there are no such methods + var k = j - 1 + while (k > i && stackTrace[k].fileName == null) { + k -= 1 + } + if (k > i && k < j - 1) { + /* there are synthetic internal methods at the end of this span, but there is a non-synthetic method + after `i`, so we include it. */ + result += stackTrace[k] + } + result += stackTrace[j - 1] // we include the other boundary of this span in any case, too + i = j } else { - result += element - includeInternalFrame = true + result += stackTrace[i] + ++i } - } - - result += stackTrace[size - 1] return result } diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt index 3e9533b09e..0b63cd2308 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebuggerInfo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UNUSED") diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt index 37c60eeb56..40101192be 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/StackTraceFrame.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.internal @@ -14,4 +14,4 @@ internal class StackTraceFrame( private val stackTraceElement: StackTraceElement ) : CoroutineStackFrame { override fun getStackTraceElement(): StackTraceElement = stackTraceElement -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt index 4fb958ac7d..d178060ddd 100644 --- a/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt +++ b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt index ab42b6345f..ea973287a7 100644 --- a/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt +++ b/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal @@ -36,7 +36,7 @@ internal actual class SafeCollector actual constructor( override val context: CoroutineContext get() = completion?.context ?: EmptyCoroutineContext - override fun invokeSuspend(result: Result): Any? { + override fun invokeSuspend(result: Result): Any { result.onFailure { lastEmissionContext = DownstreamExceptionElement(it) } completion?.resumeWith(result as Result) return COROUTINE_SUSPENDED diff --git a/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt index 75b668a335..050b974755 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -9,7 +9,7 @@ import java.util.* import java.util.concurrent.* import kotlin.concurrent.withLock as withLockJvm -internal actual fun subscriberList(): SubscribersList = CopyOnWriteArrayList() +internal actual fun subscriberList(): SubscribersList = CopyOnWriteArrayList() @Suppress("ACTUAL_WITHOUT_EXPECT") internal actual typealias ReentrantLock = java.util.concurrent.locks.ReentrantLock diff --git a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt index a03163db36..60328ebdc0 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt b/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt index 30cd09ef36..e93de2aad7 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt b/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt index f508749ed0..9dda30b5d8 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/LocalAtomics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt index d08f41bf8a..caad1e3323 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE") @@ -322,7 +322,7 @@ public actual open class LockFreeLinkedListNode { private val _affectedNode = atomic(null) final override val affectedNode: Node? get() = _affectedNode.value - final override val originalNext: Node? get() = queue + final override val originalNext: Node get() = queue override fun retry(affected: Node, next: Any): Boolean = next !== queue diff --git a/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt index 5b2b9ff68c..3102fdfbb9 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -35,7 +35,7 @@ internal object MainDispatcherLoader { ).iterator().asSequence().toList() } @Suppress("ConstantConditionIf") - factories.maxBy { it.loadPriority }?.tryCreateDispatcher(factories) + factories.maxByOrNull { it.loadPriority }?.tryCreateDispatcher(factories) ?: createMissingDispatcher() } catch (e: Throwable) { // Service loader can throw an exception as well diff --git a/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt index 2f4d1e052e..48e01fbeff 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt index 208d3f2e75..48e8790cd1 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt @@ -1,8 +1,8 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -@file:Suppress("UNCHECKED_CAST", "NO_EXPLICIT_VISIBILITY_IN_API_MODE") +@file:Suppress("UNCHECKED_CAST") package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt b/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt index 2b57b26cbd..6284f3a099 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt index bf34c1a97b..73853720ae 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmName("SystemPropsKt") diff --git a/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt index 9d9d30e41d..8536cef65d 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -7,17 +7,26 @@ package kotlinx.coroutines.internal import kotlinx.coroutines.* import kotlin.coroutines.* - -private val ZERO = Symbol("ZERO") +@JvmField +internal val NO_THREAD_ELEMENTS = Symbol("NO_THREAD_ELEMENTS") // Used when there are >= 2 active elements in the context -private class ThreadState(val context: CoroutineContext, n: Int) { - private var a = arrayOfNulls(n) +@Suppress("UNCHECKED_CAST") +private class ThreadState(@JvmField val context: CoroutineContext, n: Int) { + private val values = arrayOfNulls(n) + private val elements = arrayOfNulls>(n) private var i = 0 - fun append(value: Any?) { a[i++] = value } - fun take() = a[i++] - fun start() { i = 0 } + fun append(element: ThreadContextElement<*>, value: Any?) { + values[i] = value + elements[i++] = element as ThreadContextElement + } + + fun restore(context: CoroutineContext) { + for (i in elements.indices.reversed()) { + elements[i]!!.restoreThreadContext(context, values[i]) + } + } } // Counts ThreadContextElements in the context @@ -42,17 +51,7 @@ private val findOne = private val updateState = fun (state: ThreadState, element: CoroutineContext.Element): ThreadState { if (element is ThreadContextElement<*>) { - state.append(element.updateThreadContext(state.context)) - } - return state - } - -// Restores state for all ThreadContextElements in the context from the given ThreadState -private val restoreState = - fun (state: ThreadState, element: CoroutineContext.Element): ThreadState { - @Suppress("UNCHECKED_CAST") - if (element is ThreadContextElement<*>) { - (element as ThreadContextElement).restoreThreadContext(state.context, state.take()) + state.append(element, element.updateThreadContext(state.context)) } return state } @@ -60,12 +59,13 @@ private val restoreState = internal actual fun threadContextElements(context: CoroutineContext): Any = context.fold(0, countAll)!! // countOrElement is pre-cached in dispatched continuation +// returns NO_THREAD_ELEMENTS if the contest does not have any ThreadContextElements internal fun updateThreadContext(context: CoroutineContext, countOrElement: Any?): Any? { @Suppress("NAME_SHADOWING") val countOrElement = countOrElement ?: threadContextElements(context) @Suppress("IMPLICIT_BOXING_IN_IDENTITY_EQUALS") return when { - countOrElement === 0 -> ZERO // very fast path when there are no active ThreadContextElements + countOrElement === 0 -> NO_THREAD_ELEMENTS // very fast path when there are no active ThreadContextElements // ^^^ identity comparison for speed, we know zero always has the same identity countOrElement is Int -> { // slow path for multiple active ThreadContextElements, allocates ThreadState for multiple old values @@ -82,11 +82,10 @@ internal fun updateThreadContext(context: CoroutineContext, countOrElement: Any? internal fun restoreThreadContext(context: CoroutineContext, oldState: Any?) { when { - oldState === ZERO -> return // very fast path when there are no ThreadContextElements + oldState === NO_THREAD_ELEMENTS -> return // very fast path when there are no ThreadContextElements oldState is ThreadState -> { // slow path with multiple stored ThreadContextElements - oldState.start() - context.fold(oldState, restoreState) + oldState.restore(context) } else -> { // fast path for one ThreadContextElement, but need to find it diff --git a/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt index ff0970a219..0207334af0 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt index ad61224b52..84d9d9f8df 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling @@ -146,7 +146,7 @@ internal class CoroutineScheduler( * * Note, [newIndex] can be zero for the worker that is being terminated (removed from [workers]). */ - internal fun parkedWorkersStackTopUpdate(worker: Worker, oldIndex: Int, newIndex: Int) { + fun parkedWorkersStackTopUpdate(worker: Worker, oldIndex: Int, newIndex: Int) { parkedWorkersStack.loop { top -> val index = (top and PARKED_INDEX_MASK).toInt() val updVersion = (top + PARKED_VERSION_INC) and PARKED_VERSION_MASK @@ -169,12 +169,12 @@ internal class CoroutineScheduler( * It does nothing is this worker is already physically linked to the stack. * This method is invoked only from the worker thread itself. * This invocation always precedes [LockSupport.parkNanos]. - * See [Worker.doPark]. + * See [Worker.tryPark]. * * Returns `true` if worker was added to the stack by this invocation, `false` if it was already * registered in the stack. */ - internal fun parkedWorkersStackPush(worker: Worker): Boolean { + fun parkedWorkersStackPush(worker: Worker): Boolean { if (worker.nextParkedWorker !== NOT_IN_STACK) return false // already in stack, bail out /* * The below loop can be entered only if this worker was not in the stack and, since no other thread @@ -403,7 +403,7 @@ internal class CoroutineScheduler( } } - internal fun createTask(block: Runnable, taskContext: TaskContext): Task { + fun createTask(block: Runnable, taskContext: TaskContext): Task { val nanoTime = schedulerTimeSource.nanoTime() if (block is Task) { block.submissionTime = nanoTime @@ -422,7 +422,7 @@ internal class CoroutineScheduler( tryUnpark() // Try unpark again in case there was race between permit release and parking } - internal fun signalCpuWork() { + fun signalCpuWork() { if (tryUnpark()) return if (tryCreateWorker()) return tryUnpark() @@ -654,7 +654,7 @@ internal class CoroutineScheduler( * Releases CPU token if worker has any and changes state to [newState]. * Returns `true` if CPU permit was returned to the pool */ - internal fun tryReleaseCpu(newState: WorkerState): Boolean { + fun tryReleaseCpu(newState: WorkerState): Boolean { val previousState = state val hadCpu = previousState == WorkerState.CPU_ACQUIRED if (hadCpu) releaseCpuPermit() @@ -774,7 +774,7 @@ internal class CoroutineScheduler( * Marsaglia xorshift RNG with period 2^32-1 for work stealing purposes. * ThreadLocalRandom cannot be used to support Android and ThreadLocal is up to 15% slower on Ktor benchmarks */ - internal fun nextInt(upperBound: Int): Int { + fun nextInt(upperBound: Int): Int { var r = rngState r = r xor (r shl 13) r = r xor (r shr 17) diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt index 202c6e1d06..7227b07c07 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt index a317b9754c..da867c9853 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling @@ -52,7 +52,7 @@ internal val IDLE_WORKER_KEEP_ALIVE_NS = TimeUnit.SECONDS.toNanos( ) @JvmField -internal var schedulerTimeSource: TimeSource = NanoTimeSource +internal var schedulerTimeSource: SchedulerTimeSource = NanoTimeSource /** * Marker indicating that task is CPU-bound and will not block @@ -108,10 +108,11 @@ internal class TaskImpl( // Open for tests internal class GlobalQueue : LockFreeTaskQueue(singleConsumer = false) -internal abstract class TimeSource { +// Was previously TimeSource, renamed due to KT-42625 and KT-23727 +internal abstract class SchedulerTimeSource { abstract fun nanoTime(): Long } -internal object NanoTimeSource : TimeSource() { +internal object NanoTimeSource : SchedulerTimeSource() { override fun nanoTime() = System.nanoTime() } diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt b/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt index 354b3a1b3b..6a9a8a5a31 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling diff --git a/kotlinx-coroutines-core/jvm/src/test_/TestCoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/test_/TestCoroutineContext.kt index 649c95375d..8526ca216a 100644 --- a/kotlinx-coroutines-core/jvm/src/test_/TestCoroutineContext.kt +++ b/kotlinx-coroutines-core/jvm/src/test_/TestCoroutineContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test diff --git a/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt new file mode 100644 index 0000000000..5ba7acf994 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +package kotlinx.coroutines + +import org.jetbrains.kotlinx.lincheck.* +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* +import org.jetbrains.kotlinx.lincheck.strategy.stress.* +import org.jetbrains.kotlinx.lincheck.verifier.* +import org.junit.* + +abstract class AbstractLincheckTest : VerifierState() { + open fun > O.customize(isStressTest: Boolean): O = this + open fun ModelCheckingOptions.customize(isStressTest: Boolean): ModelCheckingOptions = this + open fun StressOptions.customize(isStressTest: Boolean): StressOptions = this + + @Test + fun modelCheckingTest() = ModelCheckingOptions() + .iterations(if (isStressTest) 100 else 20) + .invocationsPerIteration(if (isStressTest) 10_000 else 1_000) + .commonConfiguration() + .customize(isStressTest) + .check(this::class) + + @Test + fun stressTest() = StressOptions() + .iterations(if (isStressTest) 100 else 20) + .invocationsPerIteration(if (isStressTest) 10_000 else 1_000) + .commonConfiguration() + .customize(isStressTest) + .check(this::class) + + private fun > O.commonConfiguration(): O = this + .actorsBefore(if (isStressTest) 3 else 1) + .threads(3) + .actorsPerThread(if (isStressTest) 4 else 2) + .actorsAfter(if (isStressTest) 3 else 0) + .customize(isStressTest) + + override fun extractState(): Any = error("Not implemented") +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt b/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt deleted file mode 100644 index 62ded9f969..0000000000 --- a/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ -package kotlinx.coroutines - -import org.jetbrains.kotlinx.lincheck.* -import org.jetbrains.kotlinx.lincheck.strategy.stress.* -import kotlin.reflect.* - -class LCStressOptionsDefault : StressOptions() { - init { - iterations(100 * stressTestMultiplierCbrt) - invocationsPerIteration(1000 * stressTestMultiplierCbrt) - actorsBefore(if (isStressTest) 3 else 0) - threads(3) - actorsPerThread(if (isStressTest) 3 else 2) - } -} - -fun Options<*,*>.check(testClass: KClass<*>) = LinChecker.check(testClass.java, this) \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt new file mode 100644 index 0000000000..e2ab4d7282 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/ThreadContextElementRestoreTest.kt @@ -0,0 +1,198 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines + +import org.junit.Test +import kotlin.coroutines.* +import kotlin.test.* + +class ThreadContextElementRestoreTest : TestBase() { + private val tl = ThreadLocal() + + // Checks that ThreadLocal context is properly restored after executing the given block inside + // withContext(tl.asContextElement("OK")) code running in different outer contexts + private inline fun check(crossinline block: suspend () -> Unit) = runTest { + val mainDispatcher = coroutineContext[ContinuationInterceptor] as CoroutineDispatcher + // Scenario #1: withContext(ThreadLocal) direct from runTest + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + // Scenario #2: withContext(ThreadLocal) from coroutineScope + coroutineScope { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #3: withContext(ThreadLocal) from undispatched withContext + withContext(CoroutineName("NAME")) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #4: withContext(ThreadLocal) from dispatched withContext + withContext(wrapperDispatcher()) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #5: withContext(ThreadLocal) from withContext(ThreadLocal) + withContext(tl.asContextElement(null)) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #6: withContext(ThreadLocal) from withTimeout + withTimeout(1000) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #7: withContext(ThreadLocal) from withContext(Unconfined) + withContext(Dispatchers.Unconfined) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #8: withContext(ThreadLocal) from withContext(Default) + withContext(Dispatchers.Default) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + // Scenario #9: withContext(ThreadLocal) from withContext(mainDispatcher) + withContext(mainDispatcher) { + withContext(tl.asContextElement("OK")) { + block() + assertEquals("OK", tl.get()) + } + assertEquals(null, tl.get()) + } + } + + @Test + fun testSimpleNoSuspend() = + check {} + + @Test + fun testSimpleDelay() = check { + delay(1) + } + + @Test + fun testSimpleYield() = check { + yield() + } + + private suspend fun deepDelay() { + deepDelay2(); deepDelay2() + } + + private suspend fun deepDelay2() { + delay(1); delay(1) + } + + @Test + fun testDeepDelay() = check { + deepDelay() + } + + private suspend fun deepYield() { + deepYield2(); deepYield2() + } + + private suspend fun deepYield2() { + yield(); yield() + } + + @Test + fun testDeepYield() = check { + deepYield() + } + + @Test + fun testCoroutineScopeDelay() = check { + coroutineScope { + delay(1) + } + } + + @Test + fun testCoroutineScopeYield() = check { + coroutineScope { + yield() + } + } + + @Test + fun testWithContextUndispatchedDelay() = check { + withContext(CoroutineName("INNER")) { + delay(1) + } + } + + @Test + fun testWithContextUndispatchedYield() = check { + withContext(CoroutineName("INNER")) { + yield() + } + } + + @Test + fun testWithContextDispatchedDelay() = check { + withContext(wrapperDispatcher()) { + delay(1) + } + } + + @Test + fun testWithContextDispatchedYield() = check { + withContext(wrapperDispatcher()) { + yield() + } + } + + @Test + fun testWithTimeoutDelay() = check { + withTimeout(1000) { + delay(1) + } + } + + @Test + fun testWithTimeoutYield() = check { + withTimeout(1000) { + yield() + } + } + + @Test + fun testWithUnconfinedContextDelay() = check { + withContext(Dispatchers.Unconfined) { + delay(1) + } + } + @Test + fun testWithUnconfinedContextYield() = check { + withContext(Dispatchers.Unconfined) { + yield() + } + } +} diff --git a/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt new file mode 100644 index 0000000000..49f4a12ee0 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/ThreadContextOrderTest.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines + +import kotlinx.coroutines.internal.* +import org.junit.Test +import kotlin.coroutines.* +import kotlin.test.* + +class ThreadContextOrderTest : TestBase() { + /* + * The test verifies that two thread context elements are correctly nested: + * The restoration order is the reverse of update order. + */ + private val transactionalContext = ThreadLocal() + private val loggingContext = ThreadLocal() + + private val transactionalElement = object : ThreadContextElement { + override val key = ThreadLocalKey(transactionalContext) + + override fun updateThreadContext(context: CoroutineContext): String { + assertEquals("test", loggingContext.get()) + val previous = transactionalContext.get() + transactionalContext.set("tr coroutine") + return previous + } + + override fun restoreThreadContext(context: CoroutineContext, oldState: String) { + assertEquals("test", loggingContext.get()) + assertEquals("tr coroutine", transactionalContext.get()) + transactionalContext.set(oldState) + } + } + + private val loggingElement = object : ThreadContextElement { + override val key = ThreadLocalKey(loggingContext) + + override fun updateThreadContext(context: CoroutineContext): String { + val previous = loggingContext.get() + loggingContext.set("log coroutine") + return previous + } + + override fun restoreThreadContext(context: CoroutineContext, oldState: String) { + assertEquals("log coroutine", loggingContext.get()) + assertEquals("tr coroutine", transactionalContext.get()) + loggingContext.set(oldState) + } + } + + @Test + fun testCorrectOrder() = runTest { + transactionalContext.set("test") + loggingContext.set("test") + launch(transactionalElement + loggingElement) { + assertEquals("log coroutine", loggingContext.get()) + assertEquals("tr coroutine", transactionalContext.get()) + } + assertEquals("test", loggingContext.get()) + assertEquals("test", transactionalContext.get()) + + } +} diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt similarity index 88% rename from kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt rename to kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt index 8836fdc7be..fbd5c0d8f3 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt @@ -3,7 +3,7 @@ */ @file:Suppress("unused") -package kotlinx.coroutines.linearizability +package kotlinx.coroutines.lincheck import kotlinx.coroutines.* import kotlinx.coroutines.channels.* @@ -11,37 +11,37 @@ import kotlinx.coroutines.channels.Channel.Factory.CONFLATED import kotlinx.coroutines.channels.Channel.Factory.RENDEZVOUS import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED import kotlinx.coroutines.selects.* +import org.jetbrains.kotlinx.lincheck.* import org.jetbrains.kotlinx.lincheck.annotations.* import org.jetbrains.kotlinx.lincheck.annotations.Operation import org.jetbrains.kotlinx.lincheck.paramgen.* import org.jetbrains.kotlinx.lincheck.verifier.* -import org.junit.* -class RendezvousChannelLCStressTest : ChannelLCStressTestBase( +class RendezvousChannelLincheckTest : ChannelLincheckTestBase( c = Channel(RENDEZVOUS), sequentialSpecification = SequentialRendezvousChannel::class.java ) class SequentialRendezvousChannel : SequentialIntChannelBase(RENDEZVOUS) -class Array1ChannelLCStressTest : ChannelLCStressTestBase( +class Array1ChannelLincheckTest : ChannelLincheckTestBase( c = Channel(1), sequentialSpecification = SequentialArray1RendezvousChannel::class.java ) class SequentialArray1RendezvousChannel : SequentialIntChannelBase(1) -class Array2ChannelLCStressTest : ChannelLCStressTestBase( +class Array2ChannelLincheckTest : ChannelLincheckTestBase( c = Channel(2), sequentialSpecification = SequentialArray2RendezvousChannel::class.java ) class SequentialArray2RendezvousChannel : SequentialIntChannelBase(2) -class UnlimitedChannelLCStressTest : ChannelLCStressTestBase( +class UnlimitedChannelLincheckTest : ChannelLincheckTestBase( c = Channel(UNLIMITED), sequentialSpecification = SequentialUnlimitedChannel::class.java ) class SequentialUnlimitedChannel : SequentialIntChannelBase(UNLIMITED) -class ConflatedChannelLCStressTest : ChannelLCStressTestBase( +class ConflatedChannelLincheckTest : ChannelLincheckTestBase( c = Channel(CONFLATED), sequentialSpecification = SequentialConflatedChannel::class.java ) @@ -51,8 +51,11 @@ class SequentialConflatedChannel : SequentialIntChannelBase(CONFLATED) Param(name = "value", gen = IntGen::class, conf = "1:5"), Param(name = "closeToken", gen = IntGen::class, conf = "1:3") ) -abstract class ChannelLCStressTestBase(private val c: Channel, private val sequentialSpecification: Class<*>) { - @Operation +abstract class ChannelLincheckTestBase( + private val c: Channel, + private val sequentialSpecification: Class<*> +) : AbstractLincheckTest() { + @Operation(promptCancellation = true) suspend fun send(@Param(name = "value") value: Int): Any = try { c.send(value) } catch (e: NumberedCancellationException) { @@ -74,7 +77,7 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val e.testResult } - @Operation + @Operation(promptCancellation = true) suspend fun receive(): Any = try { c.receive() } catch (e: NumberedCancellationException) { @@ -96,7 +99,7 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val e.testResult } - @Operation + @Operation(causesBlocking = true) fun close(@Param(name = "closeToken") token: Int): Boolean = c.close(NumberedCancellationException(token)) // TODO: this operation should be (and can be!) linearizable, but is not @@ -113,11 +116,8 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val // @Operation fun isEmpty() = c.isEmpty - @Test - fun test() = LCStressOptionsDefault() - .actorsBefore(0) - .sequentialSpecification(sequentialSpecification) - .check(this::class) + override fun > O.customize(isStressTest: Boolean): O = + actorsBefore(0).sequentialSpecification(sequentialSpecification) } private class NumberedCancellationException(number: Int) : CancellationException() { diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeListLincheckTest.kt similarity index 83% rename from kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt rename to kotlinx-coroutines-core/jvm/test/lincheck/LockFreeListLincheckTest.kt index 5f91c640a6..4f1bb6ad02 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeListLincheckTest.kt @@ -3,18 +3,17 @@ */ @file:Suppress("unused") -package kotlinx.coroutines.linearizability +package kotlinx.coroutines.lincheck import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import org.jetbrains.kotlinx.lincheck.annotations.* import org.jetbrains.kotlinx.lincheck.annotations.Operation import org.jetbrains.kotlinx.lincheck.paramgen.* -import org.jetbrains.kotlinx.lincheck.verifier.* -import kotlin.test.* +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* @Param(name = "value", gen = IntGen::class, conf = "1:5") -class LockFreeListLCStressTest : VerifierState() { +class LockFreeListLincheckTest : AbstractLincheckTest() { class Node(val value: Int): LockFreeLinkedListNode() private val q: LockFreeLinkedListHead = LockFreeLinkedListHead() @@ -43,12 +42,12 @@ class LockFreeListLCStressTest : VerifierState() { private fun Any.isSame(value: Int) = this is Node && this.value == value - @Test - fun testAddRemoveLinearizability() = LCStressOptionsDefault().check(this::class) - override fun extractState(): Any { val elements = ArrayList() q.forEach { elements.add(it.value) } return elements } + + override fun ModelCheckingOptions.customize(isStressTest: Boolean) = + checkObstructionFreedom() } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt similarity index 50% rename from kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt rename to kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt index de494cc1e6..2a9164e1d7 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt @@ -3,19 +3,21 @@ */ @file:Suppress("unused") -package kotlinx.coroutines.linearizability +package kotlinx.coroutines.lincheck import kotlinx.coroutines.* import kotlinx.coroutines.internal.* +import org.jetbrains.kotlinx.lincheck.* import org.jetbrains.kotlinx.lincheck.annotations.* import org.jetbrains.kotlinx.lincheck.annotations.Operation import org.jetbrains.kotlinx.lincheck.paramgen.* -import org.jetbrains.kotlinx.lincheck.verifier.* +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* import org.jetbrains.kotlinx.lincheck.verifier.quiescent.* -import kotlin.test.* @Param(name = "value", gen = IntGen::class, conf = "1:3") -internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLCStressTest protected constructor(singleConsumer: Boolean) : VerifierState() { +internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLincheckTest( + val singleConsumer: Boolean +) : AbstractLincheckTest() { @JvmField protected val q = LockFreeTaskQueue(singleConsumer = singleConsumer) @@ -25,20 +27,24 @@ internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLCStressTest prote @Operation fun addLast(@Param(name = "value") value: Int) = q.addLast(value) - @QuiescentConsistent - @Operation(group = "consumer") - fun removeFirstOrNull() = q.removeFirstOrNull() + override fun > O.customize(isStressTest: Boolean): O = + verifier(QuiescentConsistencyVerifier::class.java) override fun extractState() = q.map { it } to q.isClosed() - @Test - fun testWithRemoveForQuiescentConsistency() = LCStressOptionsDefault() - .verifier(QuiescentConsistencyVerifier::class.java) - .check(this::class) + override fun ModelCheckingOptions.customize(isStressTest: Boolean) = + checkObstructionFreedom() } -@OpGroupConfig(name = "consumer", nonParallel = false) -internal class MCLockFreeTaskQueueWithRemoveLCStressTest : AbstractLockFreeTaskQueueWithoutRemoveLCStressTest(singleConsumer = false) +internal class MCLockFreeTaskQueueWithRemoveLincheckTest : AbstractLockFreeTaskQueueWithoutRemoveLincheckTest(singleConsumer = false) { + @QuiescentConsistent + @Operation(blocking = true) + fun removeFirstOrNull() = q.removeFirstOrNull() +} @OpGroupConfig(name = "consumer", nonParallel = true) -internal class SCLockFreeTaskQueueWithRemoveLCStressTest : AbstractLockFreeTaskQueueWithoutRemoveLCStressTest(singleConsumer = true) \ No newline at end of file +internal class SCLockFreeTaskQueueWithRemoveLincheckTest : AbstractLockFreeTaskQueueWithoutRemoveLincheckTest(singleConsumer = true) { + @QuiescentConsistent + @Operation(group = "consumer") + fun removeFirstOrNull() = q.removeFirstOrNull() +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/MutexLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt similarity index 54% rename from kotlinx-coroutines-core/jvm/test/linearizability/MutexLCStressTest.kt rename to kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt index 9542b5d8de..6e350660ae 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/MutexLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt @@ -2,30 +2,31 @@ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused") -package kotlinx.coroutines.linearizability +package kotlinx.coroutines.lincheck import kotlinx.coroutines.* import kotlinx.coroutines.sync.* +import org.jetbrains.kotlinx.lincheck.* import org.jetbrains.kotlinx.lincheck.annotations.Operation -import org.jetbrains.kotlinx.lincheck.verifier.* -import org.junit.* +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* -class MutexLCStressTest : VerifierState() { +class MutexLincheckTest : AbstractLincheckTest() { private val mutex = Mutex() @Operation fun tryLock() = mutex.tryLock() - @Operation + @Operation(promptCancellation = true) suspend fun lock() = mutex.lock() @Operation(handleExceptionsAsResult = [IllegalStateException::class]) fun unlock() = mutex.unlock() - @Test - fun test() = LCStressOptionsDefault() - .actorsBefore(0) - .check(this::class) + override fun > O.customize(isStressTest: Boolean): O = + actorsBefore(0) + + override fun ModelCheckingOptions.customize(isStressTest: Boolean) = + checkObstructionFreedom() override fun extractState() = mutex.isLocked } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentListRemoveLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentListRemoveLincheckTest.kt similarity index 66% rename from kotlinx-coroutines-core/jvm/test/linearizability/SegmentListRemoveLCStressTest.kt rename to kotlinx-coroutines-core/jvm/test/lincheck/SegmentListRemoveLincheckTest.kt index 5daed99829..5a8d7b475d 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentListRemoveLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentListRemoveLincheckTest.kt @@ -4,18 +4,16 @@ @file:Suppress("unused") -package kotlinx.coroutines.linearizability +package kotlinx.coroutines.lincheck import kotlinx.coroutines.* import kotlinx.coroutines.internal.* +import org.jetbrains.kotlinx.lincheck.* import org.jetbrains.kotlinx.lincheck.annotations.* -import org.jetbrains.kotlinx.lincheck.annotations.Operation import org.jetbrains.kotlinx.lincheck.paramgen.* -import org.jetbrains.kotlinx.lincheck.verifier.* -import org.junit.* +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* - -class SegmentListRemoveLCStressTest : VerifierState() { +class SegmentListRemoveLincheckTest : AbstractLincheckTest() { private val q = SegmentBasedQueue() private val segments: Array> @@ -29,6 +27,9 @@ class SegmentListRemoveLCStressTest : VerifierState() { segments[index].removeSegment() } + override fun > O.customize(isStressTest: Boolean): O = this + .actorsBefore(0).actorsAfter(0) + override fun extractState() = segments.map { it.logicallyRemoved } @Validate @@ -37,9 +38,6 @@ class SegmentListRemoveLCStressTest : VerifierState() { q.checkAllSegmentsAreNotLogicallyRemoved() } - @Test - fun test() = LCStressOptionsDefault() - .actorsBefore(0) - .actorsAfter(0) - .check(this::class) + override fun ModelCheckingOptions.customize(isStressTest: Boolean) = + checkObstructionFreedom() } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentQueueLincheckTest.kt similarity index 78% rename from kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt rename to kotlinx-coroutines-core/jvm/test/lincheck/SegmentQueueLincheckTest.kt index 89bf8dfaa4..76a59e39e7 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentQueueLincheckTest.kt @@ -3,18 +3,17 @@ */ @file:Suppress("unused") -package kotlinx.coroutines.linearizability +package kotlinx.coroutines.lincheck import kotlinx.coroutines.* import kotlinx.coroutines.internal.SegmentBasedQueue import org.jetbrains.kotlinx.lincheck.annotations.* import org.jetbrains.kotlinx.lincheck.annotations.Operation import org.jetbrains.kotlinx.lincheck.paramgen.* -import org.jetbrains.kotlinx.lincheck.verifier.* -import org.junit.* +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* @Param(name = "value", gen = IntGen::class, conf = "1:5") -class SegmentQueueLCStressTest : VerifierState() { +class SegmentQueueLincheckTest : AbstractLincheckTest() { private val q = SegmentBasedQueue() @Operation @@ -40,6 +39,6 @@ class SegmentQueueLCStressTest : VerifierState() { return elements to closed } - @Test - fun test() = LCStressOptionsDefault().check(this::class) + override fun ModelCheckingOptions.customize(isStressTest: Boolean) = + checkObstructionFreedom() } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt new file mode 100644 index 0000000000..84ce773c15 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +@file:Suppress("unused") +package kotlinx.coroutines.lincheck + +import kotlinx.coroutines.* +import kotlinx.coroutines.sync.* +import org.jetbrains.kotlinx.lincheck.* +import org.jetbrains.kotlinx.lincheck.annotations.Operation +import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.* + +abstract class SemaphoreLincheckTestBase(permits: Int) : AbstractLincheckTest() { + private val semaphore = Semaphore(permits) + + @Operation + fun tryAcquire() = semaphore.tryAcquire() + + @Operation(promptCancellation = true) + suspend fun acquire() = semaphore.acquire() + + @Operation(handleExceptionsAsResult = [IllegalStateException::class]) + fun release() = semaphore.release() + + override fun > O.customize(isStressTest: Boolean): O = + actorsBefore(0) + + override fun extractState() = semaphore.availablePermits + + override fun ModelCheckingOptions.customize(isStressTest: Boolean) = + checkObstructionFreedom() +} + +class Semaphore1LincheckTest : SemaphoreLincheckTestBase(1) +class Semaphore2LincheckTest : SemaphoreLincheckTestBase(2) \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SemaphoreLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/SemaphoreLCStressTest.kt deleted file mode 100644 index 52902f4987..0000000000 --- a/kotlinx-coroutines-core/jvm/test/linearizability/SemaphoreLCStressTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ -@file:Suppress("unused") -package kotlinx.coroutines.linearizability - -import kotlinx.coroutines.* -import kotlinx.coroutines.sync.* -import org.jetbrains.kotlinx.lincheck.annotations.Operation -import org.jetbrains.kotlinx.lincheck.verifier.* -import org.junit.* - -abstract class SemaphoreLCStressTestBase(permits: Int) : VerifierState() { - private val semaphore = Semaphore(permits) - - @Operation - fun tryAcquire() = semaphore.tryAcquire() - - @Operation - suspend fun acquire() = semaphore.acquire() - - @Operation(handleExceptionsAsResult = [IllegalStateException::class]) - fun release() = semaphore.release() - - @Test - fun test() = LCStressOptionsDefault() - .actorsBefore(0) - .check(this::class) - - override fun extractState() = semaphore.availablePermits -} - -class Semaphore1LCStressTest : SemaphoreLCStressTestBase(1) -class Semaphore2LCStressTest : SemaphoreLCStressTestBase(2) \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt b/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt index a5c83d329a..233e442098 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt @@ -1,11 +1,11 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling -internal class TestTimeSource(var time: Long) : TimeSource() { +internal class TestTimeSource(var time: Long) : SchedulerTimeSource() { override fun nanoTime() = time diff --git a/kotlinx-coroutines-core/knit.properties b/kotlinx-coroutines-core/knit.properties index 93ce87db8f..5b57398b8d 100644 --- a/kotlinx-coroutines-core/knit.properties +++ b/kotlinx-coroutines-core/knit.properties @@ -1,5 +1,5 @@ # -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # knit.package=kotlinx.coroutines.examples diff --git a/kotlinx-coroutines-core/native/src/Builders.kt b/kotlinx-coroutines-core/native/src/Builders.kt index 3554dc604e..7425a05542 100644 --- a/kotlinx-coroutines-core/native/src/Builders.kt +++ b/kotlinx-coroutines-core/native/src/Builders.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/CompletionHandler.kt b/kotlinx-coroutines-core/native/src/CompletionHandler.kt index 706f6c498e..4835f7968e 100644 --- a/kotlinx-coroutines-core/native/src/CompletionHandler.kt +++ b/kotlinx-coroutines-core/native/src/CompletionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/CoroutineContext.kt b/kotlinx-coroutines-core/native/src/CoroutineContext.kt index 4ec1289ee7..47afd8aded 100644 --- a/kotlinx-coroutines-core/native/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/native/src/CoroutineContext.kt @@ -1,9 +1,10 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines +import kotlinx.coroutines.internal.* import kotlin.coroutines.* import kotlin.native.concurrent.* @@ -38,5 +39,13 @@ public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): // No debugging facilities on native internal actual inline fun withCoroutineContext(context: CoroutineContext, countOrElement: Any?, block: () -> T): T = block() +internal actual inline fun withContinuationContext(continuation: Continuation<*>, countOrElement: Any?, block: () -> T): T = block() internal actual fun Continuation<*>.toDebugString(): String = toString() internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on native + +internal actual class UndispatchedCoroutine actual constructor( + context: CoroutineContext, + uCont: Continuation +) : ScopeCoroutine(context, uCont) { + override fun afterResume(state: Any?) = uCont.resumeWith(recoverResult(state, uCont)) +} diff --git a/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt index dff845b27f..b0aa86339a 100644 --- a/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/Debug.kt b/kotlinx-coroutines-core/native/src/Debug.kt index 1fa0ec7ff3..a0a8d272f8 100644 --- a/kotlinx-coroutines-core/native/src/Debug.kt +++ b/kotlinx-coroutines-core/native/src/Debug.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/Dispatchers.kt b/kotlinx-coroutines-core/native/src/Dispatchers.kt index c06b7c2f0a..4e5facfeee 100644 --- a/kotlinx-coroutines-core/native/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/native/src/Dispatchers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/EventLoop.kt b/kotlinx-coroutines-core/native/src/EventLoop.kt index b397d6f182..925cbe9971 100644 --- a/kotlinx-coroutines-core/native/src/EventLoop.kt +++ b/kotlinx-coroutines-core/native/src/EventLoop.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/Exceptions.kt b/kotlinx-coroutines-core/native/src/Exceptions.kt index c82199a429..7c76bc6d2c 100644 --- a/kotlinx-coroutines-core/native/src/Exceptions.kt +++ b/kotlinx-coroutines-core/native/src/Exceptions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/Runnable.kt b/kotlinx-coroutines-core/native/src/Runnable.kt index 19710f971b..b8e6980b22 100644 --- a/kotlinx-coroutines-core/native/src/Runnable.kt +++ b/kotlinx-coroutines-core/native/src/Runnable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/SchedulerTask.kt b/kotlinx-coroutines-core/native/src/SchedulerTask.kt index 4154d53e07..781e32213c 100644 --- a/kotlinx-coroutines-core/native/src/SchedulerTask.kt +++ b/kotlinx-coroutines-core/native/src/SchedulerTask.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/WorkerMain.native.kt b/kotlinx-coroutines-core/native/src/WorkerMain.native.kt index 84cc9f42b9..bf8fe6ae61 100644 --- a/kotlinx-coroutines-core/native/src/WorkerMain.native.kt +++ b/kotlinx-coroutines-core/native/src/WorkerMain.native.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt index 4705471907..bc7a1ffc26 100644 --- a/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt +++ b/kotlinx-coroutines-core/native/src/flow/internal/FlowExceptions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt index ace633ccc6..b74b547d31 100644 --- a/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt +++ b/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal diff --git a/kotlinx-coroutines-core/native/src/internal/Concurrent.kt b/kotlinx-coroutines-core/native/src/internal/Concurrent.kt index 486dc8f057..b379c6ac15 100644 --- a/kotlinx-coroutines-core/native/src/internal/Concurrent.kt +++ b/kotlinx-coroutines-core/native/src/internal/Concurrent.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt index b925317b3d..30f063a517 100644 --- a/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt +++ b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/LinkedList.kt b/kotlinx-coroutines-core/native/src/internal/LinkedList.kt index 99ab042f3c..a8aed04461 100644 --- a/kotlinx-coroutines-core/native/src/internal/LinkedList.kt +++ b/kotlinx-coroutines-core/native/src/internal/LinkedList.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("NO_EXPLICIT_RETURN_TYPE_IN_API_MODE", "NO_EXPLICIT_VISIBILITY_IN_API_MODE") diff --git a/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt b/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt index 398cb63bc2..c8c6fffe00 100644 --- a/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt +++ b/kotlinx-coroutines-core/native/src/internal/LocalAtomics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt index a13a141f4d..47d3fdbac9 100644 --- a/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt +++ b/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt index 49f043da36..d93af9f4d2 100644 --- a/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt +++ b/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/Synchronized.kt b/kotlinx-coroutines-core/native/src/internal/Synchronized.kt index 0911dbe115..dcbb20217d 100644 --- a/kotlinx-coroutines-core/native/src/internal/Synchronized.kt +++ b/kotlinx-coroutines-core/native/src/internal/Synchronized.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt index 564630f623..4fb334ed16 100644 --- a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt +++ b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt index 4a9513ab9e..2370e42ff4 100644 --- a/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt +++ b/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt index 09f501a4f5..e1825d67b8 100644 --- a/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt +++ b/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal diff --git a/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt b/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt index 3445cb9897..010bd03089 100644 --- a/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt +++ b/kotlinx-coroutines-core/nativeDarwin/src/WorkerMain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt b/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt index cac0530e4e..f3bd99a43a 100644 --- a/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt +++ b/kotlinx-coroutines-core/nativeOther/src/WorkerMain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md index fc9637a9d5..f048040bba 100644 --- a/kotlinx-coroutines-debug/README.md +++ b/kotlinx-coroutines-debug/README.md @@ -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.4.2.jar`. +You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.4.3.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. @@ -264,10 +264,13 @@ More than one file was found with OS independent path 'win32-x86-64/attach_hotsp --> + [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html + + [DebugProbes]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/index.html [DebugProbes.install]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/install.html [DebugProbes.dumpCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines.html @@ -275,6 +278,9 @@ More than one file was found with OS independent path 'win32-x86-64/attach_hotsp [DebugProbes.printJob]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-job.html [DebugProbes.printScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-scope.html [DebugProbes.enableCreationStackTraces]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/enable-creation-stack-traces.html + + [CoroutinesTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug.junit4/-coroutines-timeout/index.html + diff --git a/kotlinx-coroutines-debug/build.gradle b/kotlinx-coroutines-debug/build.gradle index 2a11bbb38c..46f894d1a4 100644 --- a/kotlinx-coroutines-debug/build.gradle +++ b/kotlinx-coroutines-debug/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: "com.github.johnrengelman.shadow" diff --git a/kotlinx-coroutines-debug/src/CoroutineInfo.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt index ce1478ad07..62728adab9 100644 --- a/kotlinx-coroutines-debug/src/CoroutineInfo.kt +++ b/kotlinx-coroutines-debug/src/CoroutineInfo.kt @@ -1,7 +1,7 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNUSED") +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNUSED") package kotlinx.coroutines.debug import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt b/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt index 091e8eb16e..7dd7d58d21 100644 --- a/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt +++ b/kotlinx-coroutines-debug/src/CoroutinesBlockHoundIntegration.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") package kotlinx.coroutines.debug diff --git a/kotlinx-coroutines-debug/src/DebugProbes.kt b/kotlinx-coroutines-debug/src/DebugProbes.kt index 254385f942..373864adb8 100644 --- a/kotlinx-coroutines-debug/src/DebugProbes.kt +++ b/kotlinx-coroutines-debug/src/DebugProbes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UNUSED", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") diff --git a/kotlinx-coroutines-debug/src/internal/Attach.kt b/kotlinx-coroutines-debug/src/internal/Attach.kt index cd4cc2a52e..f38447f72a 100644 --- a/kotlinx-coroutines-debug/src/internal/Attach.kt +++ b/kotlinx-coroutines-debug/src/internal/Attach.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused") package kotlinx.coroutines.debug.internal diff --git a/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt b/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt index 4854f5d7c6..34f1afec65 100644 --- a/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt +++ b/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused", "UNUSED_PARAMETER") diff --git a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt index 0510764a0c..12bc947586 100644 --- a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.junit4 diff --git a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt index 72413b91f2..4baf409de8 100644 --- a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.debug.junit4 diff --git a/kotlinx-coroutines-debug/test/DebugProbesTest.kt b/kotlinx-coroutines-debug/test/DebugProbesTest.kt index 3b32db3a5a..01b2da0006 100644 --- a/kotlinx-coroutines-debug/test/DebugProbesTest.kt +++ b/kotlinx-coroutines-debug/test/DebugProbesTest.kt @@ -45,6 +45,7 @@ class DebugProbesTest : DebugTestBase() { "\tat kotlinx.coroutines.DeferredCoroutine.await\$suspendImpl(Builders.common.kt)\n" + "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt)\n" + "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt)\n" + + "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:62)\n" + "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)\n" + "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt)\n" + @@ -76,6 +77,7 @@ class DebugProbesTest : DebugTestBase() { "\tat kotlinx.coroutines.DeferredCoroutine.await\$suspendImpl(Builders.common.kt)\n" + "\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:71)\n" + "\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:66)\n" + + "\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithSanitizedProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:87)\n" + "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + diff --git a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt index bf6cbdf10c..67a283d00a 100644 --- a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt +++ b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt @@ -63,6 +63,7 @@ class SanitizedProbesTest : DebugTestBase() { "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + + "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt)\n" + "\tat kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.createActiveDeferred(SanitizedProbesTest.kt:62)\n" + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$createActiveDeferred(SanitizedProbesTest.kt:16)\n" + @@ -87,10 +88,11 @@ class SanitizedProbesTest : DebugTestBase() { "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@1b68b9a4, state: SUSPENDED\n" + - "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1.invokeSuspend(SanitizedProbesTest.kt:143)\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1\$1\$1.invokeSuspend(SanitizedProbesTest.kt)\n" + "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)\n" + + "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.launch\$default(Builders.common.kt)\n" + "\tat kotlinx.coroutines.BuildersKt.launch\$default(Unknown Source)\n" + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.launchSelector(SanitizedProbesTest.kt:100)\n" + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$launchSelector(SanitizedProbesTest.kt:16)\n" + diff --git a/kotlinx-coroutines-test/README.md b/kotlinx-coroutines-test/README.md index 6022955254..dd18d96662 100644 --- a/kotlinx-coroutines-test/README.md +++ b/kotlinx-coroutines-test/README.md @@ -9,7 +9,7 @@ This package provides testing utilities for effectively testing coroutines. Add `kotlinx-coroutines-test` to your project test dependencies: ``` dependencies { - testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3' } ``` @@ -431,6 +431,7 @@ If you have any suggestions for improvements to this experimental API please sha + [Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html @@ -440,8 +441,10 @@ If you have any suggestions for improvements to this experimental API please sha [CoroutineStart]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-start/index.html [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [ExperimentalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-experimental-coroutines-api/index.html + + [setMain]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/kotlinx.coroutines.-dispatchers/set-main.html [runBlockingTest]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/run-blocking-test.html [UncompletedCoroutinesError]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-uncompleted-coroutines-error/index.html @@ -454,4 +457,5 @@ If you have any suggestions for improvements to this experimental API please sha [TestCoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-exception-handler/index.html [TestCoroutineScope.cleanupTestCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-scope/cleanup-test-coroutines.html [DelayController.cleanupTestCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-delay-controller/cleanup-test-coroutines.html + diff --git a/kotlinx-coroutines-test/build.gradle.kts b/kotlinx-coroutines-test/build.gradle.kts index 825c95f4c8..fef0a146f7 100644 --- a/kotlinx-coroutines-test/build.gradle.kts +++ b/kotlinx-coroutines-test/build.gradle.kts @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + dependencies { implementation(project(":kotlinx-coroutines-debug")) } diff --git a/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro b/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro index 41c9eb0722..1fdfb78711 100644 --- a/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro +++ b/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro @@ -4,6 +4,6 @@ -keepnames class kotlinx.coroutines.android.AndroidDispatcherFactory {} # Most of volatile fields are updated with AFU and should not be mangled --keepclassmembernames class kotlinx.** { +-keepclassmembers class kotlinx.coroutines.** { volatile ; } diff --git a/kotlinx-coroutines-test/src/DelayController.kt b/kotlinx-coroutines-test/src/DelayController.kt index a777d4b9a3..6e72222718 100644 --- a/kotlinx-coroutines-test/src/DelayController.kt +++ b/kotlinx-coroutines-test/src/DelayController.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test diff --git a/kotlinx-coroutines-test/src/TestBuilders.kt b/kotlinx-coroutines-test/src/TestBuilders.kt index 88fa01b7b8..b40769ee97 100644 --- a/kotlinx-coroutines-test/src/TestBuilders.kt +++ b/kotlinx-coroutines-test/src/TestBuilders.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test diff --git a/kotlinx-coroutines-test/src/TestCoroutineDispatcher.kt b/kotlinx-coroutines-test/src/TestCoroutineDispatcher.kt index cad2636f97..f6464789fc 100644 --- a/kotlinx-coroutines-test/src/TestCoroutineDispatcher.kt +++ b/kotlinx-coroutines-test/src/TestCoroutineDispatcher.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test diff --git a/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt b/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt index ed08fbcdd4..66eb235906 100644 --- a/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt +++ b/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test diff --git a/kotlinx-coroutines-test/src/TestCoroutineScope.kt b/kotlinx-coroutines-test/src/TestCoroutineScope.kt index 4034fcaa74..7c1ff872ec 100644 --- a/kotlinx-coroutines-test/src/TestCoroutineScope.kt +++ b/kotlinx-coroutines-test/src/TestCoroutineScope.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test diff --git a/kotlinx-coroutines-test/src/TestDispatchers.kt b/kotlinx-coroutines-test/src/TestDispatchers.kt index a247ca8365..bf068f9d7b 100644 --- a/kotlinx-coroutines-test/src/TestDispatchers.kt +++ b/kotlinx-coroutines-test/src/TestDispatchers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("unused") @file:JvmName("TestDispatchers") diff --git a/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt b/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt index baa1aa5fd2..af1eee42c4 100644 --- a/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt +++ b/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test.internal diff --git a/reactive/knit.properties b/reactive/knit.properties index 18aecba666..452cd2f17b 100644 --- a/reactive/knit.properties +++ b/reactive/knit.properties @@ -1,6 +1,6 @@ # -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # knit.package=kotlinx.coroutines.rx2.guide -knit.dir=kotlinx-coroutines-rx2/test/guide/ \ No newline at end of file +knit.dir=kotlinx-coroutines-rx2/test/guide/ diff --git a/reactive/kotlinx-coroutines-jdk9/build.gradle.kts b/reactive/kotlinx-coroutines-jdk9/build.gradle.kts index c721746f3b..38c6735cc4 100644 --- a/reactive/kotlinx-coroutines-jdk9/build.gradle.kts +++ b/reactive/kotlinx-coroutines-jdk9/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ dependencies { diff --git a/reactive/kotlinx-coroutines-jdk9/src/Await.kt b/reactive/kotlinx-coroutines-jdk9/src/Await.kt index 88268890e2..4febf4079c 100644 --- a/reactive/kotlinx-coroutines-jdk9/src/Await.kt +++ b/reactive/kotlinx-coroutines-jdk9/src/Await.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.jdk9 diff --git a/reactive/kotlinx-coroutines-jdk9/src/Publish.kt b/reactive/kotlinx-coroutines-jdk9/src/Publish.kt index 6fd9a5e75b..3db0d5da4c 100644 --- a/reactive/kotlinx-coroutines-jdk9/src/Publish.kt +++ b/reactive/kotlinx-coroutines-jdk9/src/Publish.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.jdk9 diff --git a/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt b/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt index 5d546dffd3..d3942a1629 100644 --- a/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt +++ b/reactive/kotlinx-coroutines-jdk9/src/ReactiveFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.jdk9 diff --git a/reactive/kotlinx-coroutines-reactive/README.md b/reactive/kotlinx-coroutines-reactive/README.md index aed262263d..b6466b2da7 100644 --- a/reactive/kotlinx-coroutines-reactive/README.md +++ b/reactive/kotlinx-coroutines-reactive/README.md @@ -32,11 +32,16 @@ Suspending extension functions and suspending iteration: + [Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html + + [ProducerScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-producer-scope/index.html + + [kotlinx.coroutines.reactive.publish]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/publish.html [Publisher.asFlow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/org.reactivestreams.-publisher/as-flow.html [Flow.asPublisher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/kotlinx.coroutines.flow.-flow/as-publisher.html @@ -45,6 +50,7 @@ Suspending extension functions and suspending iteration: [org.reactivestreams.Publisher.awaitFirstOrElse]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/org.reactivestreams.-publisher/await-first-or-else.html [org.reactivestreams.Publisher.awaitFirstOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/org.reactivestreams.-publisher/await-first-or-null.html [org.reactivestreams.Publisher.awaitSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactive/kotlinx.coroutines.reactive/org.reactivestreams.-publisher/await-single.html + # Package kotlinx.coroutines.reactive diff --git a/reactive/kotlinx-coroutines-reactive/build.gradle.kts b/reactive/kotlinx-coroutines-reactive/build.gradle.kts index 2ace4f9fcc..128d4d86ab 100644 --- a/reactive/kotlinx-coroutines-reactive/build.gradle.kts +++ b/reactive/kotlinx-coroutines-reactive/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ val reactiveStreamsVersion = property("reactive_streams_version") diff --git a/reactive/kotlinx-coroutines-reactive/src/Await.kt b/reactive/kotlinx-coroutines-reactive/src/Await.kt index 7956c26010..e9f6955085 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Await.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Await.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactive diff --git a/reactive/kotlinx-coroutines-reactive/src/Channel.kt b/reactive/kotlinx-coroutines-reactive/src/Channel.kt index 26f14ec63d..352a505a5f 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Channel.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Channel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactive diff --git a/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt b/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt index d5390fd6f2..043e223d49 100644 --- a/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt +++ b/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactive diff --git a/reactive/kotlinx-coroutines-reactive/src/Convert.kt b/reactive/kotlinx-coroutines-reactive/src/Convert.kt index 727eff8b48..8f4b26d377 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Convert.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Convert.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactive diff --git a/reactive/kotlinx-coroutines-reactive/src/Migration.kt b/reactive/kotlinx-coroutines-reactive/src/Migration.kt index 4e0dca63de..1bba746c03 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Migration.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Migration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass diff --git a/reactive/kotlinx-coroutines-reactive/src/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/Publish.kt index ddfd7f8aa3..35878b04b2 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Publish.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Publish.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt index 5834220c40..614e9ead1e 100644 --- a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt +++ b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactive diff --git a/reactive/kotlinx-coroutines-reactor/README.md b/reactive/kotlinx-coroutines-reactor/README.md index cd4a42a34c..7028310621 100644 --- a/reactive/kotlinx-coroutines-reactor/README.md +++ b/reactive/kotlinx-coroutines-reactor/README.md @@ -32,13 +32,18 @@ Conversion functions: + [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html + + [Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html + + [mono]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/mono.html [flux]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/flux.html [Flow.asFlux]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/kotlinx.coroutines.flow.-flow/as-flux.html @@ -47,6 +52,7 @@ Conversion functions: [kotlinx.coroutines.Deferred.asMono]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/kotlinx.coroutines.-deferred/as-mono.html [kotlinx.coroutines.channels.ReceiveChannel.asFlux]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/kotlinx.coroutines.channels.-receive-channel/as-flux.html [reactor.core.scheduler.Scheduler.asCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/reactor.core.scheduler.-scheduler/as-coroutine-dispatcher.html + # Package kotlinx.coroutines.reactor diff --git a/reactive/kotlinx-coroutines-reactor/build.gradle.kts b/reactive/kotlinx-coroutines-reactor/build.gradle.kts index d5fd208a27..03af7f4fda 100644 --- a/reactive/kotlinx-coroutines-reactor/build.gradle.kts +++ b/reactive/kotlinx-coroutines-reactor/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ val reactorVersion = version("reactor") @@ -9,6 +9,10 @@ dependencies { compile(project(":kotlinx-coroutines-reactive")) } +java { + targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_1_8 +} tasks { compileKotlin { diff --git a/reactive/kotlinx-coroutines-reactor/src/Convert.kt b/reactive/kotlinx-coroutines-reactor/src/Convert.kt index dc264f8d89..7807549ce1 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Convert.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Convert.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor diff --git a/reactive/kotlinx-coroutines-reactor/src/Flux.kt b/reactive/kotlinx-coroutines-reactor/src/Flux.kt index addc528c32..8d4f9cc969 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Flux.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Flux.kt @@ -1,6 +1,6 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-reactor/src/Migration.kt b/reactive/kotlinx-coroutines-reactor/src/Migration.kt index f0c24bb08d..ec5674d932 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Migration.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Migration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmName("FlowKt") diff --git a/reactive/kotlinx-coroutines-reactor/src/Mono.kt b/reactive/kotlinx-coroutines-reactor/src/Mono.kt index 503c891ea4..2d595c961f 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Mono.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Mono.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt index 69467ad8b1..be4b2c7d45 100644 --- a/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt +++ b/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor @@ -24,7 +24,7 @@ import kotlinx.coroutines.reactive.* * #### Propagating ReactorContext to Reactor's Context * ``` * val flux = myDatabaseService.getUsers() - * .subscriberContext() { ctx -> println(ctx); ctx } + * .contextWrite { ctx -> println(ctx); ctx } * flux.await() // Will print "null" * * // Now add ReactorContext @@ -43,7 +43,7 @@ import kotlinx.coroutines.reactive.* * .subscribe() // Will print 'Reactor context in Flow: null' * // Add subscriber's context * flow.asFlux() - * .subscriberContext { ctx -> ctx.put("answer", 42) } + * .contextWrite { ctx -> ctx.put("answer", 42) } * .subscribe() // Will print "Reactor context in Flow: Context{'answer'=42}" * ``` */ diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt index a9d140a9fd..f65d2ec2f0 100644 --- a/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt +++ b/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor @@ -18,8 +18,8 @@ internal class ReactorContextInjector : ContextInjector { override fun injectCoroutineContext(publisher: Publisher, coroutineContext: CoroutineContext): Publisher { val reactorContext = coroutineContext[ReactorContext]?.context ?: return publisher return when(publisher) { - is Mono -> publisher.subscriberContext(reactorContext) - is Flux -> publisher.subscriberContext(reactorContext) + is Mono -> publisher.contextWrite(reactorContext) + is Flux -> publisher.contextWrite(reactorContext) else -> publisher } } diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt index a478ab1ef8..0fc743f937 100644 --- a/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt +++ b/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor diff --git a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt index 4fb5514322..03b052b6b1 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor diff --git a/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt b/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt index cecc89592e..dbe97b17d8 100644 --- a/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt @@ -18,8 +18,8 @@ class FlowAsFluxTest : TestBase() { (1..4).forEach { i -> emit(createMono(i).awaitFirst()) } } .asFlux() - .subscriberContext(Context.of(1, "1")) - .subscriberContext(Context.of(2, "2", 3, "3", 4, "4")) + .contextWrite(Context.of(1, "1")) + .contextWrite(Context.of(2, "2", 3, "3", 4, "4")) val list = flux.collectList().block()!! assertEquals(listOf("1", "2", "3", "4"), list) } @@ -36,7 +36,7 @@ class FlowAsFluxTest : TestBase() { it.next("OK") it.complete() } - .subscriberContext { ctx -> + .contextWrite { ctx -> expect(2) assertEquals("CTX", ctx.get(1)) ctx @@ -58,7 +58,7 @@ class FlowAsFluxTest : TestBase() { it.next("OK") it.complete() } - .subscriberContext { ctx -> + .contextWrite { ctx -> expect(2) assertEquals("CTX", ctx.get(1)) ctx diff --git a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt index 551988b814..0271483fc1 100644 --- a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt @@ -235,7 +235,7 @@ class MonoTest : TestBase() { } finally { throw TestException() // would not be able to handle it since mono is disposed } - }.subscriberContext { Context.of("reactor.onOperatorError.local", handler) } + }.contextWrite { Context.of("reactor.onOperatorError.local", handler) } mono.subscribe(object : Subscriber { override fun onSubscribe(s: Subscription) { expect(2) diff --git a/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt b/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt index 3681261b0c..aff29241c9 100644 --- a/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/ReactorContextTest.kt @@ -18,8 +18,8 @@ class ReactorContextTest : TestBase() { buildString { (1..7).forEach { append(ctx.getOrDefault(it, "noValue")) } } - } .subscriberContext(Context.of(2, "2", 3, "3", 4, "4", 5, "5")) - .subscriberContext { ctx -> ctx.put(6, "6") } + } .contextWrite(Context.of(2, "2", 3, "3", 4, "4", 5, "5")) + .contextWrite { ctx -> ctx.put(6, "6") } assertEquals(mono.awaitFirst(), "1234567") } @@ -29,8 +29,8 @@ class ReactorContextTest : TestBase() { val ctx = reactorContext() (1..7).forEach { send(ctx.getOrDefault(it, "noValue")) } } - .subscriberContext(Context.of(2, "2", 3, "3", 4, "4", 5, "5")) - .subscriberContext { ctx -> ctx.put(6, "6") } + .contextWrite(Context.of(2, "2", 3, "3", 4, "4", 5, "5")) + .contextWrite { ctx -> ctx.put(6, "6") } val list = flux.collectList().block()!! assertEquals((1..7).map { it.toString() }, list) } @@ -42,7 +42,7 @@ class ReactorContextTest : TestBase() { buildString { (1..3).forEach { append(ctx.getOrDefault(it, "noValue")) } } - } .subscriberContext(Context.of(2, "2")) + } .contextWrite(Context.of(2, "2")) .awaitFirst() assertEquals(result, "123") } diff --git a/reactive/kotlinx-coroutines-rx2/README.md b/reactive/kotlinx-coroutines-rx2/README.md index f0fbeb001e..40fe122f89 100644 --- a/reactive/kotlinx-coroutines-rx2/README.md +++ b/reactive/kotlinx-coroutines-rx2/README.md @@ -52,15 +52,22 @@ Conversion functions: + [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html + + [ProducerScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-producer-scope/index.html [ReceiveChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/index.html + + [Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html + + [rxCompletable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/rx-completable.html [rxMaybe]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/rx-maybe.html [rxSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/rx-single.html @@ -84,6 +91,7 @@ Conversion functions: [kotlinx.coroutines.Deferred.asSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/kotlinx.coroutines.-deferred/as-single.html [kotlinx.coroutines.channels.ReceiveChannel.asObservable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/kotlinx.coroutines.channels.-receive-channel/as-observable.html [io.reactivex.Scheduler.asCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/io.reactivex.-scheduler/as-coroutine-dispatcher.html + # Package kotlinx.coroutines.rx2 diff --git a/reactive/kotlinx-coroutines-rx2/build.gradle b/reactive/kotlinx-coroutines-rx2/build.gradle index 6d2c4abcc8..73f76c3dfe 100644 --- a/reactive/kotlinx-coroutines-rx2/build.gradle +++ b/reactive/kotlinx-coroutines-rx2/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ dependencies { diff --git a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt index d9435b6b9e..6e162c9a4d 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx2 diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt index f7596f27d0..0fe43f1cee 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx2 diff --git a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt index 633693e756..a129196a13 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx2 diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt index bc91fa53e0..d0a43fb1a4 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt index 41c82ed0e8..14c24942ac 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx2 diff --git a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt index 78d397c3b3..8dfe95762e 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt index bfbcb38d92..f5ed48b9a9 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt index 2f483879b8..6d11cb9c35 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt index 9952eb91a0..0262fc12f7 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx2 diff --git a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt index 23040601df..b8012b6de9 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-rx3/README.md b/reactive/kotlinx-coroutines-rx3/README.md index 3aa73eb969..f9d3c5a86d 100644 --- a/reactive/kotlinx-coroutines-rx3/README.md +++ b/reactive/kotlinx-coroutines-rx3/README.md @@ -49,14 +49,21 @@ Conversion functions: + [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html + + [ProducerScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-producer-scope/index.html + + [Flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html + + [rxCompletable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx3/kotlinx.coroutines.rx3/rx-completable.html [rxMaybe]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx3/kotlinx.coroutines.rx3/rx-maybe.html [rxSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx3/kotlinx.coroutines.rx3/rx-single.html @@ -77,6 +84,7 @@ Conversion functions: [kotlinx.coroutines.Job.asCompletable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx3/kotlinx.coroutines.rx3/kotlinx.coroutines.-job/as-completable.html [kotlinx.coroutines.Deferred.asSingle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx3/kotlinx.coroutines.rx3/kotlinx.coroutines.-deferred/as-single.html [io.reactivex.rxjava3.core.Scheduler.asCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx3/kotlinx.coroutines.rx3/io.reactivex.rxjava3.core.-scheduler/as-coroutine-dispatcher.html + # Package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/build.gradle b/reactive/kotlinx-coroutines-rx3/build.gradle index ced694abd3..a5de40d8df 100644 --- a/reactive/kotlinx-coroutines-rx3/build.gradle +++ b/reactive/kotlinx-coroutines-rx3/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt b/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt index e52556e4e9..8ac0a10ce7 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxAwait.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt b/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt index 0b57b8bbe4..2995159850 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxCancellable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt b/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt index 737cf6710d..76333f2eb8 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxChannel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt b/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt index 54b412f171..f4c5d7e768 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxCompletable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt index 0978423ac9..63e30f2617 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxConvert.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt b/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt index 2de46a6a20..445a61401f 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxFlowable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt index 4d55ef5ffa..ca1d5b59ee 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt index 102d06ea60..7bd07750fe 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxObservable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt b/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt index a426aea6ba..24c3f11834 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxScheduler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt b/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt index 225df93ad1..f4d07fb40f 100644 --- a/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt +++ b/reactive/kotlinx-coroutines-rx3/src/RxSingle.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx3 diff --git a/settings.gradle b/settings.gradle index 3a07891799..37fa6757cf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ pluginManagement { diff --git a/site/build.gradle.kts b/site/build.gradle.kts index eba7b1a1bc..003ae76262 100644 --- a/site/build.gradle.kts +++ b/site/build.gradle.kts @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + import groovy.lang.* /* diff --git a/stdlib-stubs/build.gradle.kts b/stdlib-stubs/build.gradle.kts index 6b9d65555a..201ac43cb0 100644 --- a/stdlib-stubs/build.gradle.kts +++ b/stdlib-stubs/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile diff --git a/stdlib-stubs/src/Continuation.kt b/stdlib-stubs/src/Continuation.kt index 662f9dae8e..66d672afea 100644 --- a/stdlib-stubs/src/Continuation.kt +++ b/stdlib-stubs/src/Continuation.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin.coroutines diff --git a/stdlib-stubs/src/ContinuationInterceptor.kt b/stdlib-stubs/src/ContinuationInterceptor.kt index ebf0a33532..5c96e82dff 100644 --- a/stdlib-stubs/src/ContinuationInterceptor.kt +++ b/stdlib-stubs/src/ContinuationInterceptor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin.coroutines diff --git a/stdlib-stubs/src/CoroutineContext.kt b/stdlib-stubs/src/CoroutineContext.kt index ac216a0bec..6861198da5 100644 --- a/stdlib-stubs/src/CoroutineContext.kt +++ b/stdlib-stubs/src/CoroutineContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin.coroutines diff --git a/stdlib-stubs/src/Result.kt b/stdlib-stubs/src/Result.kt index 611074a795..d873ac8902 100644 --- a/stdlib-stubs/src/Result.kt +++ b/stdlib-stubs/src/Result.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin diff --git a/ui/coroutines-guide-ui.md b/ui/coroutines-guide-ui.md index 4832fe653d..7673c8f2b9 100644 --- a/ui/coroutines-guide-ui.md +++ b/ui/coroutines-guide-ui.md @@ -110,7 +110,7 @@ Add dependencies on `kotlinx-coroutines-android` module to the `dependencies { . `app/build.gradle` file: ```groovy -implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2" +implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3" ``` You can clone [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) project from GitHub onto your @@ -607,6 +607,7 @@ After delay + [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html [delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html @@ -618,15 +619,20 @@ After delay [CoroutineStart]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-start/index.html [async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html [CoroutineStart.UNDISPATCHED]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-start/-u-n-d-i-s-p-a-t-c-h-e-d.html + + [actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html [SendChannel.offer]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/offer.html [SendChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-send-channel/index.html [Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/index.html [Channel.CONFLATED]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/-c-o-n-f-l-a-t-e-d.html + + [kotlinx.coroutines.Dispatchers.JavaFx]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-javafx/kotlinx.coroutines.javafx/kotlinx.coroutines.-dispatchers/-java-fx.html + diff --git a/ui/knit.properties b/ui/knit.properties index 3ad209a4df..76a1d77a99 100644 --- a/ui/knit.properties +++ b/ui/knit.properties @@ -1,7 +1,7 @@ # -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # knit.dir=kotlinx-coroutines-javafx/test/guide/ knit.package=kotlinx.coroutines.javafx.guide -knit.include=knit.code.include \ No newline at end of file +knit.include=knit.code.include diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts b/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts index 2acc058d73..18adf4bd1a 100644 --- a/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts +++ b/ui/kotlinx-coroutines-android/android-unit-tests/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ dependencies { diff --git a/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt b/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt index a08f44ad4c..1c5c6abd81 100644 --- a/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt +++ b/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.android diff --git a/ui/kotlinx-coroutines-android/animation-app/app/build.gradle.kts b/ui/kotlinx-coroutines-android/animation-app/app/build.gradle.kts deleted file mode 100644 index 517f1f6341..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -plugins { - id("com.android.application") - kotlin("android") - kotlin("android.extensions") -} - -android { - compileSdkVersion = "29" - defaultConfig { - applicationId = "org.jetbrains.kotlinx.animation" - minSdkVersion(14) - targetSdkVersion(29) - versionCode = 1 - versionName = "1.0" - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } -} - -dependencies { - implementation("androidx.appcompat:appcompat:1.0.2") - implementation("androidx.constraintlayout:constraintlayout:1.1.3") - implementation("com.google.android.material:material:1.0.0") - implementation("androidx.lifecycle:lifecycle-extensions:2.0.0") - - implementation(kotlin("stdlib-jdk7")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${property("coroutines_version")}") - - testImplementation("junit:junit:4.12") - androidTestImplementation("androidx.test:runner:1.2.0") - androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") -} diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/AndroidManifest.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/AndroidManifest.xml deleted file mode 100644 index 34d0dd14d5..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt b/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt deleted file mode 100644 index 88e0baeeb3..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.kotlinx.animation - -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModel -import android.content.Context -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.RectF -import android.util.AttributeSet -import android.view.View -import kotlinx.coroutines.* -import kotlinx.coroutines.android.* -import java.util.* - -sealed class AnimatedShape { - var x = 0.5f // 0 .. 1 - var y = 0.5f // 0 .. 1 - var color = Color.BLACK - var r = 0.05f -} - -class AnimatedCircle : AnimatedShape() -class AnimatedSquare : AnimatedShape() - -private val NO_SHAPES = emptySet() - -class AnimationView( - context: Context, attributeSet: AttributeSet -) : View(context, attributeSet), Observer> { - private var shapes = NO_SHAPES - private val paint = Paint() - private val rect = RectF() - - override fun onChanged(shapes: Set?) { - this.shapes = shapes ?: NO_SHAPES - invalidate() - } - - override fun onDraw(canvas: Canvas) { - val scale = minOf(width, height) / 2.0f - shapes.forEach { shape -> - val x = (shape.x - 0.5f) * scale + width / 2 - val y = (shape.y - 0.5f) * scale + height / 2 - val r = shape.r * scale - rect.set(x - r, y - r, x + r, y + r) - paint.color = shape.color - when (shape) { - is AnimatedCircle -> canvas.drawArc(rect, 0.0f, 360.0f, true, paint) - is AnimatedSquare -> canvas.drawRect(rect, paint) - } - } - } -} - -private val rnd = Random() - -class AnimationModel : ViewModel(), CoroutineScope { - - override val coroutineContext = Job() + Dispatchers.Main - - private val shapes = MutableLiveData>() - - fun observe(owner: LifecycleOwner, observer: Observer>) = - shapes.observe(owner, observer) - - fun update(shape: AnimatedShape) { - val old = shapes.value ?: NO_SHAPES - shapes.value = if (shape in old) old else old + shape - } - - fun addAnimation() { - launch { - animateShape(if (rnd.nextBoolean()) AnimatedCircle() else AnimatedSquare()) - } - } - - fun clearAnimations() { - coroutineContext.cancelChildren() - shapes.value = NO_SHAPES - } -} - -private fun norm(x: Float, y: Float) = Math.hypot(x.toDouble(), y.toDouble()).toFloat() - -private const val ACC = 1e-18f -private const val MAX_SPEED = 2e-9f // in screen_fraction/nanos -private const val INIT_POS = 0.8f - -private fun Random.nextColor() = Color.rgb(nextInt(256), nextInt(256), nextInt(256)) -private fun Random.nextPos() = nextFloat() * INIT_POS + (1 - INIT_POS) / 2 -private fun Random.nextSpeed() = nextFloat() * MAX_SPEED - MAX_SPEED / 2 - -suspend fun AnimationModel.animateShape(shape: AnimatedShape) { - shape.x = rnd.nextPos() - shape.y = rnd.nextPos() - shape.color = rnd.nextColor() - var sx = rnd.nextSpeed() - var sy = rnd.nextSpeed() - var time = System.nanoTime() // nanos - var checkTime = time - while (true) { - val dt = time.let { old -> awaitFrame().also { time = it } - old } - if (dt > 0.5e9) continue // don't animate through over a half second lapses - val dx = shape.x - 0.5f - val dy = shape.y - 0.5f - val dn = norm(dx, dy) - sx -= dx / dn * ACC * dt - sy -= dy / dn * ACC * dt - val sn = norm(sx, sy) - val trim = sn.coerceAtMost(MAX_SPEED) - sx = sx / sn * trim - sy = sy / sn * trim - shape.x += sx * dt - shape.y += sy * dt - update(shape) - // check once a second - if (time > checkTime + 1e9) { - checkTime = time - when (rnd.nextInt(20)) { // roll d20 - 0 -> { - animateColor(shape) // wait a second & animate color - time = awaitFrame() // and sync with next frame - } - 1 -> { // random speed change - sx = rnd.nextSpeed() - sy = rnd.nextSpeed() - } - } - } - } -} - -suspend fun AnimationModel.animateColor(shape: AnimatedShape) { - val duration = 1e9f - val startTime = System.nanoTime() - val aColor = shape.color - val bColor = rnd.nextColor() - while (true) { - val time = awaitFrame() - val b = (time - startTime) / duration - if (b >= 1.0f) break - val a = 1 - b - shape.color = Color.rgb( - (Color.red(bColor) * b + Color.red(aColor) * a).toInt(), - (Color.green(bColor) * b + Color.green(aColor) * a).toInt(), - (Color.blue(bColor) * b + Color.blue(aColor) * a).toInt() - ) - update(shape) - } - shape.color = bColor - update(shape) -} diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/MainActivity.kt b/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/MainActivity.kt deleted file mode 100644 index 756db9bbe6..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/MainActivity.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.kotlinx.animation - -import androidx.lifecycle.ViewModelProviders -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import kotlinx.android.synthetic.main.activity_main.* -import kotlinx.android.synthetic.main.content_main.* - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - setSupportActionBar(toolbar) - - val animationModel = ViewModelProviders.of(this).get(AnimationModel::class.java) - animationModel.observe(this, animationView) - - addButton.setOnClickListener { - animationModel.addAnimation() - } - - removeButton.setOnClickListener { - animationModel.clearAnimations() - } - } -} diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd8..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/drawable/ic_launcher_background.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index d5fccc538c..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/layout/activity_main.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 8e06e90179..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/layout/content_main.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/layout/content_main.xml deleted file mode 100644 index 2019bb5dc1..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/layout/content_main.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 8bc717e4ad..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 8bc717e4ad..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-hdpi/ic_launcher.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f5908281..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b52399808..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-mdpi/ic_launcher.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e1..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768a..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd8083..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d3..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe024..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a1..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd48..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c23..0000000000 Binary files a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/colors.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/colors.xml deleted file mode 100644 index 9ad7e369a6..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #3f51b5 - #303F9F - #FF4081 - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/dimens.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/dimens.xml deleted file mode 100644 index 59a0b0c4f5..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 16dp - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/strings.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/strings.xml deleted file mode 100644 index cd3f467bcd..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Animation - Settings - diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/styles.xml b/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/styles.xml deleted file mode 100644 index 545b9c6d2c..0000000000 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - -