From 24f5f9c6e483dcbabe9efcc7c6b7ff8c986d305d Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 13 Dec 2019 13:05:17 +0300 Subject: [PATCH 01/50] Better diagnostics on ChannelSelectStressTest failure --- .../test/channels/ChannelSelectStressTest.kt | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt index 0fa64276df..c835250e3e 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt @@ -14,7 +14,6 @@ import java.util.concurrent.atomic.AtomicLongArray class ChannelSelectStressTest : TestBase() { private val pairedCoroutines = 3 private val dispatcher = newFixedThreadPoolContext(pairedCoroutines * 2, "ChannelSelectStressTest") - private val scope = CoroutineScope(dispatcher) private val elementsToSend = 20_000 * Long.SIZE_BITS * stressTestMultiplier private val sent = atomic(0) private val received = atomic(0) @@ -28,19 +27,27 @@ class ChannelSelectStressTest : TestBase() { @Test fun testAtomicCancelStress() = runTest { - repeat(pairedCoroutines) { launchSender() } - repeat(pairedCoroutines) { launchReceiver() } - val job = scope.coroutineContext[Job] as CompletableJob - job.complete() - job.join() - + withContext(dispatcher) { + repeat(pairedCoroutines) { launchSender() } + repeat(pairedCoroutines) { launchReceiver() } + } + val missing = ArrayList() for (i in 0 until receivedArray.length()) { - assertEquals("Missing element detected", 0L.inv(), receivedArray[i]) + val bits = receivedArray[i] + if (bits != 0L.inv()) { + for (j in 0 until Long.SIZE_BITS) { + val mask = 1L shl j + if (bits and mask == 0L) missing += i * Long.SIZE_BITS + j + } + } + } + if (missing.isNotEmpty()) { + fail("Missed ${missing.size} out of $elementsToSend: $missing") } } - private fun launchSender() { - scope.launch { + private fun CoroutineScope.launchSender() { + launch { while (sent.value < elementsToSend) { val element = sent.getAndIncrement() if (element >= elementsToSend) break @@ -50,8 +57,8 @@ class ChannelSelectStressTest : TestBase() { } } - private fun launchReceiver() { - scope.launch { + private fun CoroutineScope.launchReceiver() { + launch { while (received.value != elementsToSend) { val element = select { channel.onReceive { it } } received.incrementAndGet() From cc3d8c42ab8c42a8deb8be5c56f3918269faabd2 Mon Sep 17 00:00:00 2001 From: Rick Busarow Date: Sun, 15 Dec 2019 21:39:06 -0600 Subject: [PATCH 02/50] update `broadcastIn` comment to refer to itself instead of `produce` --- kotlinx-coroutines-core/common/src/flow/Channels.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/flow/Channels.kt b/kotlinx-coroutines-core/common/src/flow/Channels.kt index 1a572e8582..f81bc037e3 100644 --- a/kotlinx-coroutines-core/common/src/flow/Channels.kt +++ b/kotlinx-coroutines-core/common/src/flow/Channels.kt @@ -151,7 +151,7 @@ public fun BroadcastChannel.asFlow(): Flow = flow { * that collects the given flow and thus resulting channel should be properly closed or cancelled. * * A channel with [default][Channel.Factory.BUFFERED] buffer size is created. - * Use [buffer] operator on the flow before calling `produce` to specify a value other than + * Use [buffer] operator on the flow before calling `broadcastIn` to specify a value other than * default and to control what happens when data is produced faster than it is consumed, * that is to control backpressure behavior. */ @@ -169,7 +169,7 @@ public fun Flow.broadcastIn( * that collects the given flow and thus resulting channel should be properly closed or cancelled. * * A channel with [default][Channel.Factory.BUFFERED] buffer size is created. - * Use [buffer] operator on the flow before calling `produce` to specify a value other than + * Use [buffer] operator on the flow before calling `produceIn` to specify a value other than * default and to control what happens when data is produced faster than it is consumed, * that is to control backpressure behavior. */ From f8b3c443ff5181915953f29260ea7c240d86d9bb Mon Sep 17 00:00:00 2001 From: Marek Langiewicz Date: Sat, 14 Dec 2019 16:42:53 +0100 Subject: [PATCH 03/50] Fix TestBase example in kdoc --- kotlinx-coroutines-core/jvm/test/TestBase.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/test/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt index cc41ff3f62..9c3efb4a39 100644 --- a/kotlinx-coroutines-core/jvm/test/TestBase.kt +++ b/kotlinx-coroutines-core/jvm/test/TestBase.kt @@ -31,14 +31,14 @@ public actual val stressTestMultiplier = stressTestMultiplierSqrt * stressTestMu * thread can be written. Use it like this: * * ``` - * class MyTest { + * class MyTest : TestBase() { * @Test - * fun testSomething() = runBlocking { // run in the context of the main thread + * fun testSomething() = runBlocking { // run in the context of the main thread * expect(1) // initiate action counter - * val job = launch(context) { // use the context of the main thread + * launch { // use the context of the main thread * expect(3) // the body of this coroutine in going to be executed in the 3rd step * } - * expect(2) // launch just scheduled coroutine for exectuion later, so this line is executed second + * expect(2) // launch just scheduled coroutine for execution later, so this line is executed second * yield() // yield main thread to the launched job * finish(4) // fourth step is the last one. `finish` must be invoked or test fails * } From 476d6debf2f19e831c3a2d14b984babda972327f Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Mon, 16 Dec 2019 22:38:59 +0300 Subject: [PATCH 04/50] Authenticate in 'kotlin-dev' repo on Bintray --- build.gradle | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8fd5441e5e..c410ff73f7 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,13 @@ buildscript { repositories { jcenter() maven { url "https://kotlin.bintray.com/kotlinx" } - maven { url "https://kotlin.bintray.com/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://jetbrains.bintray.com/kotlin-native-dependencies" } maven { url "https://plugins.gradle.org/m2/" } @@ -125,7 +131,13 @@ allprojects { google() } jcenter() - maven { url "https://kotlin.bintray.com/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" } } From 60f8688c48829bb47efaa83ab02b391468120e10 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Tue, 17 Dec 2019 19:14:52 +0300 Subject: [PATCH 05/50] Use common SharedImmutable declaration from stdlib --- .../common/src/CancellableContinuationImpl.kt | 1 + kotlinx-coroutines-core/common/src/EventLoop.common.kt | 1 + kotlinx-coroutines-core/common/src/JobSupport.kt | 1 + .../common/src/channels/AbstractChannel.kt | 1 + .../common/src/channels/ConflatedBroadcastChannel.kt | 1 + .../common/src/flow/internal/NullSurrogate.kt | 1 + kotlinx-coroutines-core/common/src/internal/Atomic.kt | 1 + .../common/src/internal/Concurrent.common.kt | 6 +----- .../common/src/internal/DispatchedContinuation.kt | 1 + .../common/src/internal/LockFreeLinkedList.common.kt | 1 + kotlinx-coroutines-core/common/src/selects/Select.kt | 2 ++ kotlinx-coroutines-core/common/src/sync/Mutex.kt | 1 + kotlinx-coroutines-core/common/src/sync/Semaphore.kt | 5 +++++ kotlinx-coroutines-core/native/src/CoroutineContext.kt | 4 +++- kotlinx-coroutines-core/native/src/internal/Concurrent.kt | 5 +---- 15 files changed, 22 insertions(+), 10 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt index f5b5900cb6..27c83256c8 100644 --- a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt +++ b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.internal.* import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* import kotlin.jvm.* +import kotlin.native.concurrent.* private const val UNDECIDED = 0 private const val SUSPENDED = 1 diff --git a/kotlinx-coroutines-core/common/src/EventLoop.common.kt b/kotlinx-coroutines-core/common/src/EventLoop.common.kt index a4984b55e5..83959af135 100644 --- a/kotlinx-coroutines-core/common/src/EventLoop.common.kt +++ b/kotlinx-coroutines-core/common/src/EventLoop.common.kt @@ -8,6 +8,7 @@ import kotlinx.atomicfu.* import kotlinx.coroutines.internal.* import kotlin.coroutines.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * Extended by [CoroutineDispatcher] implementations that have event loop inside and can diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index eb0d823f38..c7a7195acb 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -13,6 +13,7 @@ import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* import kotlin.js.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * A concrete implementation of [Job]. It is optionally a child to a parent job. diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt index f70164485a..b9bd83b118 100644 --- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* import kotlin.coroutines.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * Abstract send channel. It is a base class for all send channel implementations. diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt index a3e72a9c1b..74fc444855 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * Broadcasts the most recently sent element (aka [value]) to all [openSubscription] subscribers. diff --git a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt index c6ff12fc4e..97faee0d74 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines.flow.internal import kotlinx.coroutines.internal.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * This value is used a a surrogate `null` value when needed. diff --git a/kotlinx-coroutines-core/common/src/internal/Atomic.kt b/kotlinx-coroutines-core/common/src/internal/Atomic.kt index 8a1185ae13..1fb4cefd1c 100644 --- a/kotlinx-coroutines-core/common/src/internal/Atomic.kt +++ b/kotlinx-coroutines-core/common/src/internal/Atomic.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines.internal import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * The most abstract operation that can be in process. Other threads observing an instance of this diff --git a/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt index 6b096f0449..d23d09cefb 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -22,7 +22,3 @@ internal expect class ReentrantLock() { internal expect inline fun ReentrantLock.withLock(action: () -> T): T internal expect fun identitySet(expectedSize: Int): MutableSet - -@ExperimentalMultiplatform -@OptionalExpectation -internal expect annotation class SharedImmutable() diff --git a/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt index f04dde1cbc..2369f18a51 100644 --- a/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt +++ b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt @@ -8,6 +8,7 @@ import kotlinx.atomicfu.* import kotlinx.coroutines.internal.* import kotlin.coroutines.* import kotlin.jvm.* +import kotlin.native.concurrent.* @SharedImmutable private val UNDEFINED = Symbol("UNDEFINED") diff --git a/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt index 39dc1d2884..2ba7d98e39 100644 --- a/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.internal import kotlin.jvm.* +import kotlin.native.concurrent.* /** @suppress **This is unstable API and it is subject to change.** */ public expect open class LockFreeLinkedListNode() { diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt index 63e4dfa31b..1725d12f4a 100644 --- a/kotlinx-coroutines-core/common/src/selects/Select.kt +++ b/kotlinx-coroutines-core/common/src/selects/Select.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.sync.* import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * Scope for [select] invocation. @@ -213,6 +214,7 @@ internal class SeqNumber { fun next() = number.incrementAndGet() } +@SharedImmutable private val selectOpSequenceNumber = SeqNumber() @PublishedApi diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index ea4a510775..4a223552d8 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* import kotlin.coroutines.* import kotlin.jvm.* +import kotlin.native.concurrent.* /** * Mutual exclusion for coroutines. diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt index b6ebc501ff..d72f989b61 100644 --- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt +++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.sync import kotlinx.atomicfu.* @@ -6,6 +10,7 @@ import kotlinx.coroutines.internal.* import kotlin.coroutines.* import kotlin.jvm.* import kotlin.math.* +import kotlin.native.concurrent.* /** * A counting semaphore for coroutines that logically maintains a number of available permits. diff --git a/kotlinx-coroutines-core/native/src/CoroutineContext.kt b/kotlinx-coroutines-core/native/src/CoroutineContext.kt index 41d2c88df5..debdc97f74 100644 --- a/kotlinx-coroutines-core/native/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/native/src/CoroutineContext.kt @@ -1,10 +1,11 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines import kotlin.coroutines.* +import kotlin.native.concurrent.* private fun takeEventLoop(): EventLoopImpl = ThreadLocalEventLoop.currentOrNull() as? EventLoopImpl ?: @@ -26,6 +27,7 @@ internal fun loopWasShutDown(): Nothing = error("Cannot execute task because eve internal actual fun createDefaultDispatcher(): CoroutineDispatcher = DefaultExecutor +@SharedImmutable internal actual val DefaultDelay: Delay = DefaultExecutor public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext { diff --git a/kotlinx-coroutines-core/native/src/internal/Concurrent.kt b/kotlinx-coroutines-core/native/src/internal/Concurrent.kt index 546d6af96b..84d5d3496b 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -16,6 +16,3 @@ internal class NoOpLock { internal actual fun subscriberList(): MutableList = CopyOnWriteList() internal actual fun identitySet(expectedSize: Int): MutableSet = HashSet() - -@Suppress("ACTUAL_WITHOUT_EXPECT") -internal actual typealias SharedImmutable = kotlin.native.concurrent.SharedImmutable From 12a0318337e1985960fabf053127590e2981c7de Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Thu, 19 Dec 2019 11:09:09 +0300 Subject: [PATCH 06/50] Use common ThreadLocal declaration from stdlib --- kotlinx-coroutines-core/common/src/EventLoop.common.kt | 2 +- .../common/src/internal/ThreadLocal.common.kt | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/EventLoop.common.kt b/kotlinx-coroutines-core/common/src/EventLoop.common.kt index 83959af135..c8bc384c3f 100644 --- a/kotlinx-coroutines-core/common/src/EventLoop.common.kt +++ b/kotlinx-coroutines-core/common/src/EventLoop.common.kt @@ -118,7 +118,7 @@ internal abstract class EventLoop : CoroutineDispatcher() { protected open fun shutdown() {} } -@NativeThreadLocal +@ThreadLocal internal object ThreadLocalEventLoop { private val ref = CommonThreadLocal() diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt index ddf29888b2..4c09e62640 100644 --- a/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt +++ b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt @@ -1,13 +1,9 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal -@OptionalExpectation -@UseExperimental(ExperimentalMultiplatform::class) -internal expect annotation class NativeThreadLocal() - internal expect class CommonThreadLocal() { fun get(): T fun set(value: T) From 70e3583e81656afc039f479c38003d1810312562 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 25 Dec 2019 13:14:21 +0300 Subject: [PATCH 07/50] Make CoroutinesDumpTest deterministic --- .../jvm/src/scheduling/CoroutineScheduler.kt | 1 + .../test/CoroutinesDumpTest.kt | 151 ++++++++++-------- .../test/StracktraceUtils.kt | 13 +- 3 files changed, 97 insertions(+), 68 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt index 09e9deb838..b096e4f815 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt @@ -653,6 +653,7 @@ internal class CoroutineScheduler( } override fun run() = runWorker() + @JvmField var mayHaveLocalTasks = false diff --git a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt index fa7353410b..91bd4f287d 100644 --- a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt +++ b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt @@ -11,41 +11,47 @@ import kotlin.test.* class CoroutinesDumpTest : DebugTestBase() { private val monitor = Any() - private var coroutineStarted = false // guarded by monitor + private var coroutineThread: Thread? = null // guarded by monitor @Test - fun testSuspendedCoroutine() = synchronized(monitor) { - val deferred = GlobalScope.async { + fun testSuspendedCoroutine() = runBlocking { + val deferred = async(Dispatchers.Default) { sleepingOuterMethod() } - awaitCoroutineStarted() - Thread.sleep(100) // Let delay be invoked + awaitCoroutine() + val found = DebugProbes.dumpCoroutinesInfo().single { it.job === deferred } verifyDump( "Coroutine \"coroutine#1\":DeferredCoroutine{Active}@1e4a7dd4, state: SUSPENDED\n" + - "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.sleepingNestedMethod(CoroutinesDumpTest.kt:95)\n" + - "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.sleepingOuterMethod(CoroutinesDumpTest.kt:88)\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" + - "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:99)\n") - - val found = DebugProbes.dumpCoroutinesInfo().single { it.job === deferred } + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.sleepingNestedMethod(CoroutinesDumpTest.kt:95)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.sleepingOuterMethod(CoroutinesDumpTest.kt:88)\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" + + "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:99)\n", + ignoredCoroutine = "BlockingCoroutine" + ) { + deferred.cancel() + coroutineThread!!.interrupt() + } assertSame(deferred, found.job) - runBlocking { deferred.cancelAndJoin() } } @Test - fun testRunningCoroutine() = synchronized(monitor) { - val deferred = GlobalScope.async { + fun testRunningCoroutine() = runBlocking { + val deferred = async(Dispatchers.Default) { activeMethod(shouldSuspend = false) assertTrue(true) } - awaitCoroutineStarted() + awaitCoroutine() verifyDump( - "Coroutine \"coroutine#1\":DeferredCoroutine{Active}@227d9994, state: RUNNING (Last suspension stacktrace, not an actual stacktrace)\n" + - "\t(Coroutine creation stacktrace)\n" + + "Coroutine \"coroutine#1\":DeferredCoroutine{Active}@227d9994, state: RUNNING\n" + + "\tat java.lang.Thread.sleep(Native Method)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.nestedActiveMethod(CoroutinesDumpTest.kt:141)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.activeMethod(CoroutinesDumpTest.kt:133)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest\$testRunningCoroutine\$1$deferred\$1.invokeSuspend(CoroutinesDumpTest.kt:41)\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" + "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:99)\n" + @@ -54,74 +60,84 @@ class CoroutinesDumpTest : DebugTestBase() { "\tat kotlinx.coroutines.BuildersKt.async(Unknown Source)\n" + "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt)\n" + "\tat kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + - "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.testRunningCoroutine(CoroutinesDumpTest.kt:49)") - runBlocking { deferred.cancelAndJoin() } + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.testRunningCoroutine(CoroutinesDumpTest.kt:49)", + ignoredCoroutine = "BlockingCoroutine" + ) { + deferred.cancel() + coroutineThread?.interrupt() + } } @Test - fun testRunningCoroutineWithSuspensionPoint() = synchronized(monitor) { - val deferred = GlobalScope.async { + fun testRunningCoroutineWithSuspensionPoint() = runBlocking { + val deferred = async(Dispatchers.Default) { activeMethod(shouldSuspend = true) yield() // tail-call } - awaitCoroutineStarted() - Thread.sleep(10) + awaitCoroutine() verifyDump( "Coroutine \"coroutine#1\":DeferredCoroutine{Active}@1e4a7dd4, state: RUNNING\n" + - "\tat java.lang.Thread.sleep(Native Method)\n" + - "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.nestedActiveMethod(CoroutinesDumpTest.kt:111)\n" + - "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.activeMethod(CoroutinesDumpTest.kt:106)\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" + - "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:99)\n" + - "\tat kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:148)\n" + - "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async(Builders.common.kt)\n" + - "\tat kotlinx.coroutines.BuildersKt.async(Unknown Source)\n" + - "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt)\n" + - "\tat kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + - "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.testRunningCoroutineWithSuspensionPoint(CoroutinesDumpTest.kt:71)" - ) - runBlocking { deferred.cancelAndJoin() } + "\tat java.lang.Thread.sleep(Native Method)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.nestedActiveMethod(CoroutinesDumpTest.kt:111)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.activeMethod(CoroutinesDumpTest.kt:106)\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" + + "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:99)\n" + + "\tat kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:148)\n" + + "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async(Builders.common.kt)\n" + + "\tat kotlinx.coroutines.BuildersKt.async(Unknown Source)\n" + + "\tat kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt)\n" + + "\tat kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + + "\tat kotlinx.coroutines.debug.CoroutinesDumpTest.testRunningCoroutineWithSuspensionPoint(CoroutinesDumpTest.kt:71)", + ignoredCoroutine = "BlockingCoroutine" + ) { + deferred.cancel() + coroutineThread!!.interrupt() + } } @Test - fun testCreationStackTrace() = synchronized(monitor) { - val deferred = GlobalScope.async { + fun testCreationStackTrace() = runBlocking { + val deferred = async(Dispatchers.Default) { activeMethod(shouldSuspend = true) } - awaitCoroutineStarted() - val coroutine = DebugProbes.dumpCoroutinesInfo().first() + awaitCoroutine() + val coroutine = DebugProbes.dumpCoroutinesInfo().first { it.job is Deferred<*> } val result = coroutine.creationStackTrace.fold(StringBuilder()) { acc, element -> acc.append(element.toString()) acc.append('\n') }.toString().trimStackTrace() - runBlocking { deferred.cancelAndJoin() } - - val expected = ("kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + - "kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + - "kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)\n" + - "kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:160)\n" + - "kotlinx.coroutines.BuildersKt__Builders_commonKt.async(Builders.common.kt:88)\n" + - "kotlinx.coroutines.BuildersKt.async(Unknown Source)\n" + - "kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt:81)\n" + - "kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + - "kotlinx.coroutines.debug.CoroutinesDumpTest.testCreationStackTrace(CoroutinesDumpTest.kt:109)").trimStackTrace() + deferred.cancel() + coroutineThread!!.interrupt() + + val expected = + ("kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + + "kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + + "kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)\n" + + "kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:160)\n" + + "kotlinx.coroutines.BuildersKt__Builders_commonKt.async(Builders.common.kt:88)\n" + + "kotlinx.coroutines.BuildersKt.async(Unknown Source)\n" + + "kotlinx.coroutines.BuildersKt__Builders_commonKt.async\$default(Builders.common.kt:81)\n" + + "kotlinx.coroutines.BuildersKt.async\$default(Unknown Source)\n" + + "kotlinx.coroutines.debug.CoroutinesDumpTest\$testCreationStackTrace\$1.invokeSuspend(CoroutinesDumpTest.kt)").trimStackTrace() assertTrue(result.startsWith(expected)) } @Test - fun testFinishedCoroutineRemoved() = synchronized(monitor) { - val deferred = GlobalScope.async { + fun testFinishedCoroutineRemoved() = runBlocking { + val deferred = async(Dispatchers.Default) { activeMethod(shouldSuspend = true) } - awaitCoroutineStarted() - runBlocking { deferred.cancelAndJoin() } - verifyDump() + awaitCoroutine() + deferred.cancel() + coroutineThread!!.interrupt() + deferred.join() + verifyDump(ignoredCoroutine = "BlockingCoroutine") } private suspend fun activeMethod(shouldSuspend: Boolean) { @@ -133,28 +149,31 @@ class CoroutinesDumpTest : DebugTestBase() { if (shouldSuspend) yield() notifyCoroutineStarted() while (coroutineContext[Job]!!.isActive) { - Thread.sleep(100) + runCatching { Thread.sleep(60_000) } } } private suspend fun sleepingOuterMethod() { sleepingNestedMethod() - yield() + yield() // TCE } private suspend fun sleepingNestedMethod() { - yield() + yield() // Suspension point notifyCoroutineStarted() delay(Long.MAX_VALUE) } - private fun awaitCoroutineStarted() { - while (!coroutineStarted) (monitor as Object).wait() + private fun awaitCoroutine() = synchronized(monitor) { + while (coroutineThread == null) (monitor as Object).wait() + while (coroutineThread!!.state != Thread.State.TIMED_WAITING) { + // Wait until thread sleeps to have a consistent stacktrace + } } private fun notifyCoroutineStarted() { synchronized(monitor) { - coroutineStarted = true + coroutineThread = Thread.currentThread() (monitor as Object).notifyAll() } } diff --git a/kotlinx-coroutines-debug/test/StracktraceUtils.kt b/kotlinx-coroutines-debug/test/StracktraceUtils.kt index cab4ed86b3..2600e4a572 100644 --- a/kotlinx-coroutines-debug/test/StracktraceUtils.kt +++ b/kotlinx-coroutines-debug/test/StracktraceUtils.kt @@ -55,13 +55,22 @@ public fun toStackTrace(t: Throwable): String { public fun String.count(substring: String): Int = split(substring).size - 1 +public fun verifyDump(vararg traces: String, ignoredCoroutine: String? = null, finally: () -> Unit) { + try { + verifyDump(*traces, ignoredCoroutine = ignoredCoroutine) + } finally { + finally() + } +} + public fun verifyDump(vararg traces: String, ignoredCoroutine: String? = null) { val baos = ByteArrayOutputStream() DebugProbes.dumpCoroutines(PrintStream(baos)) val trace = baos.toString().split("\n\n") if (traces.isEmpty()) { - assertEquals(1, trace.size) - assertTrue(trace[0].startsWith("Coroutines dump")) + val filtered = trace.filter { ignoredCoroutine == null || !it.contains(ignoredCoroutine) } + assertEquals(1, filtered.count()) + assertTrue(filtered[0].startsWith("Coroutines dump")) return } // Drop "Coroutine dump" line From c526c3fafa0efdb638e99cb30a10cdcfb8e2bc1c Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 25 Dec 2019 14:16:39 +0300 Subject: [PATCH 08/50] =?UTF-8?q?Do=20not=20request=20additional=20worker?= =?UTF-8?q?=20from=20'yield'=20calls=20and=20during=20post-e=E2=80=A6=20(#?= =?UTF-8?q?1728)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not request additional worker from 'yield' calls and during post-execution phase in LimitingDispatcher Fixes #1704 Fixes #1706 --- .../jvm/src/scheduling/CoroutineScheduler.kt | 34 ++++++++++++------- .../jvm/src/scheduling/Dispatcher.kt | 14 +++++--- .../BlockingCoroutineDispatcherTest.kt | 21 ++++++++++-- ...oroutineDispatcherThreadLimitStressTest.kt | 1 - .../scheduling/CoroutineDispatcherTest.kt | 12 +++++++ .../CoroutineSchedulerCloseStressTest.kt | 5 ++- .../test/scheduling/CoroutineSchedulerTest.kt | 2 +- 7 files changed, 66 insertions(+), 23 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt index b096e4f815..7a52d34849 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt @@ -372,25 +372,34 @@ internal class CoroutineScheduler( * Dispatches execution of a runnable [block] with a hint to a scheduler whether * this [block] may execute blocking operations (IO, system calls, locking primitives etc.) * - * @param taskContext concurrency context of given [block] - * @param fair whether the task should be dispatched fairly (strict FIFO) or not (semi-FIFO) + * [taskContext] -- concurrency context of given [block]. + * [tailDispatch] -- whether this [dispatch] call is the last action the (presumably) worker thread does in its current task. + * If `true`, then the task will be dispatched in a FIFO manner and no additional workers will be requested, + * but only if the current thread is a corresponding worker thread. + * Note that caller cannot be ensured that it is being executed on worker thread for the following reasons: + * * [CoroutineStart.UNDISPATCHED] + * * Concurrent [close] that effectively shutdowns the worker thread */ - fun dispatch(block: Runnable, taskContext: TaskContext = NonBlockingContext, fair: Boolean = false) { + fun dispatch(block: Runnable, taskContext: TaskContext = NonBlockingContext, tailDispatch: Boolean = false) { trackTask() // this is needed for virtual time support val task = createTask(block, taskContext) // try to submit the task to the local queue and act depending on the result - val notAdded = submitToLocalQueue(task, fair) + val currentWorker = currentWorker() + val notAdded = currentWorker.submitToLocalQueue(task, tailDispatch) if (notAdded != null) { if (!addToGlobalQueue(notAdded)) { // Global queue is closed in the last step of close/shutdown -- no more tasks should be accepted throw RejectedExecutionException("$schedulerName was terminated") } } + val skipUnpark = tailDispatch && currentWorker != null // Checking 'task' instead of 'notAdded' is completely okay if (task.mode == TaskMode.NON_BLOCKING) { + if (skipUnpark) return signalCpuWork() } else { - signalBlockingWork() + // Increment blocking tasks anyway + signalBlockingWork(skipUnpark = skipUnpark) } } @@ -404,9 +413,10 @@ internal class CoroutineScheduler( return TaskImpl(block, nanoTime, taskContext) } - private fun signalBlockingWork() { + private fun signalBlockingWork(skipUnpark: Boolean) { // Use state snapshot to avoid thread overprovision val stateSnapshot = incrementBlockingTasks() + if (skipUnpark) return if (tryUnpark()) return if (tryCreateWorker(stateSnapshot)) return tryUnpark() // Try unpark again in case there was race between permit release and parking @@ -481,19 +491,19 @@ internal class CoroutineScheduler( * Returns `null` if task was successfully added or an instance of the * task that was not added or replaced (thus should be added to global queue). */ - private fun submitToLocalQueue(task: Task, fair: Boolean): Task? { - val worker = currentWorker() ?: return task + private fun Worker?.submitToLocalQueue(task: Task, tailDispatch: Boolean): Task? { + if (this == null) return task /* * This worker could have been already terminated from this thread by close/shutdown and it should not * accept any more tasks into its local queue. */ - if (worker.state === WorkerState.TERMINATED) return task + if (state === WorkerState.TERMINATED) return task // Do not add CPU tasks in local queue if we are not able to execute it - if (task.mode === TaskMode.NON_BLOCKING && worker.state === WorkerState.BLOCKING) { + if (task.mode === TaskMode.NON_BLOCKING && state === WorkerState.BLOCKING) { return task } - worker.mayHaveLocalTasks = true - return worker.localQueue.add(task, fair = fair) + mayHaveLocalTasks = true + return localQueue.add(task, fair = tailDispatch) } private fun currentWorker(): Worker? = (Thread.currentThread() as? Worker)?.takeIf { it.scheduler == this } diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt index bd1ba95dd8..bbc2b35b16 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt @@ -65,7 +65,7 @@ open class ExperimentalCoroutineDispatcher( override fun dispatchYield(context: CoroutineContext, block: Runnable): Unit = try { - coroutineScheduler.dispatch(block, fair = true) + coroutineScheduler.dispatch(block, tailDispatch = true) } catch (e: RejectedExecutionException) { DefaultExecutor.dispatchYield(context, block) } @@ -101,9 +101,9 @@ open class ExperimentalCoroutineDispatcher( return LimitingDispatcher(this, parallelism, TaskMode.NON_BLOCKING) } - internal fun dispatchWithContext(block: Runnable, context: TaskContext, fair: Boolean) { + internal fun dispatchWithContext(block: Runnable, context: TaskContext, tailDispatch: Boolean) { try { - coroutineScheduler.dispatch(block, context, fair) + coroutineScheduler.dispatch(block, context, tailDispatch) } catch (e: RejectedExecutionException) { // Context shouldn't be lost here to properly invoke before/after task DefaultExecutor.enqueue(coroutineScheduler.createTask(block, context)) @@ -147,7 +147,7 @@ private class LimitingDispatcher( override fun dispatch(context: CoroutineContext, block: Runnable) = dispatch(block, false) - private fun dispatch(block: Runnable, fair: Boolean) { + private fun dispatch(block: Runnable, tailDispatch: Boolean) { var taskToSchedule = block while (true) { // Commit in-flight tasks slot @@ -155,7 +155,7 @@ private class LimitingDispatcher( // Fast path, if parallelism limit is not reached, dispatch task and return if (inFlight <= parallelism) { - dispatcher.dispatchWithContext(taskToSchedule, this, fair) + dispatcher.dispatchWithContext(taskToSchedule, this, tailDispatch) return } @@ -185,6 +185,10 @@ private class LimitingDispatcher( } } + override fun dispatchYield(context: CoroutineContext, block: Runnable) { + dispatch(block, tailDispatch = true) + } + override fun toString(): String { return "${super.toString()}[dispatcher = $dispatcher]" } diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt index 66b93be9cf..f31752c8b5 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt @@ -194,10 +194,10 @@ class BlockingCoroutineDispatcherTest : SchedulerTestBase() { fun testYield() = runBlocking { corePoolSize = 1 maxPoolSize = 1 - val ds = blockingDispatcher(1) - val outerJob = launch(ds) { + val bd = blockingDispatcher(1) + val outerJob = launch(bd) { expect(1) - val innerJob = launch(ds) { + val innerJob = launch(bd) { // Do nothing expect(3) } @@ -215,6 +215,21 @@ class BlockingCoroutineDispatcherTest : SchedulerTestBase() { finish(5) } + @Test + fun testUndispatchedYield() = runTest { + expect(1) + corePoolSize = 1 + maxPoolSize = 1 + val blockingDispatcher = blockingDispatcher(1) + val job = launch(blockingDispatcher, CoroutineStart.UNDISPATCHED) { + expect(2) + yield() + } + expect(3) + job.join() + finish(4) + } + @Test(expected = IllegalArgumentException::class) fun testNegativeParallelism() { blockingDispatcher(-1) diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt index 123fe3c9c4..c1fda44487 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherThreadLimitStressTest.kt @@ -21,7 +21,6 @@ class BlockingCoroutineDispatcherThreadLimitStressTest : SchedulerTestBase() { private val concurrentWorkers = AtomicInteger(0) @Test - @Ignore fun testLimitParallelismToOne() = runTest { val limitingDispatcher = blockingDispatcher(1) // Do in bursts to avoid OOM diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt index 062b849c0a..3cd77da74a 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt @@ -117,6 +117,18 @@ class CoroutineDispatcherTest : SchedulerTestBase() { finish(5) } + @Test + fun testUndispatchedYield() = runTest { + expect(1) + val job = launch(dispatcher, CoroutineStart.UNDISPATCHED) { + expect(2) + yield() + } + expect(3) + job.join() + finish(4) + } + @Test fun testThreadName() = runBlocking { val initialCount = Thread.getAllStackTraces().keys.asSequence() diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt index f91b0a9131..473b429283 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt @@ -10,7 +10,6 @@ import org.junit.Test import org.junit.runner.* import org.junit.runners.* import java.util.* -import java.util.concurrent.* import kotlin.test.* @RunWith(Parameterized::class) @@ -79,6 +78,10 @@ class CoroutineSchedulerCloseStressTest(private val mode: Mode) : TestBase() { } else { if (rnd.nextBoolean()) { delay(1000) + val t = Thread.currentThread() + if (!t.name.contains("DefaultDispatcher-worker")) { + val a = 2 + } } else { yield() } diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt index ff831950b5..38145af8c9 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt @@ -82,7 +82,7 @@ class CoroutineSchedulerTest : TestBase() { it.dispatch(Runnable { expect(2) finishLatch.countDown() - }, fair = true) + }, tailDispatch = true) }) startLatch.countDown() From c5e6e03b7e7c012ab08144696e921f05f91ba3fa Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 25 Dec 2019 11:50:07 +0300 Subject: [PATCH 09/50] Generate site using Jekyll via Docker This makes site-building process more stable and less dependent on the environment, requiring only Docker to be installed locally. --- gradle.properties | 3 ++ site/build.gradle | 13 ++++++++- site/docs/Gemfile | 16 ----------- site/docs/Gemfile.lock | 64 ------------------------------------------ site/docs/_config.yml | 3 -- 5 files changed, 15 insertions(+), 84 deletions(-) delete mode 100644 site/docs/Gemfile delete mode 100644 site/docs/Gemfile.lock diff --git a/gradle.properties b/gradle.properties index b87d2b009f..1ac5febcff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,3 +30,6 @@ source_map_support_version=0.5.3 # Settings kotlin.incremental.multiplatform=true kotlin.native.ignoreDisabledTargets=true + +# Site deneration +jekyll_version=4.0 \ No newline at end of file diff --git a/site/build.gradle b/site/build.gradle index 796fcacaed..c69d9459a1 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -3,6 +3,7 @@ */ def buildDocsDir = "$buildDir/docs" +def jekyllDockerImage = "jekyll/jekyll:$jekyll_version" task copyDocs(type: Copy, dependsOn: rootProject.getTasksByName("dokka", true)) { from (rootProject.getTasksByName("dokka", true).collect { "$it.project.buildDir/dokka" }) { @@ -23,7 +24,17 @@ task site(type: Exec, description: 'Generate github pages', dependsOn: [copyDocs inputs.files(fileTree(buildDocsDir)) outputs.dir("$buildDir/dist") workingDir file(buildDocsDir) - commandLine 'bundle', 'exec', 'jekyll', 'build' + commandLine 'docker', 'run', '--rm', "--volume=$buildDir:/srv/jekyll", + '-t', jekyllDockerImage, + '/bin/bash', '-c', 'cd docs; jekyll build' +} + +// A useful task for local debugging -- serves a site locally +task serve(type: Exec, dependsOn: [copyDocs, copyExampleFrontendJs]) { + commandLine 'docker', 'run', '--rm', "--volume=$buildDir:/srv/jekyll", + '-p', '8080:8080', + '-t', jekyllDockerImage, + '/bin/bash', '-c', 'cd docs; jekyll serve --host 0.0.0.0 --port 8080' } task clean(type: Delete) { diff --git a/site/docs/Gemfile b/site/docs/Gemfile deleted file mode 100644 index dcf29c30b1..0000000000 --- a/site/docs/Gemfile +++ /dev/null @@ -1,16 +0,0 @@ -source "https://rubygems.org" -ruby RUBY_VERSION - -# Hello! This is where you manage which Jekyll version is used to run. -# When you want to use a different version, change it below, save the -# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: -# -# bundle exec jekyll serve -# -# This will help ensure the proper Jekyll version is running. -# Happy Jekylling! - -gem "jekyll", "3.6.3" - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] diff --git a/site/docs/Gemfile.lock b/site/docs/Gemfile.lock deleted file mode 100644 index f7f42451da..0000000000 --- a/site/docs/Gemfile.lock +++ /dev/null @@ -1,64 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) - colorator (1.1.0) - ffi (1.9.25) - ffi (1.9.25-x64-mingw32) - forwardable-extended (2.6.0) - jekyll (3.6.3) - addressable (~> 2.4) - colorator (~> 1.0) - jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 1.1) - kramdown (~> 1.14) - liquid (~> 4.0) - mercenary (~> 0.3.3) - pathutil (~> 0.9) - rouge (>= 1.7, < 3) - safe_yaml (~> 1.0) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-watch (1.5.1) - listen (~> 3.0) - kramdown (1.17.0) - liquid (4.0.1) - listen (3.1.5) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - ruby_dep (~> 1.2) - mercenary (0.3.6) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (3.0.3) - rb-fsevent (0.10.3) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) - rouge (2.2.1) - ruby_dep (1.5.0) - safe_yaml (1.0.4) - sass (3.7.2) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - thread_safe (0.3.6) - tzinfo (1.2.4) - thread_safe (~> 0.1) - tzinfo-data (1.2017.3) - tzinfo (>= 1.0.0) - -PLATFORMS - ruby - x64-mingw32 - -DEPENDENCIES - jekyll (= 3.6.3) - tzinfo-data - -RUBY VERSION - ruby 2.3.7p456 - -BUNDLED WITH - 1.16.1 diff --git a/site/docs/_config.yml b/site/docs/_config.yml index 978e0fb2ec..d7617e1ba1 100644 --- a/site/docs/_config.yml +++ b/site/docs/_config.yml @@ -10,8 +10,5 @@ destination: ../dist # Build settings markdown: kramdown -exclude: - - Gemfile - - Gemfile.lock include: - package-list From 16d2606dc119be0ddb84920ccd36fd949f2fe070 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 25 Dec 2019 14:49:50 +0300 Subject: [PATCH 10/50] Site building docs updated --- RELEASE.md | 3 ++- site/README.md | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 22140e68c7..efb361f1e5 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -53,7 +53,8 @@ To release new `` of `kotlinx-coroutines`: * Create a release named ``. * Cut & paste lines from [`CHANGES.md`](CHANGES.md) into description. -3. Build and publish documentation for web-site:
+3. Build and publish documentation for web-site + (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: diff --git a/site/README.md b/site/README.md index 8533dbf442..7ffb4103fc 100644 --- a/site/README.md +++ b/site/README.md @@ -2,13 +2,14 @@ This module builds references documentation. -## Building - -* Install [Jekyll](https://jekyllrb.com) -* If you already have Ruby/Jekyll installed you might need to update its version: - * `cd site/docs` - * `bundle install` -* In project root directory do: - * Run `./gradlew site` -* The result is in `site/build/gh-pages/_site` -* Upload it to github pages (`gh-pages` branch) +## Building docs + +* Install [Docker](https://www.docker.com/) +* In the project root directory run `./gradlew site` +* The resulting HTML pages are generated in `site/build/dist` +* For continuous testing of the documentation run `./gradlew serve` and navigate + to the URL that is printed on the screen + * Update the docs via `./gradlew copyDocs` while `serve` is running + +For release use [`deploy.sh`](deploy.sh) that performs clean build of the site and pushes the results +into `gh-pages` branch of the project. \ No newline at end of file From 1f77783bb089fcd8328eb7958b95cddc91960468 Mon Sep 17 00:00:00 2001 From: Nikita Koval Date: Wed, 25 Dec 2019 16:24:43 +0300 Subject: [PATCH 11/50] Fix non-linearizability in `ArrayChannel` while moving an element from the waiting queue to the buffer --- .../common/src/channels/AbstractChannel.kt | 31 +++++----- .../common/src/channels/ArrayChannel.kt | 58 +++++++++++-------- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt index b9bd83b118..dfca3b32d1 100644 --- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt @@ -30,6 +30,7 @@ internal abstract class AbstractSendChannel : SendChannel { /** * Returns `true` if this channel's buffer is full. + * This operation should be atomic if it is invoked by [enqueueSend]. * @suppress **This is unstable API and it is subject to change.** */ protected abstract val isBufferFull: Boolean @@ -140,8 +141,8 @@ internal abstract class AbstractSendChannel : SendChannel { // ------ SendChannel ------ public final override val isClosedForSend: Boolean get() = closedForSend != null - public final override val isFull: Boolean get() = full - private val full: Boolean get() = queue.nextNode !is ReceiveOrClosed<*> && isBufferFull // TODO rename to `isFull` + public override val isFull: Boolean get() = isFullImpl + protected val isFullImpl: Boolean get() = queue.nextNode !is ReceiveOrClosed<*> && isBufferFull public final override suspend fun send(element: E) { // fast path -- try offer non-blocking @@ -182,7 +183,7 @@ internal abstract class AbstractSendChannel : SendChannel { private suspend fun sendSuspend(element: E): Unit = suspendAtomicCancellableCoroutineReusable sc@ { cont -> loop@ while (true) { - if (full) { + if (isFullImpl) { val send = SendElement(element, cont) val enqueueResult = enqueueSend(send) when { @@ -227,7 +228,7 @@ internal abstract class AbstractSendChannel : SendChannel { * * ENQUEUE_FAILED -- buffer is not full (should not enqueue) * * ReceiveOrClosed<*> -- receiver is waiting or it is closed (should not enqueue) */ - private fun enqueueSend(send: Send): Any? { + protected open fun enqueueSend(send: Send): Any? { if (isBufferAlwaysFull) { queue.addLastIfPrev(send) { prev -> if (prev is ReceiveOrClosed<*>) return@enqueueSend prev @@ -382,7 +383,7 @@ internal abstract class AbstractSendChannel : SendChannel { private fun registerSelectSend(select: SelectInstance, element: E, block: suspend (SendChannel) -> R) { while (true) { if (select.isSelected) return - if (full) { + if (isFullImpl) { val node = SendSelect(element, this, select, block) val enqueueResult = enqueueSend(node) when { @@ -495,6 +496,7 @@ internal abstract class AbstractChannel : AbstractSendChannel(), Channel : AbstractSendChannel(), Channel : AbstractSendChannel(), Channel): Boolean { - val result = if (isBufferAlwaysEmpty) - queue.addLastIfPrev(receive) { it !is Send } else - queue.addLastIfPrevAndIf(receive, { it !is Send }, { isBufferEmpty }) + protected open fun enqueueReceiveInternal(receive: Receive): Boolean = if (isBufferAlwaysEmpty) + queue.addLastIfPrev(receive) { it !is Send } else + queue.addLastIfPrevAndIf(receive, { it !is Send }, { isBufferEmpty }) + + private fun enqueueReceive(receive: Receive) = enqueueReceiveInternal(receive).also { result -> if (result) onReceiveEnqueued() - return result } public final override suspend fun receiveOrNull(): E? { @@ -718,7 +721,7 @@ internal abstract class AbstractChannel : AbstractSendChannel(), Channel registerSelectReceiveMode(select: SelectInstance, receiveMode: Int, block: suspend (Any?) -> R) { while (true) { if (select.isSelected) return - if (isEmpty) { + if (isEmptyImpl) { if (enqueueReceiveSelect(select, block, receiveMode)) return } else { val pollResult = pollSelectInternal(select) @@ -1058,7 +1061,7 @@ internal class Closed( override fun toString(): String = "Closed@$hexAddress[$closeCause]" } -private abstract class Receive : LockFreeLinkedListNode(), ReceiveOrClosed { +internal abstract class Receive : LockFreeLinkedListNode(), ReceiveOrClosed { override val offerResult get() = OFFER_SUCCESS abstract fun resumeReceiveClosed(closed: Closed<*>) } diff --git a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt index da284be525..aa0e1822ed 100644 --- a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt @@ -36,34 +36,38 @@ internal open class ArrayChannel( */ private var buffer: Array = arrayOfNulls(min(capacity, 8)) private var head: Int = 0 - private var size = 0 // Invariant: size <= capacity + private val size = atomic(0) // Invariant: size <= capacity protected final override val isBufferAlwaysEmpty: Boolean get() = false - protected final override val isBufferEmpty: Boolean get() = lock.withLock { size == 0 } + protected final override val isBufferEmpty: Boolean get() = size.value == 0 protected final override val isBufferAlwaysFull: Boolean get() = false - protected final override val isBufferFull: Boolean get() = lock.withLock { size == capacity } + protected final override val isBufferFull: Boolean get() = size.value == capacity + + override val isFull: Boolean get() = lock.withLock { isFullImpl } + override val isEmpty: Boolean get() = lock.withLock { isEmptyImpl } + override val isClosedForReceive: Boolean get() = lock.withLock { super.isClosedForReceive } // result is `OFFER_SUCCESS | OFFER_FAILED | Closed` protected override fun offerInternal(element: E): Any { var receive: ReceiveOrClosed? = null lock.withLock { - val size = this.size + val size = this.size.value closedForSend?.let { return it } if (size < capacity) { // tentatively put element to buffer - this.size = size + 1 // update size before checking queue (!!!) + this.size.value = size + 1 // update size before checking queue (!!!) // check for receivers that were waiting on empty queue if (size == 0) { loop@ while (true) { receive = takeFirstReceiveOrPeekClosed() ?: break@loop // break when no receivers queued if (receive is Closed) { - this.size = size // restore size + this.size.value = size // restore size return receive!! } val token = receive!!.tryResumeReceive(element, null) if (token != null) { assert { token === RESUME_TOKEN } - this.size = size // restore size + this.size.value = size // restore size return@withLock } } @@ -84,11 +88,11 @@ internal open class ArrayChannel( protected override fun offerSelectInternal(element: E, select: SelectInstance<*>): Any { var receive: ReceiveOrClosed? = null lock.withLock { - val size = this.size + val size = this.size.value closedForSend?.let { return it } if (size < capacity) { // tentatively put element to buffer - this.size = size + 1 // update size before checking queue (!!!) + this.size.value = size + 1 // update size before checking queue (!!!) // check for receivers that were waiting on empty queue if (size == 0) { loop@ while (true) { @@ -96,14 +100,14 @@ internal open class ArrayChannel( val failure = select.performAtomicTrySelect(offerOp) when { failure == null -> { // offered successfully - this.size = size // restore size + this.size.value = size // restore size receive = offerOp.result return@withLock } failure === OFFER_FAILED -> break@loop // cannot offer -> Ok to queue to buffer failure === RETRY_ATOMIC -> {} // retry failure === ALREADY_SELECTED || failure is Closed<*> -> { - this.size = size // restore size + this.size.value = size // restore size return failure } else -> error("performAtomicTrySelect(describeTryOffer) returned $failure") @@ -112,7 +116,7 @@ internal open class ArrayChannel( } // let's try to select sending this element to buffer if (!select.trySelect()) { // :todo: move trySelect completion outside of lock - this.size = size // restore size + this.size.value = size // restore size return ALREADY_SELECTED } ensureCapacity(size) @@ -127,6 +131,10 @@ internal open class ArrayChannel( return receive!!.offerResult } + override fun enqueueSend(send: Send): Any? = lock.withLock { + super.enqueueSend(send) + } + // Guarded by lock private fun ensureCapacity(currentSize: Int) { if (currentSize >= buffer.size) { @@ -146,12 +154,12 @@ internal open class ArrayChannel( var resumed = false var result: Any? = null lock.withLock { - val size = this.size + val size = this.size.value if (size == 0) return closedForSend ?: POLL_FAILED // when nothing can be read from buffer // size > 0: not empty -- retrieve element result = buffer[head] buffer[head] = null - this.size = size - 1 // update size before checking queue (!!!) + this.size.value = size - 1 // update size before checking queue (!!!) // check for senders that were waiting on full queue var replacement: Any? = POLL_FAILED if (size == capacity) { @@ -167,7 +175,7 @@ internal open class ArrayChannel( } } if (replacement !== POLL_FAILED && replacement !is Closed<*>) { - this.size = size // restore size + this.size.value = size // restore size buffer[(head + size) % buffer.size] = replacement } head = (head + 1) % buffer.size @@ -184,12 +192,12 @@ internal open class ArrayChannel( var success = false var result: Any? = null lock.withLock { - val size = this.size + val size = this.size.value if (size == 0) return closedForSend ?: POLL_FAILED // size > 0: not empty -- retrieve element result = buffer[head] buffer[head] = null - this.size = size - 1 // update size before checking queue (!!!) + this.size.value = size - 1 // update size before checking queue (!!!) // check for senders that were waiting on full queue var replacement: Any? = POLL_FAILED if (size == capacity) { @@ -206,7 +214,7 @@ internal open class ArrayChannel( failure === POLL_FAILED -> break@loop // cannot poll -> Ok to take from buffer failure === RETRY_ATOMIC -> {} // retry failure === ALREADY_SELECTED -> { - this.size = size // restore size + this.size.value = size // restore size buffer[head] = result // restore head return failure } @@ -221,12 +229,12 @@ internal open class ArrayChannel( } } if (replacement !== POLL_FAILED && replacement !is Closed<*>) { - this.size = size // restore size + this.size.value = size // restore size buffer[(head + size) % buffer.size] = replacement } else { // failed to poll or is already closed --> let's try to select receiving this element from buffer if (!select.trySelect()) { // :todo: move trySelect completion outside of lock - this.size = size // restore size + this.size.value = size // restore size buffer[head] = result // restore head return ALREADY_SELECTED } @@ -239,16 +247,20 @@ internal open class ArrayChannel( return result } + override fun enqueueReceiveInternal(receive: Receive): Boolean = lock.withLock { + super.enqueueReceiveInternal(receive) + } + // Note: this function is invoked when channel is already closed override fun onCancelIdempotent(wasClosed: Boolean) { // clear buffer first, but do not wait for it in helpers if (wasClosed) { lock.withLock { - repeat(size) { + repeat(size.value) { buffer[head] = 0 head = (head + 1) % buffer.size } - size = 0 + size.value = 0 } } // then clean all queued senders @@ -258,5 +270,5 @@ internal open class ArrayChannel( // ------ debug ------ override val bufferDebugString: String - get() = "(buffer:capacity=$capacity,size=$size)" + get() = "(buffer:capacity=$capacity,size=${size.value})" } From 4f24a7a71f83564089c5871d48b94bc758d6c079 Mon Sep 17 00:00:00 2001 From: Nikita Koval Date: Tue, 12 Nov 2019 15:54:50 +0300 Subject: [PATCH 12/50] Update lincheck to 2.5.3 and re-write the corresponding tests --- build.gradle | 2 +- gradle.properties | 2 +- kotlinx-coroutines-core/build.gradle | 2 +- .../common/test/channels/TestChannelKind.kt | 55 ++--- .../jvm/test/LCStressOptionsDefault.kt | 20 ++ kotlinx-coroutines-core/jvm/test/TestBase.kt | 4 + .../test/internal/SegmentQueueLCStressTest.kt | 30 --- .../ChannelCloseLCStressTest.kt | 82 ------- .../ChannelIsClosedLCStressTest.kt | 54 ----- .../linearizability/ChannelLCStressTest.kt | 73 ------ .../linearizability/ChannelsLCStressTest.kt | 226 ++++++++++++++++++ .../jvm/test/linearizability/LinTesting.kt | 138 ----------- .../LockFreeListLCStressTest.kt | 40 +--- .../LockFreeTaskQueueLCStressTest.kt | 89 ++----- .../SegmentQueueLCStressTest.kt | 40 ++++ 15 files changed, 342 insertions(+), 515 deletions(-) create mode 100644 kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/internal/SegmentQueueLCStressTest.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/linearizability/ChannelCloseLCStressTest.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/linearizability/ChannelIsClosedLCStressTest.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/linearizability/ChannelLCStressTest.kt create mode 100644 kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/linearizability/LinTesting.kt create mode 100644 kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt diff --git a/build.gradle b/build.gradle index c410ff73f7..01345b6f95 100644 --- a/build.gradle +++ b/build.gradle @@ -101,7 +101,7 @@ allprojects { kotlin_version = rootProject.properties['kotlin_snapshot_version'] } - if (build_snapshot_train || atomicfu_version.endsWith("-SNAPSHOT")) { + if (build_snapshot_train || atomicfu_version.endsWith("-SNAPSHOT") || lincheck_version.endsWith("-SNAPSHOT")) { repositories { mavenLocal() maven { url "https://oss.sonatype.org/content/repositories/snapshots" } diff --git a/gradle.properties b/gradle.properties index 1ac5febcff..6d8456a5a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ kotlin_version=1.3.61 junit_version=4.12 atomicfu_version=0.14.1 html_version=0.6.8 -lincheck_version=2.0 +lincheck_version=2.5.3 dokka_version=0.9.16-rdev-2-mpp-hacks byte_buddy_version=1.9.3 reactor_vesion=3.2.5.RELEASE diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index 4d516962e9..6fedd7c016 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -48,7 +48,7 @@ configurations { kotlin.sourceSets { jvmTest.dependencies { - api "com.devexperts.lincheck:lincheck:$lincheck_version" + api "org.jetbrains.kotlinx:lincheck:$lincheck_version" api "com.esotericsoftware:kryo:4.0.0" implementation project (":android-unit-tests") } diff --git a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt index 27c58165c1..69d8fd03e3 100644 --- a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt +++ b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt @@ -7,45 +7,26 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* import kotlinx.coroutines.selects.* -enum class TestChannelKind { - RENDEZVOUS { - override fun create(): Channel = Channel(Channel.RENDEZVOUS) - override fun toString(): String = "RendezvousChannel" - }, - ARRAY_1 { - override fun create(): Channel = Channel(1) - override fun toString(): String = "ArrayChannel(1)" - }, - ARRAY_10 { - override fun create(): Channel = Channel(10) - override fun toString(): String = "ArrayChannel(10)" - }, - LINKED_LIST { - override fun create(): Channel = Channel(Channel.UNLIMITED) - override fun toString(): String = "LinkedListChannel" - }, - CONFLATED { - override fun create(): Channel = Channel(Channel.CONFLATED) - override fun toString(): String = "ConflatedChannel" - override val isConflated: Boolean get() = true - }, - ARRAY_BROADCAST_1 { - override fun create(): Channel = ChannelViaBroadcast(BroadcastChannel(1)) - override fun toString(): String = "ArrayBroadcastChannel(1)" - }, - ARRAY_BROADCAST_10 { - override fun create(): Channel = ChannelViaBroadcast(BroadcastChannel(10)) - override fun toString(): String = "ArrayBroadcastChannel(10)" - }, - CONFLATED_BROADCAST { - override fun create(): Channel = ChannelViaBroadcast(ConflatedBroadcastChannel()) - override fun toString(): String = "ConflatedBroadcastChannel" - override val isConflated: Boolean get() = true - } +enum class TestChannelKind(val capacity: Int, + private val description: String, + private val viaBroadcast: Boolean = false +) { + RENDEZVOUS(0, "RendezvousChannel"), + ARRAY_1(1, "ArrayChannel(1)"), + ARRAY_2(2, "ArrayChannel(2)"), + ARRAY_10(10, "ArrayChannel(10)"), + LINKED_LIST(Channel.UNLIMITED, "LinkedListChannel"), + CONFLATED(Channel.CONFLATED, "ConflatedChannel"), + ARRAY_1_BROADCAST(1, "ArrayBroadcastChannel(1)", viaBroadcast = true), + ARRAY_10_BROADCAST(10, "ArrayBroadcastChannel(10)", viaBroadcast = true), + CONFLATED_BROADCAST(Channel.CONFLATED, "ConflatedBroadcastChannel", viaBroadcast = true) ; - abstract fun create(): Channel - open val isConflated: Boolean get() = false + fun create(): Channel = if (viaBroadcast) ChannelViaBroadcast(BroadcastChannel(capacity)) + else Channel(capacity) + + val isConflated get() = capacity == Channel.CONFLATED + override fun toString(): String = description } private class ChannelViaBroadcast( diff --git a/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt b/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt new file mode 100644 index 0000000000..62ded9f969 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt @@ -0,0 +1,20 @@ +/* + * 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/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt index 9c3efb4a39..bf462cc78f 100644 --- a/kotlinx-coroutines-core/jvm/test/TestBase.kt +++ b/kotlinx-coroutines-core/jvm/test/TestBase.kt @@ -7,9 +7,11 @@ package kotlinx.coroutines import kotlinx.coroutines.internal.* import kotlinx.coroutines.scheduling.* import org.junit.* +import java.lang.Math.* import java.util.* import java.util.concurrent.atomic.* import kotlin.coroutines.* +import kotlin.math.* import kotlin.test.* private val VERBOSE = systemProp("test.verbose", false) @@ -26,6 +28,8 @@ public val stressTestMultiplierSqrt = if (isStressTest) 5 else 1 */ public actual val stressTestMultiplier = stressTestMultiplierSqrt * stressTestMultiplierSqrt +public val stressTestMultiplierCbrt = cbrt(stressTestMultiplier.toDouble()).roundToInt() + /** * Base class for tests, so that tests for predictable scheduling of actions in multiple coroutines sharing a single * thread can be written. Use it like this: diff --git a/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueLCStressTest.kt deleted file mode 100644 index c8493f6f30..0000000000 --- a/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueLCStressTest.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 kotlinx.coroutines.internal - -import com.devexperts.dxlab.lincheck.LinChecker -import com.devexperts.dxlab.lincheck.annotations.Operation -import com.devexperts.dxlab.lincheck.annotations.Param -import com.devexperts.dxlab.lincheck.paramgen.IntGen -import com.devexperts.dxlab.lincheck.strategy.stress.StressCTest -import org.junit.Test - -@StressCTest -class SegmentQueueLCStressTest { - private val q = SegmentBasedQueue() - - @Operation - fun add(@Param(gen = IntGen::class) x: Int) { - q.enqueue(x) - } - - @Operation - fun poll(): Int? = q.dequeue() - - @Test - fun test() { - LinChecker.check(SegmentQueueLCStressTest::class.java) - } -} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelCloseLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelCloseLCStressTest.kt deleted file mode 100644 index 5bdc2841dc..0000000000 --- a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelCloseLCStressTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2016-2019 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 com.devexperts.dxlab.lincheck.* -import com.devexperts.dxlab.lincheck.annotations.* -import com.devexperts.dxlab.lincheck.paramgen.* -import com.devexperts.dxlab.lincheck.strategy.stress.* -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.* -import org.junit.* -import java.io.* - -/** - * This is stress test that is fine-tuned to catch the problem - * [#1419](https://github.com/Kotlin/kotlinx.coroutines/issues/1419) - */ -@Param(name = "value", gen = IntGen::class, conf = "2:2") -@OpGroupConfig.OpGroupConfigs( - OpGroupConfig(name = "send", nonParallel = true), - OpGroupConfig(name = "receive", nonParallel = true), - OpGroupConfig(name = "close", nonParallel = true) -) -class ChannelCloseLCStressTest : TestBase() { - - private companion object { - // Emulating ctor argument for lincheck - var capacity = 0 - } - - private val lt = LinTesting() - private var channel: Channel = Channel(capacity) - - @Operation(runOnce = true, group = "send") - fun send1(@Param(name = "value") value: Int) = lt.run("send1") { channel.send(value) } - - @Operation(runOnce = true, group = "send") - fun send2(@Param(name = "value") value: Int) = lt.run("send2") { channel.send(value) } - - @Operation(runOnce = true, group = "receive") - fun receive1() = lt.run("receive1") { channel.receive() } - - @Operation(runOnce = true, group = "receive") - fun receive2() = lt.run("receive2") { channel.receive() } - - @Operation(runOnce = true, group = "close") - fun close1() = lt.run("close1") { channel.close(IOException("close1")) } - - @Operation(runOnce = true, group = "close") - fun close2() = lt.run("close2") { channel.close(IOException("close2")) } - - @Test - fun testRendezvousChannelLinearizability() { - runTest(0) - } - - @Test - fun testArrayChannelLinearizability() { - for (i in listOf(1, 2, 16)) { - runTest(i) - } - } - - @Test - fun testConflatedChannelLinearizability() = runTest(Channel.CONFLATED) - - @Test - fun testUnlimitedChannelLinearizability() = runTest(Channel.UNLIMITED) - - private fun runTest(capacity: Int) { - ChannelCloseLCStressTest.capacity = capacity - val options = StressOptions() - .iterations(1) // only one iteration -- test scenario is fixed - .invocationsPerIteration(10_000 * stressTestMultiplierSqrt) - .threads(3) - .verifier(LinVerifier::class.java) - LinChecker.check(ChannelCloseLCStressTest::class.java, options) - } -} diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelIsClosedLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelIsClosedLCStressTest.kt deleted file mode 100644 index 44ba182dd3..0000000000 --- a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelIsClosedLCStressTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016-2019 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 com.devexperts.dxlab.lincheck.* -import com.devexperts.dxlab.lincheck.annotations.* -import com.devexperts.dxlab.lincheck.paramgen.* -import com.devexperts.dxlab.lincheck.strategy.stress.* -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.* -import org.junit.* -import java.io.* - -@Param(name = "value", gen = IntGen::class, conf = "1:3") -class ChannelIsClosedLCStressTest : TestBase() { - - private val lt = LinTesting() - private val channel = Channel() - - @Operation(runOnce = true) - fun send1(@Param(name = "value") value: Int) = lt.run("send1") { channel.send(value) } - - @Operation(runOnce = true) - fun send2(@Param(name = "value") value: Int) = lt.run("send2") { channel.send(value) } - - @Operation(runOnce = true) - fun receive1() = lt.run("receive1") { channel.receive() } - - @Operation(runOnce = true) - fun receive2() = lt.run("receive2") { channel.receive() } - - @Operation(runOnce = true) - fun close1() = lt.run("close1") { channel.close(IOException("close1")) } - - @Operation(runOnce = true) - fun isClosedForReceive() = lt.run("isClosedForReceive") { channel.isClosedForReceive } - - @Operation(runOnce = true) - fun isClosedForSend() = lt.run("isClosedForSend") { channel.isClosedForSend } - - @Test - fun testLinearizability() { - val options = StressOptions() - .iterations(100 * stressTestMultiplierSqrt) - .invocationsPerIteration(1000 * stressTestMultiplierSqrt) - .threads(3) - .verifier(LinVerifier::class.java) - - LinChecker.check(ChannelIsClosedLCStressTest::class.java, options) - } -} diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelLCStressTest.kt deleted file mode 100644 index f4b775631f..0000000000 --- a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelLCStressTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2016-2019 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 com.devexperts.dxlab.lincheck.* -import com.devexperts.dxlab.lincheck.annotations.* -import com.devexperts.dxlab.lincheck.paramgen.* -import com.devexperts.dxlab.lincheck.strategy.stress.* -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.* -import org.junit.* -import java.io.* - -@Param(name = "value", gen = IntGen::class, conf = "1:3") -class ChannelLCStressTest : TestBase() { - - private companion object { - // Emulating ctor argument for lincheck - var capacity = 0 - } - - private val lt = LinTesting() - private var channel: Channel = Channel(capacity) - - @Operation(runOnce = true) - fun send1(@Param(name = "value") value: Int) = lt.run("send1") { channel.send(value) } - - @Operation(runOnce = true) - fun send2(@Param(name = "value") value: Int) = lt.run("send2") { channel.send(value) } - - @Operation(runOnce = true) - fun receive1() = lt.run("receive1") { channel.receive() } - - @Operation(runOnce = true) - fun receive2() = lt.run("receive2") { channel.receive() } - - @Operation(runOnce = true) - fun close1() = lt.run("close1") { channel.close(IOException("close1")) } - - @Operation(runOnce = true) - fun close2() = lt.run("close2") { channel.close(IOException("close2")) } - - @Test - fun testRendezvousChannelLinearizability() { - runTest(0) - } - - @Test - fun testArrayChannelLinearizability() { - for (i in listOf(1, 2, 16)) { - runTest(i) - } - } - - @Test - fun testConflatedChannelLinearizability() = runTest(Channel.CONFLATED) - - @Test - fun testUnlimitedChannelLinearizability() = runTest(Channel.UNLIMITED) - - private fun runTest(capacity: Int) { - ChannelLCStressTest.capacity = capacity - val options = StressOptions() - .iterations(50 * stressTestMultiplierSqrt) - .invocationsPerIteration(500 * stressTestMultiplierSqrt) - .threads(3) - .verifier(LinVerifier::class.java) - LinChecker.check(ChannelLCStressTest::class.java, options) - } -} diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt new file mode 100644 index 0000000000..625c620497 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt @@ -0,0 +1,226 @@ +/* + * Copyright 2016-2019 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.channels.* +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.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( + c = Channel(RENDEZVOUS), + sequentialSpecification = SequentialRendezvousChannel::class.java +) +class SequentialRendezvousChannel : SequentialIntChannelBase(RENDEZVOUS) + +class Array1ChannelLCStressTest : ChannelLCStressTestBase( + c = Channel(1), + sequentialSpecification = SequentialArray1RendezvousChannel::class.java +) +class SequentialArray1RendezvousChannel : SequentialIntChannelBase(1) + +class Array2ChannelLCStressTest : ChannelLCStressTestBase( + c = Channel(2), + sequentialSpecification = SequentialArray2RendezvousChannel::class.java +) +class SequentialArray2RendezvousChannel : SequentialIntChannelBase(2) + +class UnlimitedChannelLCStressTest : ChannelLCStressTestBase( + c = Channel(UNLIMITED), + sequentialSpecification = SequentialUnlimitedChannel::class.java +) +class SequentialUnlimitedChannel : SequentialIntChannelBase(UNLIMITED) + +class ConflatedChannelLCStressTest : ChannelLCStressTestBase( + c = Channel(CONFLATED), + sequentialSpecification = SequentialConflatedChannel::class.java +) +class SequentialConflatedChannel : SequentialIntChannelBase(CONFLATED) + + +@Param.Params( + 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 + suspend fun send(@Param(name = "value") value: Int): Any = try { + c.send(value) + } catch (e: NumberedCancellationException) { + e.testResult + } + + @Operation + fun offer(@Param(name = "value") value: Int): Any = try { + c.offer(value) + } catch (e: NumberedCancellationException) { + e.testResult + } + + // TODO: this operation should be (and can be!) linearizable, but is not + // @Operation + suspend fun sendViaSelect(@Param(name = "value") value: Int): Any = try { + select { c.onSend(value) {} } + } catch (e: NumberedCancellationException) { + e.testResult + } + + @Operation + suspend fun receive(): Any = try { + c.receive() + } catch (e: NumberedCancellationException) { + e.testResult + } + + @Operation + fun poll(): Any? = try { + c.poll() + } catch (e: NumberedCancellationException) { + e.testResult + } + + // TODO: this operation should be (and can be!) linearizable, but is not + // @Operation + suspend fun receiveViaSelect(): Any = try { + select { c.onReceive { it } } + } catch (e: NumberedCancellationException) { + e.testResult + } + + @Operation + fun close(@Param(name = "closeToken") token: Int): Boolean = c.close(NumberedCancellationException(token)) + + // TODO: this operation should be (and can be!) linearizable, but is not + // @Operation + fun cancel(@Param(name = "closeToken") token: Int) = c.cancel(NumberedCancellationException(token)) + +// @Operation + fun isClosedForReceive() = c.isClosedForReceive + +// @Operation + fun isClosedForSend() = c.isClosedForSend + + // TODO: this operation should be (and can be!) linearizable, but is not + // @Operation + fun isEmpty() = c.isEmpty + + @Test + fun test() = LCStressOptionsDefault() + .actorsBefore(0) + .sequentialSpecification(sequentialSpecification) + .check(this::class) +} + +private class NumberedCancellationException(number: Int) : CancellationException() { + val testResult = "Closed($number)" +} + + +abstract class SequentialIntChannelBase(private val capacity: Int) : VerifierState() { + private val senders = ArrayList, Int>>() + private val receivers = ArrayList>() + private val buffer = ArrayList() + private var closedMessage: String? = null + + suspend fun send(x: Int): Any = when (val offerRes = offer(x)) { + true -> Unit + false -> suspendCancellableCoroutine { cont -> + senders.add(cont to x) + } + else -> offerRes + } + + fun offer(element: Int): Any { + if (closedMessage !== null) return closedMessage!! + if (capacity == CONFLATED) { + if (resumeFirstReceiver(element)) return true + buffer.clear() + buffer.add(element) + return true + } + if (resumeFirstReceiver(element)) return true + if (buffer.size < capacity) { + buffer.add(element) + return true + } + return false + } + + private fun resumeFirstReceiver(element: Int): Boolean { + while (receivers.isNotEmpty()) { + val r = receivers.removeAt(0) + if (r.resume(element)) return true + } + return false + } + + suspend fun receive(): Any = poll() ?: suspendCancellableCoroutine { cont -> + receivers.add(cont) + } + + fun poll(): Any? { + if (buffer.isNotEmpty()) { + val el = buffer.removeAt(0) + resumeFirstSender().also { + if (it !== null) buffer.add(it) + } + return el + } + resumeFirstSender()?.also { return it } + if (closedMessage !== null) return closedMessage + return null + } + + private fun resumeFirstSender(): Int? { + while (senders.isNotEmpty()) { + val (s, el) = senders.removeAt(0) + if (s.resume(Unit)) return el + } + return null + } + + suspend fun sendViaSelect(element: Int) = send(element) + suspend fun receiveViaSelect() = receive() + + fun close(token: Int): Boolean { + if (closedMessage !== null) return false + closedMessage = "Closed($token)" + for (r in receivers) r.resume(closedMessage!!) + receivers.clear() + return true + } + + fun cancel(token: Int) { + if (!close(token)) return + for ((s, _) in senders) s.resume(closedMessage!!) + senders.clear() + buffer.clear() + } + + fun isClosedForSend(): Boolean = closedMessage !== null + fun isClosedForReceive(): Boolean = isClosedForSend() && buffer.isEmpty() && senders.isEmpty() + + fun isEmpty(): Boolean { + if (closedMessage !== null) return false + return buffer.isEmpty() && senders.isEmpty() + } + + override fun extractState() = buffer to closedMessage +} + +private fun CancellableContinuation.resume(res: T): Boolean { + val token = tryResume(res) ?: return false + completeResume(token) + return true +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LinTesting.kt b/kotlinx-coroutines-core/jvm/test/linearizability/LinTesting.kt deleted file mode 100644 index 14cf2a7039..0000000000 --- a/kotlinx-coroutines-core/jvm/test/linearizability/LinTesting.kt +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines - -import com.devexperts.dxlab.lincheck.Actor -import com.devexperts.dxlab.lincheck.Result -import com.devexperts.dxlab.lincheck.Utils.* -import com.devexperts.dxlab.lincheck.execution.* -import com.devexperts.dxlab.lincheck.verifier.Verifier -import java.lang.reflect.Method -import java.util.* -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn - -data class OpResult(val name: String, val value: Any?) { - override fun toString(): String = "$name=$value" -} - -private const val CS_STR = "COROUTINE_SUSPENDED" - -class LinTesting { - private val resumed = object : ThreadLocal>() { - override fun initialValue() = arrayListOf() - } - - private inline fun wrap(block: () -> Any?): Any? = - try { repr(block()) } - catch(e: Throwable) { repr(e) } - - private fun repr(e: Any?): Any? = - when { - e === COROUTINE_SUSPENDED -> CS_STR - e is Throwable -> e.toString() - else -> e - } - - fun run(name: String, block: suspend () -> T): List { - val list = resumed.get() - list.clear() - val result = arrayListOf(OpResult(name, wrap { - block.startCoroutineUninterceptedOrReturn(completion = object : Continuation { - override val context: CoroutineContext - get() = EmptyCoroutineContext - - override fun resumeWith(result: kotlin.Result) { - val value = if (result.isSuccess) result.getOrNull() else result.exceptionOrNull() - resumed.get() += OpResult(name, repr(value)) - } - } - ) - })) - result.addAll(list) - return result - } -} - -class LinVerifier(scenario: ExecutionScenario, - testClass: Class<*>) : Verifier { - private val possibleResultsSet: Set>> = - generateAllLinearizableExecutions(scenario.parallelExecution) - .asSequence() - .map { linEx: List -> - val res: List = executeActors(testClass.newInstance(), linEx) - val actorIds = linEx.asSequence().withIndex().associateBy({ it.value}, { it.index }) - scenario.parallelExecution.map { actors -> actors.map { actor -> res[actorIds[actor]!!] } } - }.toSet() - - override fun verifyResults(results: ExecutionResult): Boolean { - if (!valid(results.parallelResults)) { - println("\nNon-linearizable execution:") - printResults(results.parallelResults) - println("\nPossible linearizable executions:") - possibleResultsSet.forEach { possibleResults -> - printResults(possibleResults) - println() - } - throw AssertionError("Non-linearizable execution detected, see log for details") - } - - return true - } - - private fun printResults(results: List>) { - results.forEachIndexed { index, res -> - println("Thread $index: $res") - } - println("Op map: ${results.toOpMap()}") - } - - private fun valid(results: List>): Boolean = - (results in possibleResultsSet) || possibleResultsSet.any { matches(results, it) } - - private fun matches(results: List>, possible: List>): Boolean = - results.toOpMap() == possible.toOpMap() - - private fun List>.toOpMap(): Map> { - val filtered = flatMap { it }.flatMap { it.resultValue }.filter { it.value != CS_STR } - return filtered.groupBy({ it.name }, { it.value }) - } - - private fun generateAllLinearizableExecutions(actorsPerThread: List>): List> { - val executions = ArrayList>() - generateLinearizableExecutions0( - executions, actorsPerThread, ArrayList(), IntArray(actorsPerThread.size), - actorsPerThread.sumBy { it.size }) - return executions - } - - @Suppress("UNCHECKED_CAST") - private fun generateLinearizableExecutions0(executions: MutableList>, actorsPerThread: List>, - currentExecution: ArrayList, indexes: IntArray, length: Int) { - if (currentExecution.size == length) { - executions.add(currentExecution.clone() as List) - return - } - for (i in indexes.indices) { - val actors = actorsPerThread[i] - if (indexes[i] == actors.size) - continue - currentExecution.add(actors[indexes[i]]) - indexes[i]++ - generateLinearizableExecutions0(executions, actorsPerThread, currentExecution, indexes, length) - indexes[i]-- - currentExecution.removeAt(currentExecution.size - 1) - } - } -} - -private val VALUE = Result::class.java.getDeclaredField("value").apply { isAccessible = true } - -@Suppress("UNCHECKED_CAST") -private val Result.resultValue: List - get() = VALUE.get(this) as List diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt index 546615489b..5f91c640a6 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt @@ -5,16 +5,16 @@ package kotlinx.coroutines.linearizability -import com.devexperts.dxlab.lincheck.* -import com.devexperts.dxlab.lincheck.annotations.* -import com.devexperts.dxlab.lincheck.paramgen.* -import com.devexperts.dxlab.lincheck.strategy.stress.* 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.* -@Param(name = "value", gen = IntGen::class, conf = "1:3") -class LockFreeListLCStressTest : TestBase() { +@Param(name = "value", gen = IntGen::class, conf = "1:5") +class LockFreeListLCStressTest : VerifierState() { class Node(val value: Int): LockFreeLinkedListNode() private val q: LockFreeLinkedListHead = LockFreeLinkedListHead() @@ -44,29 +44,11 @@ class LockFreeListLCStressTest : TestBase() { private fun Any.isSame(value: Int) = this is Node && this.value == value @Test - fun testAddRemoveLinearizability() { - val options = StressOptions() - .iterations(100 * stressTestMultiplierSqrt) - .invocationsPerIteration(1000 * stressTestMultiplierSqrt) - .threads(3) - LinChecker.check(LockFreeListLCStressTest::class.java, options) - } - - private var _curElements: ArrayList? = null - private val curElements: ArrayList get() { - if (_curElements == null) { - _curElements = ArrayList() - q.forEach { _curElements!!.add(it.value) } - } - return _curElements!! - } - - override fun equals(other: Any?): Boolean { - other as LockFreeListLCStressTest - return curElements == other.curElements - } + fun testAddRemoveLinearizability() = LCStressOptionsDefault().check(this::class) - override fun hashCode(): Int { - return curElements.hashCode() + override fun extractState(): Any { + val elements = ArrayList() + q.forEach { elements.add(it.value) } + return elements } } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt index ea2afa1019..de494cc1e6 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt @@ -5,22 +5,19 @@ package kotlinx.coroutines.linearizability -import com.devexperts.dxlab.lincheck.* -import com.devexperts.dxlab.lincheck.annotations.* -import com.devexperts.dxlab.lincheck.paramgen.* -import com.devexperts.dxlab.lincheck.strategy.stress.* 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 org.jetbrains.kotlinx.lincheck.verifier.quiescent.* import kotlin.test.* -internal data class Snapshot(val elements: List, val isClosed: Boolean) { - constructor(q: LockFreeTaskQueue) : this(q.map { it }, q.isClosed()) -} - -@OpGroupConfig.OpGroupConfigs(OpGroupConfig(name = "consumer", nonParallel = true)) @Param(name = "value", gen = IntGen::class, conf = "1:3") -class SCLockFreeTaskQueueLCStressTest : LockFreeTaskQueueLCTestBase() { - private val q: LockFreeTaskQueue = LockFreeTaskQueue(singleConsumer = true) +internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLCStressTest protected constructor(singleConsumer: Boolean) : VerifierState() { + @JvmField + protected val q = LockFreeTaskQueue(singleConsumer = singleConsumer) @Operation fun close() = q.close() @@ -28,66 +25,20 @@ class SCLockFreeTaskQueueLCStressTest : LockFreeTaskQueueLCTestBase() { @Operation fun addLast(@Param(name = "value") value: Int) = q.addLast(value) - /** - * Note that removeFirstOrNull is not linearizable w.r.t. to addLast, so here - * we test only linearizability of close. - */ -// @Operation(group = "consumer") -// fun removeFirstOrNull() = q.removeFirstOrNull() - - @Test - fun testSC() = linTest() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as SCLockFreeTaskQueueLCStressTest - - return Snapshot(q) == Snapshot(other.q) - } - - override fun hashCode(): Int = Snapshot(q).hashCode() -} - -@Param(name = "value", gen = IntGen::class, conf = "1:3") -class MCLockFreeTaskQueueLCStressTest : LockFreeTaskQueueLCTestBase() { - private val q: LockFreeTaskQueue = LockFreeTaskQueue(singleConsumer = false) - - @Operation - fun close() = q.close() - - @Operation - fun addLast(@Param(name = "value") value: Int) = q.addLast(value) + @QuiescentConsistent + @Operation(group = "consumer") + fun removeFirstOrNull() = q.removeFirstOrNull() - /** - * Note that removeFirstOrNull is not linearizable w.r.t. to addLast, so here - * we test only linearizability of close. - */ -// @Operation(group = "consumer") -// fun removeFirstOrNull() = q.removeFirstOrNull() + override fun extractState() = q.map { it } to q.isClosed() @Test - fun testMC() = linTest() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as MCLockFreeTaskQueueLCStressTest - - return Snapshot(q) == Snapshot(other.q) - } - - override fun hashCode(): Int = Snapshot(q).hashCode() + fun testWithRemoveForQuiescentConsistency() = LCStressOptionsDefault() + .verifier(QuiescentConsistencyVerifier::class.java) + .check(this::class) } -open class LockFreeTaskQueueLCTestBase : TestBase() { - fun linTest() { - val options = StressOptions() - .iterations(100 * stressTestMultiplierSqrt) - .invocationsPerIteration(1000 * stressTestMultiplierSqrt) - .threads(2) - LinChecker.check(this::class.java, options) - } -} \ No newline at end of file +@OpGroupConfig(name = "consumer", nonParallel = false) +internal class MCLockFreeTaskQueueWithRemoveLCStressTest : AbstractLockFreeTaskQueueWithoutRemoveLCStressTest(singleConsumer = false) + +@OpGroupConfig(name = "consumer", nonParallel = true) +internal class SCLockFreeTaskQueueWithRemoveLCStressTest : AbstractLockFreeTaskQueueWithoutRemoveLCStressTest(singleConsumer = true) \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt new file mode 100644 index 0000000000..1bb51a568f --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2016-2019 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.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.* + +@Param(name = "value", gen = IntGen::class, conf = "1:5") +class SegmentQueueLCStressTest : VerifierState() { + private val q = SegmentBasedQueue() + + @Operation + fun add(@Param(name = "value") value: Int) { + q.enqueue(value) + } + + @Operation + fun poll(): Int? = q.dequeue() + + override fun extractState(): Any { + val elements = ArrayList() + while (true) { + val x = q.dequeue() ?: break + elements.add(x) + } + + return elements + } + + @Test + fun test() = LCStressOptionsDefault().check(this::class) +} \ No newline at end of file From fe15b6d81dcf5c2fc9f905ed7d743a759ce51414 Mon Sep 17 00:00:00 2001 From: fmixing Date: Thu, 26 Dec 2019 11:53:51 +0300 Subject: [PATCH 13/50] Flow.flattenMerge benchmark (#1464) --- benchmarks/build.gradle | 2 + .../generate_plots_flow_flatten_merge.py | 75 +++++++++++++++++++ .../kotlin/benchmarks/SemaphoreBenchmark.kt | 19 ++--- .../flow/FlowFlattenMergeBenchmark.kt | 63 ++++++++++++++++ .../benchmarks/common/BenchmarkUtils.kt | 17 +++++ 5 files changed, 162 insertions(+), 14 deletions(-) create mode 100644 benchmarks/scripts/generate_plots_flow_flatten_merge.py create mode 100644 benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt create mode 100644 benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index 157eb88aa6..88148130c5 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -74,4 +74,6 @@ dependencies { compile "org.openjdk.jmh:jmh-core:1.21" compile 'com.typesafe.akka:akka-actor_2.12:2.5.0' compile project(':kotlinx-coroutines-core') + // add jmh dependency on main + jmh sourceSets.main.runtimeClasspath } diff --git a/benchmarks/scripts/generate_plots_flow_flatten_merge.py b/benchmarks/scripts/generate_plots_flow_flatten_merge.py new file mode 100644 index 0000000000..c7f5ebb88b --- /dev/null +++ b/benchmarks/scripts/generate_plots_flow_flatten_merge.py @@ -0,0 +1,75 @@ +# To run this script run the command 'python3 scripts/generate_plots_flow_flatten_merge.py' in the /benchmarks folder + + +import pandas as pd +import sys +import locale +import matplotlib.pyplot as plt +from matplotlib.ticker import FormatStrFormatter + +input_file = "build/reports/jmh/results.csv" +output_file = "out/flow-flatten-merge.svg" +# Please change the value of this variable according to the FlowFlattenMergeBenchmarkKt.ELEMENTS +elements = 100000 +benchmark_name = "benchmarks.flow.FlowFlattenMergeBenchmark.flattenMerge" +csv_columns = ["Benchmark", "Score", "Unit", "Param: concurrency", "Param: flowsNumberStrategy"] +rename_columns = {"Benchmark": "benchmark", "Score" : "score", "Unit" : "unit", + "Param: concurrency" : "concurrency", "Param: flowsNumberStrategy" : "flows"} + +markers = ['.', 'v', '^', '1', '2', '8', 'p', 'P', 'x', 'D', 'd', 's'] +colours = ['red', 'gold', 'sienna', 'olivedrab', 'lightseagreen', 'navy', 'blue', 'm', 'crimson', 'yellow', 'orangered', 'slateblue', 'aqua', 'black', 'silver'] + +def next_colour(): + i = 0 + while True: + yield colours[i % len(colours)] + i += 1 + +def next_marker(): + i = 0 + while True: + yield markers[i % len(markers)] + i += 1 + +def draw(data, plt): + plt.xscale('log', basex=2) + plt.gca().xaxis.set_major_formatter(FormatStrFormatter('%0.f')) + plt.grid(linewidth='0.5', color='lightgray') + if data.unit.unique()[0] != "ops/s": + print("Unexpected time unit: " + data.unit.unique()[0]) + sys.exit(1) + plt.ylabel("elements / ms") + plt.xlabel('concurrency') + plt.xticks(data.concurrency.unique()) + + colour_gen = next_colour() + marker_gen = next_marker() + for flows in data.flows.unique(): + gen_colour = next(colour_gen) + gen_marker = next(marker_gen) + res = data[(data.flows == flows)] +# plt.plot(res.concurrency, res.score*elements/1000, label="flows={}".format(flows), color=gen_colour, marker=gen_marker) + plt.errorbar(x=res.concurrency, y=res.score*elements/1000, yerr=res.score_error*elements/1000, solid_capstyle='projecting', + label="flows={}".format(flows), capsize=4, color=gen_colour, linewidth=2.2) + +langlocale = locale.getdefaultlocale()[0] +locale.setlocale(locale.LC_ALL, langlocale) +dp = locale.localeconv()['decimal_point'] +if dp == ",": + csv_columns.append("Score Error (99,9%)") + rename_columns["Score Error (99,9%)"] = "score_error" +elif dp == ".": + csv_columns.append("Score Error (99.9%)") + rename_columns["Score Error (99.9%)"] = "score_error" +else: + print("Unexpected locale delimeter: " + dp) + sys.exit(1) +data = pd.read_csv(input_file, sep=",", decimal=dp) +data = data[csv_columns].rename(columns=rename_columns) +data = data[(data.benchmark == benchmark_name)] +plt.rcParams.update({'font.size': 15}) +plt.figure(figsize=(12.5, 10)) +draw(data, plt) +plt.legend(loc='upper center', borderpad=0, bbox_to_anchor=(0.5, 1.3), ncol=2, frameon=False, borderaxespad=2, prop={'size': 15}) +plt.tight_layout(pad=12, w_pad=2, h_pad=1) +plt.savefig(output_file, bbox_inches='tight') diff --git a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt index 0fc563a89e..a651d8fa63 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt @@ -1,5 +1,6 @@ package benchmarks +import benchmarks.common.* import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.scheduling.ExperimentalCoroutineDispatcher @@ -7,7 +8,6 @@ import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import org.openjdk.jmh.annotations.* import java.util.concurrent.ForkJoinPool -import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.TimeUnit @Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MICROSECONDS) @@ -50,9 +50,9 @@ open class SemaphoreBenchmark { jobs += GlobalScope.launch { repeat(n) { semaphore.withPermit { - doWork(WORK_INSIDE) + doGeomDistrWork(WORK_INSIDE) } - doWork(WORK_OUTSIDE) + doGeomDistrWork(WORK_OUTSIDE) } } } @@ -68,9 +68,9 @@ open class SemaphoreBenchmark { jobs += GlobalScope.launch { repeat(n) { semaphore.send(Unit) // acquire - doWork(WORK_INSIDE) + doGeomDistrWork(WORK_INSIDE) semaphore.receive() // release - doWork(WORK_OUTSIDE) + doGeomDistrWork(WORK_OUTSIDE) } } } @@ -83,15 +83,6 @@ enum class SemaphoreBenchDispatcherCreator(val create: (parallelism: Int) -> Cor EXPERIMENTAL({ parallelism -> ExperimentalCoroutineDispatcher(corePoolSize = parallelism, maxPoolSize = parallelism) }) } -private fun doWork(work: Int) { - // We use geometric distribution here - val p = 1.0 / work - val r = ThreadLocalRandom.current() - while (true) { - if (r.nextDouble() < p) break - } -} - private const val WORK_INSIDE = 80 private const val WORK_OUTSIDE = 40 private const val BATCH_SIZE = 1000000 \ No newline at end of file diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt new file mode 100644 index 0000000000..c91c3da964 --- /dev/null +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package benchmarks.flow + +import benchmarks.common.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import org.openjdk.jmh.annotations.* +import java.util.concurrent.* + +/** + * Benchmark to measure performance of [kotlinx.coroutines.flow.FlowKt.flattenMerge]. + * In addition to that, it can be considered as a macro benchmark for the [kotlinx.coroutines.sync.Semaphore] + */ +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +@Fork(1) +open class FlowFlattenMergeBenchmark { + @Param + private var flowsNumberStrategy: FlowsNumberStrategy = FlowsNumberStrategy.`10xConcurrency flows` + + @Param("1", "2", "4", "8") + private var concurrency: Int = 0 + + private lateinit var flow: Flow> + + @Setup + fun setup() { + val n = flowsNumberStrategy.get(concurrency) + val flowElementsToProcess = ELEMENTS / n + + flow = (1..n).asFlow().map { + flow { + repeat(flowElementsToProcess) { + doGeomDistrWork(WORK) + emit(it) + } + } + } + } + + @Benchmark + fun flattenMerge() = runBlocking(Dispatchers.Default) { + flow.flattenMerge(concurrency = concurrency).collect() + } +} + +enum class FlowsNumberStrategy(val get: (concurrency: Int) -> Int) { + `10xConcurrency flows`({ concurrency -> concurrency * 10 }), + `1xConcurrency flows`({ it }), + `100 flows`({ 100 }), + `500 flows`({ 500 }) +} + +// If you change this variable please be sure that you change variable elements in the generate_plots_flow_flatten_merge.py +// python script as well +private const val ELEMENTS = 100_000 +private const val WORK = 100 \ No newline at end of file diff --git a/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt b/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt new file mode 100644 index 0000000000..fd2832bfeb --- /dev/null +++ b/benchmarks/src/main/kotlin/benchmarks/common/BenchmarkUtils.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package benchmarks.common + +import java.util.concurrent.* + +fun doGeomDistrWork(work: Int) { + // We use geometric distribution here. We also checked on macbook pro 13" (2017) that the resulting work times + // are distributed geometrically, see https://github.com/Kotlin/kotlinx.coroutines/pull/1464#discussion_r355705325 + val p = 1.0 / work + val r = ThreadLocalRandom.current() + while (true) { + if (r.nextDouble() < p) break + } +} \ No newline at end of file From 345458b962b464fbb1619389300dc5a6aa2c2f9c Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Thu, 26 Dec 2019 12:59:40 +0300 Subject: [PATCH 14/50] ReceiveChannel.receiveAsFlow extension (#1731) Experimental ReceiveChannel.receiveAsFlow extension convert channel to flow in fan-out fashion allowing for multi-use. * Also, ReceiveChannel.consumeAsFlow is promoted to experimental from preview Fixes #1490 --- .../kotlinx-coroutines-core.txt | 1 + .../common/src/flow/Channels.kt | 58 ++++++++++++++----- .../flow/channels/ChannelBuildersFlowTest.kt | 48 +++++++++++++++ 3 files changed, 93 insertions(+), 14 deletions(-) diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt index d8d4528eb4..6df47e179f 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -943,6 +943,7 @@ public final class kotlinx/coroutines/flow/FlowKt { public static final fun onStart (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow; public static final fun produceIn (Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/channels/ReceiveChannel; public static final fun publishOn (Lkotlinx/coroutines/flow/Flow;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/flow/Flow; + public static final fun receiveAsFlow (Lkotlinx/coroutines/channels/ReceiveChannel;)Lkotlinx/coroutines/flow/Flow; public static final fun reduce (Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final synthetic fun retry (Lkotlinx/coroutines/flow/Flow;ILkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; public static final fun retry (Lkotlinx/coroutines/flow/Flow;JLkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow; diff --git a/kotlinx-coroutines-core/common/src/flow/Channels.kt b/kotlinx-coroutines-core/common/src/flow/Channels.kt index f81bc037e3..612fe8c285 100644 --- a/kotlinx-coroutines-core/common/src/flow/Channels.kt +++ b/kotlinx-coroutines-core/common/src/flow/Channels.kt @@ -23,8 +23,11 @@ import kotlinx.coroutines.flow.internal.unsafeFlow as flow * This function provides a more efficient shorthand for `channel.consumeEach { value -> emit(value) }`. * See [consumeEach][ReceiveChannel.consumeEach]. */ -@ExperimentalCoroutinesApi -public suspend fun FlowCollector.emitAll(channel: ReceiveChannel) { +@ExperimentalCoroutinesApi // since version 1.3.0 +public suspend fun FlowCollector.emitAll(channel: ReceiveChannel) = + emitAllImpl(channel, consume = true) + +private suspend fun FlowCollector.emitAllImpl(channel: ReceiveChannel, consume: Boolean) { // Manually inlined "consumeEach" implementation that does not use iterator but works via "receiveOrClosed". // It has smaller and more efficient spilled state which also allows to implement a manual kludge to // fix retention of the last emitted value. @@ -59,20 +62,43 @@ public suspend fun FlowCollector.emitAll(channel: ReceiveChannel) { cause = e throw e } finally { - channel.cancelConsumed(cause) + if (consume) channel.cancelConsumed(cause) } } +/** + * Represents the given receive channel as a hot flow and [receives][ReceiveChannel.receive] from the channel + * in fan-out fashion every time this flow is collected. One element will be emitted to one collector only. + * + * See also [consumeAsFlow] which ensures that the resulting flow is collected just once. + * + * ### Cancellation semantics + * + * * Flow collectors are cancelled when the original channel is [closed][SendChannel.close] with an exception. + * * Flow collectors complete normally when the original channel is [closed][SendChannel.close] normally. + * * Failure or cancellation of the flow collector does not affect the channel. + * + * ### Operator fusion + * + * Adjacent applications of [flowOn], [buffer], [conflate], and [produceIn] to the result of `receiveAsFlow` are fused. + * In particular, [produceIn] returns the original channel. + * Calls to [flowOn] have generally no effect, unless [buffer] is used to explicitly request buffering. + */ +@ExperimentalCoroutinesApi // since version 1.4.0 +public fun ReceiveChannel.receiveAsFlow(): Flow = ChannelAsFlow(this, consume = false) + /** * Represents the given receive channel as a hot flow and [consumes][ReceiveChannel.consume] the channel * on the first collection from this flow. The resulting flow can be collected just once and throws * [IllegalStateException] when trying to collect it more than once. * + * See also [receiveAsFlow] which supports multiple collectors of the resulting flow. + * * ### Cancellation semantics * - * 1) Flow consumer is cancelled when the original channel is cancelled. - * 2) Flow consumer completes normally when the original channel was closed normally and then fully consumed. - * 3) If the flow consumer fails with an exception, channel is cancelled. + * * Flow collector is cancelled when the original channel is [closed][SendChannel.close] with an exception. + * * Flow collector completes normally when the original channel is [closed][SendChannel.close] normally. + * * If the flow collector fails with an exception, the source channel is [cancelled][ReceiveChannel.cancel]. * * ### Operator fusion * @@ -80,8 +106,8 @@ public suspend fun FlowCollector.emitAll(channel: ReceiveChannel) { * In particular, [produceIn] returns the original channel (but throws [IllegalStateException] on repeated calls). * Calls to [flowOn] have generally no effect, unless [buffer] is used to explicitly request buffering. */ -@FlowPreview -public fun ReceiveChannel.consumeAsFlow(): Flow = ConsumeAsFlow(this) +@ExperimentalCoroutinesApi // since version 1.3.0 +public fun ReceiveChannel.consumeAsFlow(): Flow = ChannelAsFlow(this, consume = true) /** * Represents an existing [channel] as [ChannelFlow] implementation. @@ -89,21 +115,25 @@ public fun ReceiveChannel.consumeAsFlow(): Flow = ConsumeAsFlow(this) * However, additional [buffer] calls cause a separate buffering channel to be created and that is where * the context might play a role, because it is used by the producing coroutine. */ -private class ConsumeAsFlow( +private class ChannelAsFlow( private val channel: ReceiveChannel, + private val consume: Boolean, context: CoroutineContext = EmptyCoroutineContext, capacity: Int = Channel.OPTIONAL_CHANNEL ) : ChannelFlow(context, capacity) { private val consumed = atomic(false) - private fun markConsumed() = - check(!consumed.getAndSet(true)) { "ReceiveChannel.consumeAsFlow can be collected just once" } + private fun markConsumed() { + if (consume) { + check(!consumed.getAndSet(true)) { "ReceiveChannel.consumeAsFlow can be collected just once" } + } + } override fun create(context: CoroutineContext, capacity: Int): ChannelFlow = - ConsumeAsFlow(channel, context, capacity) + ChannelAsFlow(channel, consume, context, capacity) override suspend fun collectTo(scope: ProducerScope) = - SendingCollector(scope).emitAll(channel) // use efficient channel receiving code from emitAll + SendingCollector(scope).emitAllImpl(channel, consume) // use efficient channel receiving code from emitAll override fun broadcastImpl(scope: CoroutineScope, start: CoroutineStart): BroadcastChannel { markConsumed() // fail fast on repeated attempt to collect it @@ -121,7 +151,7 @@ private class ConsumeAsFlow( override suspend fun collect(collector: FlowCollector) { if (capacity == Channel.OPTIONAL_CHANNEL) { markConsumed() - collector.emitAll(channel) // direct + collector.emitAllImpl(channel, consume) // direct } else { super.collect(collector) // extra buffering channel, produceImpl will mark it as consumed } diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt index de5c220f31..8dd6e3c8a7 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt @@ -21,6 +21,18 @@ class ChannelBuildersFlowTest : TestBase() { assertFailsWith { flow.collect() } } + @Test + fun testChannelReceiveAsFlow() = runTest { + val channel = produce { + repeat(10) { + send(it + 1) + } + } + val flow = channel.receiveAsFlow() + assertEquals(55, flow.sum()) + assertEquals(emptyList(), flow.toList()) + } + @Test fun testConsumeAsFlowCancellation() = runTest { val channel = produce(NonCancellable) { // otherwise failure will cancel scope as well @@ -36,6 +48,20 @@ class ChannelBuildersFlowTest : TestBase() { assertFailsWith { flow.collect() } } + @Test + fun testReceiveAsFlowCancellation() = runTest { + val channel = produce(NonCancellable) { // otherwise failure will cancel scope as well + repeat(10) { + send(it + 1) + } + throw TestException() + } + val flow = channel.receiveAsFlow() + assertEquals(15, flow.take(5).sum()) // sum of first 5 + assertEquals(40, flow.take(5).sum()) // sum the rest 5 + assertFailsWith { flow.sum() } // exception in the rest + } + @Test fun testConsumeAsFlowException() = runTest { val channel = produce(NonCancellable) { // otherwise failure will cancel scope as well @@ -49,6 +75,19 @@ class ChannelBuildersFlowTest : TestBase() { assertFailsWith { flow.collect() } } + @Test + fun testReceiveAsFlowException() = runTest { + val channel = produce(NonCancellable) { // otherwise failure will cancel scope as well + repeat(10) { + send(it + 1) + } + throw TestException() + } + val flow = channel.receiveAsFlow() + assertFailsWith { flow.sum() } + assertFailsWith { flow.collect() } // repeated collection -- same exception + } + @Test fun testConsumeAsFlowProduceFusing() = runTest { val channel = produce { send("OK") } @@ -58,6 +97,15 @@ class ChannelBuildersFlowTest : TestBase() { channel.cancel() } + @Test + fun testReceiveAsFlowProduceFusing() = runTest { + val channel = produce { send("OK") } + val flow = channel.receiveAsFlow() + assertSame(channel, flow.produceIn(this)) + assertSame(channel, flow.produceIn(this)) // can use produce multiple times + channel.cancel() + } + @Test fun testConsumeAsFlowProduceBuffered() = runTest { expect(1) From 3d59fef9572b7116139ef8555481438db55842b1 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Tue, 21 Jan 2020 14:58:47 +0300 Subject: [PATCH 15/50] Fix context support in Publisher.asFlow.flowOn * When using asFlow().flowOn(...) context is now properly tracked and taken into account for both execution context of the reactive subscription and for injection into Reactor context. * Publisher.asFlow slow-path implementation is simplified. It does not sure specialized openSubscription anymore, but always uses the same flow request logic. Fixes #1765 --- .../src/ReactiveFlow.kt | 55 +++++++++---------- .../test/PublisherAsFlowTest.kt | 4 +- .../test/FlowAsFluxTest.kt | 52 ++++++++++++++++-- .../test/FluxContextTest.kt | 43 +++++++++++++++ .../test/FlowableContextTest.kt | 43 +++++++++++++++ 5 files changed, 163 insertions(+), 34 deletions(-) create mode 100644 reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt create mode 100644 reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt diff --git a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt index b3b764a43c..5accbf243c 100644 --- a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt +++ b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactive @@ -27,7 +27,7 @@ import kotlin.coroutines.* * see its documentation for additional details. */ public fun Publisher.asFlow(): Flow = - PublisherAsFlow(this, 1) + PublisherAsFlow(this) /** * Transforms the given flow to a reactive specification compliant [Publisher]. @@ -39,30 +39,11 @@ public fun Flow.asPublisher(): Publisher = FlowAsPublisher(this) private class PublisherAsFlow( private val publisher: Publisher, - capacity: Int -) : ChannelFlow(EmptyCoroutineContext, capacity) { + context: CoroutineContext = EmptyCoroutineContext, + capacity: Int = 1 +) : ChannelFlow(context, capacity) { override fun create(context: CoroutineContext, capacity: Int): ChannelFlow = - PublisherAsFlow(publisher, capacity) - - override fun produceImpl(scope: CoroutineScope): ReceiveChannel { - // use another channel for conflation (cannot do openSubscription) - if (capacity < 0) return super.produceImpl(scope) - // Open subscription channel directly - val channel = publisher - .injectCoroutineContext(scope.coroutineContext) - .openSubscription(capacity) - val handle = scope.coroutineContext[Job]?.invokeOnCompletion(onCancelling = true) { cause -> - channel.cancel(cause?.let { - it as? CancellationException ?: CancellationException("Job was cancelled", it) - }) - } - if (handle != null && handle !== NonDisposableHandle) { - (channel as SendChannel<*>).invokeOnClose { - handle.dispose() - } - } - return channel - } + PublisherAsFlow(publisher, context, capacity) private val requestSize: Long get() = when (capacity) { @@ -73,8 +54,26 @@ private class PublisherAsFlow( } override suspend fun collect(collector: FlowCollector) { + val collectContext = coroutineContext + val newDispatcher = context[ContinuationInterceptor] + if (newDispatcher == null || newDispatcher == collectContext[ContinuationInterceptor]) { + // fast path -- subscribe directly in this dispatcher + return collectImpl(collectContext + context, collector) + } + // slow path -- produce in a separate dispatcher + collectSlowPath(collector) + } + + private suspend fun collectSlowPath(collector: FlowCollector) { + coroutineScope { + collector.emitAll(produceImpl(this + context)) + } + } + + private suspend fun collectImpl(injectContext: CoroutineContext, collector: FlowCollector) { val subscriber = ReactiveSubscriber(capacity, requestSize) - publisher.injectCoroutineContext(coroutineContext).subscribe(subscriber) + // inject subscribe context into publisher + publisher.injectCoroutineContext(injectContext).subscribe(subscriber) try { var consumed = 0L while (true) { @@ -90,9 +89,9 @@ private class PublisherAsFlow( } } - // The second channel here is used only for broadcast + // The second channel here is used for produceIn/broadcastIn and slow-path (dispatcher change) override suspend fun collectTo(scope: ProducerScope) = - collect(SendingCollector(scope.channel)) + collectImpl(scope.coroutineContext, SendingCollector(scope.channel)) } @Suppress("SubscriberImplementation") diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt index a37719de64..e458c918a5 100644 --- a/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt @@ -120,7 +120,7 @@ class PublisherAsFlowTest : TestBase() { 7 -> try { send(value) } catch (e: CancellationException) { - finish(6) + expect(5) throw e } else -> expectUnreached() @@ -143,6 +143,6 @@ class PublisherAsFlowTest : TestBase() { } } } - expect(5) + finish(6) } } \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt b/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt index ccef000b5b..e4bd8b315b 100644 --- a/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/FlowAsFluxTest.kt @@ -4,16 +4,17 @@ import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.reactive.* import org.junit.Test -import reactor.core.publisher.Mono +import reactor.core.publisher.* import reactor.util.context.Context -import kotlin.test.assertEquals +import kotlin.test.* class FlowAsFluxTest : TestBase() { @Test - fun testFlowToFluxContextPropagation() { + fun testFlowAsFluxContextPropagation() { val flux = flow { (1..4).forEach { i -> emit(createMono(i).awaitFirst()) } - } .asFlux() + } + .asFlux() .subscriberContext(Context.of(1, "1")) .subscriberContext(Context.of(2, "2", 3, "3", 4, "4")) val list = flux.collectList().block()!! @@ -24,4 +25,47 @@ class FlowAsFluxTest : TestBase() { val ctx = coroutineContext[ReactorContext]!!.context ctx.getOrDefault(i, "noValue") } + + @Test + fun testFluxAsFlowContextPropagationWithFlowOn() = runTest { + expect(1) + Flux.create { + it.next("OK") + it.complete() + } + .subscriberContext { ctx -> + expect(2) + assertEquals("CTX", ctx.get(1)) + ctx + } + .asFlow() + .flowOn(ReactorContext(Context.of(1, "CTX"))) + .collect { + expect(3) + assertEquals("OK", it) + } + finish(4) + } + + @Test + fun testFluxAsFlowContextPropagationFromScope() = runTest { + expect(1) + withContext(ReactorContext(Context.of(1, "CTX"))) { + Flux.create { + it.next("OK") + it.complete() + } + .subscriberContext { ctx -> + expect(2) + assertEquals("CTX", ctx.get(1)) + ctx + } + .asFlow() + .collect { + expect(3) + assertEquals("OK", it) + } + } + finish(4) + } } \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt new file mode 100644 index 0000000000..1ed3a164f6 --- /dev/null +++ b/reactive/kotlinx-coroutines-reactor/test/FluxContextTest.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.reactor + +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.reactive.* +import org.junit.* +import org.junit.Test +import reactor.core.publisher.* +import kotlin.test.* + +class FluxContextTest : TestBase() { + private val dispatcher = newSingleThreadContext("FluxContextTest") + + @After + fun tearDown() { + dispatcher.close() + } + + @Test + fun testFluxCreateAsFlowThread() = runTest { + expect(1) + val mainThread = Thread.currentThread() + val dispatcherThread = withContext(dispatcher) { Thread.currentThread() } + assertTrue(dispatcherThread != mainThread) + Flux.create { + assertEquals(dispatcherThread, Thread.currentThread()) + it.next("OK") + it.complete() + } + .asFlow() + .flowOn(dispatcher) + .collect { + expect(2) + assertEquals("OK", it) + assertEquals(mainThread, Thread.currentThread()) + } + finish(3) + } +} \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt new file mode 100644 index 0000000000..2cc3243551 --- /dev/null +++ b/reactive/kotlinx-coroutines-rx2/test/FlowableContextTest.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.rx2 + +import io.reactivex.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.reactive.* +import org.junit.* +import org.junit.Test +import kotlin.test.* + +class FlowableContextTest : TestBase() { + private val dispatcher = newSingleThreadContext("FlowableContextTest") + + @After + fun tearDown() { + dispatcher.close() + } + + @Test + fun testFlowableCreateAsFlowThread() = runTest { + expect(1) + val mainThread = Thread.currentThread() + val dispatcherThread = withContext(dispatcher) { Thread.currentThread() } + assertTrue(dispatcherThread != mainThread) + Flowable.create({ + assertEquals(dispatcherThread, Thread.currentThread()) + it.onNext("OK") + it.onComplete() + }, BackpressureStrategy.BUFFER) + .asFlow() + .flowOn(dispatcher) + .collect { + expect(2) + assertEquals("OK", it) + assertEquals(mainThread, Thread.currentThread()) + } + finish(3) + } +} \ No newline at end of file From 642989ee9d7712e4cf171a545534a189efd7b481 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 24 Jan 2020 20:00:46 +0300 Subject: [PATCH 16/50] Disable companions test in binary-compatibility-validation in train builds (KT-11567) --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 01345b6f95..febcc3d31c 100644 --- a/build.gradle +++ b/build.gradle @@ -176,8 +176,11 @@ if (build_snapshot_train) { exclude '**/*LFTest*' exclude '**/*StressTest*' exclude '**/*scheduling*' + exclude '**/*scheduling*' exclude '**/*Timeout*' exclude '**/*definitely/not/kotlinx*' + // Disable because of KT-11567 in 1.4 + exclude '**/*CasesPublicAPITest.companions*' } } From 6810745ceaa1b5ee549c7d825777e8e6515174b2 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 27 Jan 2020 16:34:56 +0300 Subject: [PATCH 17/50] Request elements in batches in ReactiveFlow to avoid requesting elements one by one in a default configuration Also, partially masks #1766 --- .../src/ReactiveFlow.kt | 13 ++++-- .../test/PublisherAsFlowTest.kt | 40 ++++++++++++++++++- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt index 5accbf243c..3a81c0696d 100644 --- a/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt +++ b/reactive/kotlinx-coroutines-reactive/src/ReactiveFlow.kt @@ -18,9 +18,9 @@ import kotlin.coroutines.* * Transforms the given reactive [Publisher] into [Flow]. * Use [buffer] operator on the resulting flow to specify the size of the backpressure. * More precisely, it specifies the value of the subscription's [request][Subscription.request]. - * `1` is used by default. + * [buffer] default capacity is used by default. * - * If any of the resulting flow transformations fails, subscription is immediately cancelled and all in-flights elements + * If any of the resulting flow transformations fails, subscription is immediately cancelled and all in-flight elements * are discarded. * * This function is integrated with `ReactorContext` from `kotlinx-coroutines-reactor` module, @@ -40,16 +40,23 @@ public fun Flow.asPublisher(): Publisher = FlowAsPublisher(this) private class PublisherAsFlow( private val publisher: Publisher, context: CoroutineContext = EmptyCoroutineContext, - capacity: Int = 1 + capacity: Int = Channel.BUFFERED ) : ChannelFlow(context, capacity) { override fun create(context: CoroutineContext, capacity: Int): ChannelFlow = PublisherAsFlow(publisher, context, capacity) + /* + * Suppress for Channel.CHANNEL_DEFAULT_CAPACITY. + * It's too counter-intuitive to be public and moving it to Flow companion + * will also create undesired effect. + */ + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") private val requestSize: Long get() = when (capacity) { Channel.CONFLATED -> Long.MAX_VALUE // request all and conflate incoming Channel.RENDEZVOUS -> 1L // need to request at least one anyway Channel.UNLIMITED -> Long.MAX_VALUE // reactive streams way to say "give all" must be Long.MAX_VALUE + Channel.BUFFERED -> Channel.CHANNEL_DEFAULT_CAPACITY.toLong() else -> capacity.toLong().also { check(it >= 1) } } diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt index e458c918a5..61f88f6af3 100644 --- a/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/PublisherAsFlowTest.kt @@ -56,7 +56,43 @@ class PublisherAsFlowTest : TestBase() { expect(6) } + publisher.asFlow().buffer(1).collect { + expect(it) + } + + finish(8) + } + + @Test + fun testBufferSizeDefault() = runTest { + val publisher = publish(currentDispatcher()) { + repeat(64) { + send(it + 1) + expect(it + 1) + } + assertFalse { offer(-1) } + } + publisher.asFlow().collect { + expect(64 + it) + } + + finish(129) + } + + @Test + fun testDefaultCapacityIsProperlyOverwritten() = runTest { + val publisher = publish(currentDispatcher()) { + expect(1) + send(3) + expect(2) + send(5) + expect(4) + send(7) + expect(6) + } + + publisher.asFlow().flowOn(wrapperDispatcher()).buffer(1).collect { expect(it) } @@ -126,7 +162,7 @@ class PublisherAsFlowTest : TestBase() { else -> expectUnreached() } } - }.asFlow() + }.asFlow().buffer(1) assertFailsWith { coroutineScope { expect(2) @@ -145,4 +181,4 @@ class PublisherAsFlowTest : TestBase() { } finish(6) } -} \ No newline at end of file +} From fb990b03df1fa04b4723199b448d23d2d6f028fa Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 4 Feb 2020 17:11:47 +0300 Subject: [PATCH 18/50] Disable CasesPublicAPITest completely for train builds --- build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index febcc3d31c..94db6c08c8 100644 --- a/build.gradle +++ b/build.gradle @@ -176,11 +176,10 @@ if (build_snapshot_train) { exclude '**/*LFTest*' exclude '**/*StressTest*' exclude '**/*scheduling*' - exclude '**/*scheduling*' exclude '**/*Timeout*' exclude '**/*definitely/not/kotlinx*' // Disable because of KT-11567 in 1.4 - exclude '**/*CasesPublicAPITest.companions*' + exclude '**/*CasesPublicAPITest*' } } From cf5da1a2a019bae39de4432a6d34757357224d3a Mon Sep 17 00:00:00 2001 From: Eric O'Connell Date: Tue, 4 Feb 2020 12:23:13 -0800 Subject: [PATCH 19/50] Remove extraneous word in comment --- kotlinx-coroutines-core/common/src/selects/Select.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt index 1725d12f4a..98ead14dee 100644 --- a/kotlinx-coroutines-core/common/src/selects/Select.kt +++ b/kotlinx-coroutines-core/common/src/selects/Select.kt @@ -35,7 +35,7 @@ public interface SelectBuilder { public operator fun SelectClause2.invoke(param: P, block: suspend (Q) -> R) /** - * Registers clause in this [select] expression with additional parameter nullable parameter of type [P] + * Registers clause in this [select] expression with additional nullable parameter of type [P] * with the `null` value for this parameter that selects value of type [Q]. */ public operator fun SelectClause2.invoke(block: suspend (Q) -> R) = invoke(null, block) From 09cb4bfe21602479d55e5734e9d7f77c05b11b8d Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Tue, 4 Feb 2020 18:25:47 +0300 Subject: [PATCH 20/50] Fix tests hanging when `verifyDump` fails `runBlocking` waits for all the threads it spawned to finish, so if `verifyDump` failed in `RunningThreadStackMergeTest.kt`, the tests would just hang: one of the threads would wait for a barrier to break, which would never happen. --- .../test/RunningThreadStackMergeTest.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt index 193bcce135..3f3c69cdb2 100644 --- a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt +++ b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt @@ -33,8 +33,9 @@ class RunningThreadStackMergeTest : DebugTestBase() { "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", ignoredCoroutine = ":BlockingCoroutine" - ) - coroutineBlocker.await() + ) { + coroutineBlocker.await() + } } private fun awaitCoroutineStarted() { @@ -87,8 +88,9 @@ class RunningThreadStackMergeTest : DebugTestBase() { "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", ignoredCoroutine = ":BlockingCoroutine" - ) - coroutineBlocker.await() + ) { + coroutineBlocker.await() + } } private fun CoroutineScope.launchEscapingCoroutine() { @@ -125,8 +127,9 @@ class RunningThreadStackMergeTest : DebugTestBase() { "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", ignoredCoroutine = ":BlockingCoroutine" - ) - coroutineBlocker.await() + ) { + coroutineBlocker.await() + } } private fun CoroutineScope.launchEscapingCoroutineWithoutContext() { From e153863c8beb4448df527a3006b3ef00f2d5e93f Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 10 Feb 2020 21:12:58 +0300 Subject: [PATCH 21/50] Integration with binary-compatibility-validator plugin (#1790) --- binary-compatibility-validator/README.md | 10 - binary-compatibility-validator/build.gradle | 58 ------ .../resources/api.properties | 9 - .../src/PublicApiDump.kt | 120 ------------ .../src/asmUtils.kt | 173 ------------------ .../src/kotlinVisibilities.kt | 57 ------ .../test/CasesPublicAPITest.kt | 98 ---------- .../test/PublicApiTest.kt | 96 ---------- .../test/cases/companions/companions.kt | 106 ----------- .../test/cases/companions/companions.txt | 66 ------- .../test/cases/inline/inline.txt | 9 - .../test/cases/inline/inlineExposed.kt | 28 --- .../test/cases/inline/inlineOnly.kt | 9 - .../interfaces/interfaceWithEmptyImpls.kt | 10 - .../cases/interfaces/interfaceWithImpls.kt | 18 -- .../test/cases/interfaces/interfaces.txt | 27 --- .../test/cases/internal/internal.txt | 3 - .../test/cases/internal/internalClass.kt | 11 -- .../test/cases/internal/internalMultifile1.kt | 9 - .../test/cases/internal/internalMultifile2.kt | 9 - .../test/cases/internal/internalPart.kt | 11 -- .../internal/publicClassInternalMember.kt | 13 -- .../test/cases/java/Facade.java | 16 -- .../test/cases/java/java.txt | 6 - .../test/cases/localClasses/fromStdlib.kt | 7 - .../test/cases/localClasses/lambdas.kt | 24 --- .../test/cases/localClasses/localClasses.kt | 27 --- .../test/cases/localClasses/localClasses.txt | 18 -- .../test/cases/nestedClasses/internalClass.kt | 28 --- .../cases/nestedClasses/internalInterface.kt | 18 -- .../cases/nestedClasses/internalObject.kt | 21 --- .../cases/nestedClasses/nestedClasses.txt | 86 --------- .../test/cases/nestedClasses/privateClass.kt | 28 --- .../cases/nestedClasses/privateInterface.kt | 18 -- .../test/cases/nestedClasses/privateObject.kt | 21 --- .../nestedClasses/publicAbstractClass.kt | 16 -- .../test/cases/nestedClasses/publicClass.kt | 28 --- .../cases/nestedClasses/publicInterface.kt | 18 -- .../test/cases/nestedClasses/publicObject.kt | 21 --- .../cases/nestedClasses/publicOpenClass.kt | 16 -- .../test/cases/private/private.txt | 0 .../test/cases/private/privateClassMembers.kt | 11 -- .../test/cases/private/privateMultifile1.kt | 12 -- .../test/cases/private/privateMultifile2.kt | 23 --- .../test/cases/private/privatePart.kt | 28 --- .../test/cases/protected/protected.txt | 19 -- .../cases/protected/protectedInAbstract.kt | 12 -- .../test/cases/protected/protectedInFinal.kt | 12 -- .../test/cases/protected/protectedInOpen.kt | 12 -- .../test/cases/public/public.txt | 9 - .../test/cases/public/publicMultifile1.kt | 9 - .../test/cases/public/publicMultifile2.kt | 9 - .../test/cases/public/publicPart.kt | 9 - .../test/cases/special/hidden.kt | 29 --- .../cases/special/internalLateinitMember.kt | 14 -- .../test/cases/special/jvmField.kt | 55 ------ .../test/cases/special/jvmNames.kt | 26 --- .../test/cases/special/jvmOverloads.kt | 23 --- .../test/cases/special/special.txt | 61 ------ .../test/cases/whenMappings/enumWhen.kt | 24 --- .../cases/whenMappings/sealedClassWhen.kt | 24 --- .../test/cases/whenMappings/whenMappings.txt | 33 ---- binary-compatibility-validator/test/utils.kt | 48 ----- build.gradle | 11 +- gradle.properties | 3 +- .../api/kotlinx-coroutines-guava.api | 0 .../api/kotlinx-coroutines-jdk8.api | 0 .../api/kotlinx-coroutines-play-services.api | 0 .../api/kotlinx-coroutines-slf4j.api | 0 .../api/kotlinx-coroutines-core.api | 0 .../api/kotlinx-coroutines-debug.api | 0 .../api/kotlinx-coroutines-test.api | 0 .../api/kotlinx-coroutines-reactive.api | 0 .../api/kotlinx-coroutines-reactor.api | 0 .../api/kotlinx-coroutines-rx2.api | 0 settings.gradle | 2 - .../api/kotlinx-coroutines-android.api | 0 .../api/kotlinx-coroutines-javafx.api | 0 .../api/kotlinx-coroutines-swing.api | 0 79 files changed, 12 insertions(+), 1873 deletions(-) delete mode 100644 binary-compatibility-validator/README.md delete mode 100644 binary-compatibility-validator/build.gradle delete mode 100644 binary-compatibility-validator/resources/api.properties delete mode 100644 binary-compatibility-validator/src/PublicApiDump.kt delete mode 100644 binary-compatibility-validator/src/asmUtils.kt delete mode 100644 binary-compatibility-validator/src/kotlinVisibilities.kt delete mode 100644 binary-compatibility-validator/test/CasesPublicAPITest.kt delete mode 100644 binary-compatibility-validator/test/PublicApiTest.kt delete mode 100644 binary-compatibility-validator/test/cases/companions/companions.kt delete mode 100644 binary-compatibility-validator/test/cases/companions/companions.txt delete mode 100644 binary-compatibility-validator/test/cases/inline/inline.txt delete mode 100644 binary-compatibility-validator/test/cases/inline/inlineExposed.kt delete mode 100644 binary-compatibility-validator/test/cases/inline/inlineOnly.kt delete mode 100644 binary-compatibility-validator/test/cases/interfaces/interfaceWithEmptyImpls.kt delete mode 100644 binary-compatibility-validator/test/cases/interfaces/interfaceWithImpls.kt delete mode 100644 binary-compatibility-validator/test/cases/interfaces/interfaces.txt delete mode 100644 binary-compatibility-validator/test/cases/internal/internal.txt delete mode 100644 binary-compatibility-validator/test/cases/internal/internalClass.kt delete mode 100644 binary-compatibility-validator/test/cases/internal/internalMultifile1.kt delete mode 100644 binary-compatibility-validator/test/cases/internal/internalMultifile2.kt delete mode 100644 binary-compatibility-validator/test/cases/internal/internalPart.kt delete mode 100644 binary-compatibility-validator/test/cases/internal/publicClassInternalMember.kt delete mode 100644 binary-compatibility-validator/test/cases/java/Facade.java delete mode 100644 binary-compatibility-validator/test/cases/java/java.txt delete mode 100644 binary-compatibility-validator/test/cases/localClasses/fromStdlib.kt delete mode 100644 binary-compatibility-validator/test/cases/localClasses/lambdas.kt delete mode 100644 binary-compatibility-validator/test/cases/localClasses/localClasses.kt delete mode 100644 binary-compatibility-validator/test/cases/localClasses/localClasses.txt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/internalClass.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/internalInterface.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/internalObject.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/nestedClasses.txt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/privateClass.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/privateInterface.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/privateObject.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/publicAbstractClass.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/publicClass.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/publicInterface.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/publicObject.kt delete mode 100644 binary-compatibility-validator/test/cases/nestedClasses/publicOpenClass.kt delete mode 100644 binary-compatibility-validator/test/cases/private/private.txt delete mode 100644 binary-compatibility-validator/test/cases/private/privateClassMembers.kt delete mode 100644 binary-compatibility-validator/test/cases/private/privateMultifile1.kt delete mode 100644 binary-compatibility-validator/test/cases/private/privateMultifile2.kt delete mode 100644 binary-compatibility-validator/test/cases/private/privatePart.kt delete mode 100644 binary-compatibility-validator/test/cases/protected/protected.txt delete mode 100644 binary-compatibility-validator/test/cases/protected/protectedInAbstract.kt delete mode 100644 binary-compatibility-validator/test/cases/protected/protectedInFinal.kt delete mode 100644 binary-compatibility-validator/test/cases/protected/protectedInOpen.kt delete mode 100644 binary-compatibility-validator/test/cases/public/public.txt delete mode 100644 binary-compatibility-validator/test/cases/public/publicMultifile1.kt delete mode 100644 binary-compatibility-validator/test/cases/public/publicMultifile2.kt delete mode 100644 binary-compatibility-validator/test/cases/public/publicPart.kt delete mode 100644 binary-compatibility-validator/test/cases/special/hidden.kt delete mode 100644 binary-compatibility-validator/test/cases/special/internalLateinitMember.kt delete mode 100644 binary-compatibility-validator/test/cases/special/jvmField.kt delete mode 100644 binary-compatibility-validator/test/cases/special/jvmNames.kt delete mode 100644 binary-compatibility-validator/test/cases/special/jvmOverloads.kt delete mode 100644 binary-compatibility-validator/test/cases/special/special.txt delete mode 100644 binary-compatibility-validator/test/cases/whenMappings/enumWhen.kt delete mode 100644 binary-compatibility-validator/test/cases/whenMappings/sealedClassWhen.kt delete mode 100644 binary-compatibility-validator/test/cases/whenMappings/whenMappings.txt delete mode 100644 binary-compatibility-validator/test/utils.kt rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt => integration/kotlinx-coroutines-guava/api/kotlinx-coroutines-guava.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt => integration/kotlinx-coroutines-jdk8/api/kotlinx-coroutines-jdk8.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-play-services.txt => integration/kotlinx-coroutines-play-services/api/kotlinx-coroutines-play-services.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-slf4j.txt => integration/kotlinx-coroutines-slf4j/api/kotlinx-coroutines-slf4j.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt => kotlinx-coroutines-core/api/kotlinx-coroutines-core.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt => kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-test.txt => kotlinx-coroutines-test/api/kotlinx-coroutines-test.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactive.txt => reactive/kotlinx-coroutines-reactive/api/kotlinx-coroutines-reactive.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt => reactive/kotlinx-coroutines-reactor/api/kotlinx-coroutines-reactor.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt => reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt => ui/kotlinx-coroutines-android/api/kotlinx-coroutines-android.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt => ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api (100%) rename binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt => ui/kotlinx-coroutines-swing/api/kotlinx-coroutines-swing.api (100%) diff --git a/binary-compatibility-validator/README.md b/binary-compatibility-validator/README.md deleted file mode 100644 index e34d6877c5..0000000000 --- a/binary-compatibility-validator/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Public API binary compatibility validator - -This module allows to dump and compare public binary API to ensure binary compatibility with a previous version. -This tool is slightly adapted copy of [original Kotlin compatibility validator](https://github.com/JetBrains/kotlin/tree/master/libraries/tools/binary-compatibility-validator) by @ilya-g. - -To update public API dumps use: - -```bash -./gradlew :binary-compatibility-validator:test -Poverwrite.output=true -``` diff --git a/binary-compatibility-validator/build.gradle b/binary-compatibility-validator/build.gradle deleted file mode 100644 index c6eaffdfca..0000000000 --- a/binary-compatibility-validator/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -configurations { - testArtifacts - configureKotlinJvmPlatform(testArtifacts) -} - -dependencies { - compile 'org.ow2.asm:asm-debug-all:5.0.4' - compile 'com.google.code.gson:gson:2.6.2' - - testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" - - testArtifacts project(':kotlinx-coroutines-core') - testArtifacts project(':kotlinx-coroutines-test') - testArtifacts project(':kotlinx-coroutines-debug') - - testArtifacts project(':kotlinx-coroutines-reactive') - testArtifacts project(':kotlinx-coroutines-reactor') - testArtifacts project(':kotlinx-coroutines-rx2') - - testArtifacts project(':kotlinx-coroutines-guava') - testArtifacts project(':kotlinx-coroutines-jdk8') - testArtifacts project(':kotlinx-coroutines-slf4j') - testArtifacts project(path: ':kotlinx-coroutines-play-services', configuration: 'default') - - testArtifacts project(':kotlinx-coroutines-android') - testArtifacts project(':kotlinx-coroutines-javafx') - testArtifacts project(':kotlinx-coroutines-swing') -} - -def testCasesDeclarationsDump = "${buildDir}/visibilities.json".toString() - -compileTestKotlin { - kotlinOptions { - freeCompilerArgs = ["-Xdump-declarations-to=$testCasesDeclarationsDump"] - } -} - -sourceSets { - test { - java { - srcDir "test/cases" - } - } -} - -test { - dependsOn cleanCompileTestKotlin - dependsOn configurations.testArtifacts - - systemProperty 'testCasesClassesDirs', sourceSets.test.output.classesDirs.asPath - systemProperty 'testCasesDeclarations', testCasesDeclarationsDump - systemProperty 'overwrite.output', project.properties['overwrite.output'] - jvmArgs '-ea' -} diff --git a/binary-compatibility-validator/resources/api.properties b/binary-compatibility-validator/resources/api.properties deleted file mode 100644 index e15ad21a02..0000000000 --- a/binary-compatibility-validator/resources/api.properties +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -module.roots=/ integration reactive ui -module.marker=build.gradle -module.ignore=stdlib-stubs benchmarks knit binary-compatibility-validator site publication-validator kotlinx-coroutines-bom - -packages.internal=kotlinx.coroutines.internal \ No newline at end of file diff --git a/binary-compatibility-validator/src/PublicApiDump.kt b/binary-compatibility-validator/src/PublicApiDump.kt deleted file mode 100644 index 343df34b87..0000000000 --- a/binary-compatibility-validator/src/PublicApiDump.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines.tools - -import org.objectweb.asm.* -import org.objectweb.asm.tree.* -import java.io.* -import java.util.jar.* - -fun JarFile.classEntries() = entries().asSequence().filter { - !it.isDirectory && it.name.endsWith(".class") && !it.name.startsWith("META-INF/") -} - -fun getBinaryAPI(jar: JarFile, visibilityMap: Map): List = - getBinaryAPI(jar.classEntries().map { entry -> jar.getInputStream(entry) }, visibilityMap) - -fun getBinaryAPI( - classStreams: Sequence, - visibilityMap: Map -): List = - classStreams.map { - it.use { stream -> - val classNode = ClassNode() - ClassReader(stream).accept(classNode, ClassReader.SKIP_CODE) - classNode - } - }.map { - with(it) { - val classVisibility = visibilityMap[name] - val classAccess = AccessFlags(effectiveAccess and Opcodes.ACC_STATIC.inv()) - val supertypes = listOf(superName) - "java/lang/Object" + interfaces.sorted() - - val memberSignatures = ( - fields.map { - with(it) { - FieldBinarySignature( - name, - desc, - isPublishedApi(), - AccessFlags(access) - ) - } - } + - methods.map { - with(it) { - MethodBinarySignature( - name, - desc, - isPublishedApi(), - AccessFlags(access) - ) - } - } - ).filter { - it.isEffectivelyPublic(classAccess, classVisibility) - } - - ClassBinarySignature( - name, - superName, - outerClassName, - supertypes, - memberSignatures, - classAccess, - isEffectivelyPublic(classVisibility), - isFileOrMultipartFacade() || isDefaultImpls() - ) - } - }.asIterable().sortedBy { it.name } - - -fun List.filterOutNonPublic(nonPublicPackages: List = emptyList()): List { - val nonPublicPaths = nonPublicPackages.map { it.replace('.', '/') + '/' } - val classByName = associateBy { it.name } - - fun ClassBinarySignature.isInNonPublicPackage() = - nonPublicPaths.any { name.startsWith(it) } - - fun ClassBinarySignature.isPublicAndAccessible(): Boolean = - isEffectivelyPublic && - (outerName == null || classByName[outerName]?.let { outerClass -> - !(this.access.isProtected && outerClass.access.isFinal) - && outerClass.isPublicAndAccessible() - } ?: true) - - fun supertypes(superName: String) = generateSequence({ classByName[superName] }, { classByName[it.superName] }) - - fun ClassBinarySignature.flattenNonPublicBases(): ClassBinarySignature { - - val nonPublicSupertypes = supertypes(superName).takeWhile { !it.isPublicAndAccessible() }.toList() - if (nonPublicSupertypes.isEmpty()) - return this - - val inheritedStaticSignatures = - nonPublicSupertypes.flatMap { it.memberSignatures.filter { it.access.isStatic } } - - // not covered the case when there is public superclass after chain of private superclasses - return this.copy( - memberSignatures = memberSignatures + inheritedStaticSignatures, - supertypes = supertypes - superName - ) - } - - return filter { !it.isInNonPublicPackage() && it.isPublicAndAccessible() } - .map { it.flattenNonPublicBases() } - .filterNot { it.isNotUsedWhenEmpty && it.memberSignatures.isEmpty() } -} - -fun List.dump() = dump(to = System.out) - -fun List.dump(to: T): T = to.apply { - this@dump.forEach { - append(it.signature).appendln(" {") - it.memberSignatures.sortedWith(MEMBER_SORT_ORDER).forEach { append("\t").appendln(it.signature) } - appendln("}\n") - } -} - diff --git a/binary-compatibility-validator/src/asmUtils.kt b/binary-compatibility-validator/src/asmUtils.kt deleted file mode 100644 index b14cb8d5e6..0000000000 --- a/binary-compatibility-validator/src/asmUtils.kt +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines.tools - -import org.objectweb.asm.* -import org.objectweb.asm.tree.* - -val ACCESS_NAMES = mapOf( - Opcodes.ACC_PUBLIC to "public", - Opcodes.ACC_PROTECTED to "protected", - Opcodes.ACC_PRIVATE to "private", - Opcodes.ACC_STATIC to "static", - Opcodes.ACC_FINAL to "final", - Opcodes.ACC_ABSTRACT to "abstract", - Opcodes.ACC_SYNTHETIC to "synthetic", - Opcodes.ACC_INTERFACE to "interface", - Opcodes.ACC_ANNOTATION to "annotation") - -data class ClassBinarySignature( - val name: String, - val superName: String, - val outerName: String?, - val supertypes: List, - val memberSignatures: List, - val access: AccessFlags, - val isEffectivelyPublic: Boolean, - val isNotUsedWhenEmpty: Boolean) { - - val signature: String - get() = "${access.getModifierString()} class $name" + if (supertypes.isEmpty()) "" else " : ${supertypes.joinToString()}" - -} - - -interface MemberBinarySignature { - val name: String - val desc: String - val access: AccessFlags - val isPublishedApi: Boolean - - fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?) - = access.isPublic && !(access.isProtected && classAccess.isFinal) - && (findMemberVisibility(classVisibility)?.isPublic(isPublishedApi) ?: true) - - fun findMemberVisibility(classVisibility: ClassVisibility?) - = classVisibility?.members?.get(MemberSignature(name, desc)) - - val signature: String -} - -data class MethodBinarySignature( - override val name: String, - override val desc: String, - override val isPublishedApi: Boolean, - override val access: AccessFlags) : MemberBinarySignature { - override val signature: String - get() = "${access.getModifierString()} fun $name $desc" - - override fun isEffectivelyPublic(classAccess: AccessFlags, classVisibility: ClassVisibility?) - = super.isEffectivelyPublic(classAccess, classVisibility) - && !isAccessOrAnnotationsMethod() - - private fun isAccessOrAnnotationsMethod() = access.isSynthetic && (name.startsWith("access\$") || name.endsWith("\$annotations")) -} - -data class FieldBinarySignature( - override val name: String, - override val desc: String, - override val isPublishedApi: Boolean, - override val access: AccessFlags) : MemberBinarySignature { - override val signature: String - get() = "${access.getModifierString()} field $name $desc" - - override fun findMemberVisibility(classVisibility: ClassVisibility?): MemberVisibility? { - val fieldVisibility = super.findMemberVisibility(classVisibility) ?: return null - - // good case for 'satisfying': fieldVisibility.satisfying { it.isLateInit() }?.let { classVisibility?.findSetterForProperty(it) } - if (fieldVisibility.isLateInit()) { - classVisibility?.findSetterForProperty(fieldVisibility)?.let { return it } - } - return fieldVisibility - } -} - -val MemberBinarySignature.kind: Int get() = when (this) { - is FieldBinarySignature -> 1 - is MethodBinarySignature -> 2 - else -> error("Unsupported $this") -} - -val MEMBER_SORT_ORDER = compareBy( - { it.kind }, - { it.name }, - { it.desc } -) - - -data class AccessFlags(val access: Int) { - val isPublic: Boolean get() = isPublic(access) - val isProtected: Boolean get() = isProtected(access) - val isStatic: Boolean get() = isStatic(access) - val isFinal: Boolean get() = isFinal(access) - val isSynthetic: Boolean get() = isSynthetic(access) - - fun getModifiers(): List = ACCESS_NAMES.entries.mapNotNull { if (access and it.key != 0) it.value else null } - fun getModifierString(): String = getModifiers().joinToString(" ") -} - -fun isPublic(access: Int) = access and Opcodes.ACC_PUBLIC != 0 || access and Opcodes.ACC_PROTECTED != 0 -fun isProtected(access: Int) = access and Opcodes.ACC_PROTECTED != 0 -fun isStatic(access: Int) = access and Opcodes.ACC_STATIC != 0 -fun isFinal(access: Int) = access and Opcodes.ACC_FINAL != 0 -fun isSynthetic(access: Int) = access and Opcodes.ACC_SYNTHETIC != 0 - - -fun ClassNode.isEffectivelyPublic(classVisibility: ClassVisibility?) = - isPublic(access) - && !isLocal() - && !isWhenMappings() - && (classVisibility?.isPublic(isPublishedApi()) ?: true) - - -val ClassNode.innerClassNode: InnerClassNode? get() = innerClasses.singleOrNull { it.name == name } -fun ClassNode.isLocal() = innerClassNode?.run { innerName == null && outerName == null} ?: false -fun ClassNode.isInner() = innerClassNode != null -fun ClassNode.isWhenMappings() = isSynthetic(access) && name.endsWith("\$WhenMappings") - -val ClassNode.effectiveAccess: Int get() = innerClassNode?.access ?: access -val ClassNode.outerClassName: String? get() = innerClassNode?.outerName - - -const val publishedApiAnnotationName = "kotlin/PublishedApi" -fun ClassNode.isPublishedApi() = findAnnotation(publishedApiAnnotationName, includeInvisible = true) != null -fun MethodNode.isPublishedApi() = findAnnotation(publishedApiAnnotationName, includeInvisible = true) != null -fun FieldNode.isPublishedApi() = findAnnotation(publishedApiAnnotationName, includeInvisible = true) != null - - -private object KotlinClassKind { - const val FILE = 2 - const val SYNTHETIC_CLASS = 3 - const val MULTIPART_FACADE = 4 - - val FILE_OR_MULTIPART_FACADE_KINDS = listOf(FILE, MULTIPART_FACADE) -} - -fun ClassNode.isFileOrMultipartFacade() = kotlinClassKind.let { it != null && it in KotlinClassKind.FILE_OR_MULTIPART_FACADE_KINDS } -fun ClassNode.isDefaultImpls() = isInner() && name.endsWith("\$DefaultImpls") && kotlinClassKind == KotlinClassKind.SYNTHETIC_CLASS - - -val ClassNode.kotlinClassKind: Int? - get() = findAnnotation("kotlin/Metadata", false)?.get("k") as Int? - -fun ClassNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) = findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible) -fun MethodNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) = findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible) -fun FieldNode.findAnnotation(annotationName: String, includeInvisible: Boolean = false) = findAnnotation(annotationName, visibleAnnotations, invisibleAnnotations, includeInvisible) - -operator fun AnnotationNode.get(key: String): Any? = values.annotationValue(key) - -private fun List.annotationValue(key: String): Any? { - for (index in (0 .. size / 2 - 1)) { - if (this[index*2] == key) - return this[index*2 + 1] - } - return null -} - -private fun findAnnotation(annotationName: String, visibleAnnotations: List?, invisibleAnnotations: List?, includeInvisible: Boolean): AnnotationNode? = - visibleAnnotations?.firstOrNull { it.refersToName(annotationName) } ?: - if (includeInvisible) invisibleAnnotations?.firstOrNull { it.refersToName(annotationName) } else null - -fun AnnotationNode.refersToName(name: String) = desc.startsWith('L') && desc.endsWith(';') && desc.regionMatches(1, name, 0, name.length) \ No newline at end of file diff --git a/binary-compatibility-validator/src/kotlinVisibilities.kt b/binary-compatibility-validator/src/kotlinVisibilities.kt deleted file mode 100644 index 4322140c80..0000000000 --- a/binary-compatibility-validator/src/kotlinVisibilities.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines.tools - -import com.google.gson.internal.* -import com.google.gson.stream.* -import java.io.* - -data class ClassVisibility(val name: String, val visibility: String?, val members: Map) -data class MemberVisibility(val member: MemberSignature, val declaration: String?, val visibility: String?) -data class MemberSignature(val name: String, val desc: String) - -private fun isPublic(visibility: String?, isPublishedApi: Boolean) = visibility == null || visibility == "public" || visibility == "protected" || (isPublishedApi && visibility == "internal") -fun ClassVisibility.isPublic(isPublishedApi: Boolean) = isPublic(visibility, isPublishedApi) -fun MemberVisibility.isPublic(isPublishedApi: Boolean) = isPublic(visibility, isPublishedApi) - -fun MemberVisibility.isLateInit() = declaration != null && "lateinit var " in declaration - -private val varValPrefix = Regex("va[lr]\\s+") -fun ClassVisibility.findSetterForProperty(property: MemberVisibility): MemberVisibility? { - // ad-hoc solution: - val declaration = property.declaration ?: return null - val match = varValPrefix.find(declaration) ?: return null - val name = declaration.substring(match.range.endInclusive + 1).substringBefore(':') - val setterName = "" - return members.values.find { it.declaration?.contains(setterName) ?: false } -} - -fun readKotlinVisibilities(declarationFile: File): Map { - val result = mutableListOf() - declarationFile.bufferedReader().use { reader -> - val jsonReader = JsonReader(reader) - jsonReader.beginArray() - while (jsonReader.hasNext()) { - val classObject = Streams.parse(jsonReader).asJsonObject - result += with (classObject) { - val name = getAsJsonPrimitive("class").asString - val visibility = getAsJsonPrimitive("visibility")?.asString - val members = getAsJsonArray("members").map { it -> - with(it.asJsonObject) { - val name = getAsJsonPrimitive("name").asString - val desc = getAsJsonPrimitive("desc").asString - val declaration = getAsJsonPrimitive("declaration")?.asString - val visibility = getAsJsonPrimitive("visibility")?.asString - MemberVisibility(MemberSignature(name, desc), declaration, visibility) - } - } - ClassVisibility(name, visibility, members.associateByTo(hashMapOf()) { it.member }) - } - } - jsonReader.endArray() - } - - return result.associateByTo(hashMapOf()) { it.name } -} diff --git a/binary-compatibility-validator/test/CasesPublicAPITest.kt b/binary-compatibility-validator/test/CasesPublicAPITest.kt deleted file mode 100644 index f0212e70a9..0000000000 --- a/binary-compatibility-validator/test/CasesPublicAPITest.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines.tools - -import org.junit.* -import org.junit.rules.* -import java.io.* - -class CasesPublicAPITest { - - companion object { - val visibilities by lazy { readKotlinVisibilities(File(System.getProperty("testCasesDeclarations")!!)) } - - val baseClassPaths: List = - System.getProperty("testCasesClassesDirs") - .let { requireNotNull(it) { "Specify testCasesClassesDirs with a system property" } } - .split(File.pathSeparator) - .map { File(it, "cases").canonicalFile } - val baseOutputPath = File("test/cases") - } - - @Rule - @JvmField - val testName = TestName() - - @Test - fun companions() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun inline() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun interfaces() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun internal() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun java() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun localClasses() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun nestedClasses() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun private() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun protected() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun public() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun special() { - snapshotAPIAndCompare(testName.methodName) - } - - @Test - fun whenMappings() { - snapshotAPIAndCompare(testName.methodName) - } - - - private fun snapshotAPIAndCompare(testClassRelativePath: String) { - val testClassPaths = baseClassPaths.map { it.resolve(testClassRelativePath) } - val testClasses = testClassPaths.flatMap { it.listFiles().orEmpty().asIterable() } - check(testClasses.isNotEmpty()) { "No class files are found in paths: $testClassPaths" } - val testClassStreams = testClasses.asSequence().filter { it.name.endsWith(".class") }.map { it.inputStream() } - val api = getBinaryAPI(testClassStreams, visibilities).filterOutNonPublic() - val target = baseOutputPath.resolve(testClassRelativePath).resolve(testName.methodName + ".txt") - api.dumpAndCompareWith(target) - } -} diff --git a/binary-compatibility-validator/test/PublicApiTest.kt b/binary-compatibility-validator/test/PublicApiTest.kt deleted file mode 100644 index fb4f55cc17..0000000000 --- a/binary-compatibility-validator/test/PublicApiTest.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines.tools - -import org.junit.* -import org.junit.runner.* -import org.junit.runners.* -import java.io.* -import java.util.* -import java.util.jar.* -import kotlin.collections.ArrayList - -@RunWith(Parameterized::class) -class PublicApiTest( - private val rootDir: String, - private val moduleName: String -) { - companion object { - private val apiProps = ClassLoader.getSystemClassLoader() - .getResource("api.properties").openStream().use { Properties().apply { load(it) } } - private val nonPublicPackages = apiProps.getProperty("packages.internal")!!.split(" ") - - @Parameterized.Parameters(name = "{1}") - @JvmStatic - fun modules(): List> { - val moduleRoots = apiProps.getProperty("module.roots").split(" ") - val moduleMarker = apiProps.getProperty("module.marker")!! - val moduleIgnore = apiProps.getProperty("module.ignore")!!.split(" ").toSet() - val modules = ArrayList>() - for (rootDir in moduleRoots) { - File("../$rootDir").listFiles( FileFilter { it.isDirectory })?.forEach { dir -> - if (dir.name !in moduleIgnore && File(dir, moduleMarker).exists()) { - modules += arrayOf(rootDir, dir.name) - } - } - } - return modules - } - } - - @Test - fun testApi() { - val libsDir = File("../$rootDir/$moduleName/build/libs").absoluteFile.normalize() - val jarPath = getJarPath(libsDir) - val kotlinJvmMappingsFiles = listOf(libsDir.resolve("../visibilities.json")) - val visibilities = - kotlinJvmMappingsFiles - .map { readKotlinVisibilities(it) } - .reduce { m1, m2 -> m1 + m2 } - JarFile(jarPath).use { jarFile -> - val api = getBinaryAPI(jarFile, visibilities).filterOutNonPublic(nonPublicPackages) - api.dumpAndCompareWith(File("reference-public-api").resolve("$moduleName.txt")) - // check for atomicfu leaks - jarFile.checkForAtomicFu() - } - } - - private fun getJarPath(libsDir: File): File { - val regex = Regex("$moduleName-.+\\.jar") - var files = (libsDir.listFiles() ?: throw Exception("Cannot list files in $libsDir")) - .filter { it.name.let { - it matches regex - && !it.endsWith("-sources.jar") - && !it.endsWith("-javadoc.jar") - && !it.endsWith("-tests.jar")} - && !it.name.contains("-metadata-")} - if (files.size > 1) // maybe multiplatform? - files = files.filter { it.name.startsWith("$moduleName-jvm-") } - return files.singleOrNull() ?: - error("No single file matching $regex in $libsDir:\n${files.joinToString("\n")}") - } -} - -private val ATOMIC_FU_REF = "Lkotlinx/atomicfu/".toByteArray() - -private fun JarFile.checkForAtomicFu() { - val foundClasses = mutableListOf() - for (e in entries()) { - if (!e.name.endsWith(".class")) continue - val bytes = getInputStream(e).use { it.readBytes() } - loop@for (i in 0 until bytes.size - ATOMIC_FU_REF.size) { - for (j in 0 until ATOMIC_FU_REF.size) { - if (bytes[i + j] != ATOMIC_FU_REF[j]) continue@loop - } - foundClasses += e.name // report error at the end with all class names - break@loop - } - } - if (foundClasses.isNotEmpty()) { - error("Found references to atomicfu in jar file $name in the following class files: ${ - foundClasses.joinToString("") { "\n\t\t" + it } - }") - } -} diff --git a/binary-compatibility-validator/test/cases/companions/companions.kt b/binary-compatibility-validator/test/cases/companions/companions.kt deleted file mode 100644 index ef59c6febb..0000000000 --- a/binary-compatibility-validator/test/cases/companions/companions.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.companions - - -object PublicClasses { - class PublicCompanion { - companion object - } - - class ProtectedCompanion { - protected companion object - } - - abstract class AbstractProtectedCompanion { - protected companion object - } - - class InternalCompanion { - internal companion object - } - - class PrivateCompanion { - private companion object - } -} - -object PublicInterfaces { - interface PublicCompanion { - companion object - } - - interface PrivateCompanion { - private companion object - } -} - - - -object InternalClasses { - internal class PublicCompanion { - companion object - } - - internal class ProtectedCompanion { - protected companion object - } - - internal abstract class AbstractProtectedCompanion { - protected companion object - } - - internal class InternalCompanion { - internal companion object - } - - internal class PrivateCompanion { - private companion object - } -} - -object InternalInterfaces { - internal interface PublicCompanion { - companion object - } - - internal interface PrivateCompanion { - private companion object - } -} - - -object PrivateClasses { - private class PublicCompanion { - companion object - } - - private class ProtectedCompanion { - protected companion object - } - - private abstract class AbstractProtectedCompanion { - protected companion object - } - - private class InternalCompanion { - internal companion object - } - - private class PrivateCompanion { - private companion object - } -} - -object PrivateInterfaces { - private interface PublicCompanion { - companion object - } - - private interface PrivateCompanion { - private companion object - } -} - diff --git a/binary-compatibility-validator/test/cases/companions/companions.txt b/binary-compatibility-validator/test/cases/companions/companions.txt deleted file mode 100644 index 691907ba0d..0000000000 --- a/binary-compatibility-validator/test/cases/companions/companions.txt +++ /dev/null @@ -1,66 +0,0 @@ -public final class cases/companions/InternalClasses { - public static final field INSTANCE Lcases/companions/InternalClasses; -} - -public final class cases/companions/InternalInterfaces { - public static final field INSTANCE Lcases/companions/InternalInterfaces; -} - -public final class cases/companions/PrivateClasses { - public static final field INSTANCE Lcases/companions/PrivateClasses; -} - -public final class cases/companions/PrivateInterfaces { - public static final field INSTANCE Lcases/companions/PrivateInterfaces; -} - -public final class cases/companions/PublicClasses { - public static final field INSTANCE Lcases/companions/PublicClasses; -} - -public abstract class cases/companions/PublicClasses$AbstractProtectedCompanion { - public static final field Companion Lcases/companions/PublicClasses$AbstractProtectedCompanion$Companion; - public fun ()V -} - -protected final class cases/companions/PublicClasses$AbstractProtectedCompanion$Companion { -} - -public final class cases/companions/PublicClasses$InternalCompanion { - public static final field Companion Lcases/companions/PublicClasses$InternalCompanion$Companion; - public fun ()V -} - -public final class cases/companions/PublicClasses$PrivateCompanion { - public static final field Companion Lcases/companions/PublicClasses$PrivateCompanion$Companion; - public fun ()V -} - -public final class cases/companions/PublicClasses$ProtectedCompanion { - public static final field Companion Lcases/companions/PublicClasses$ProtectedCompanion$Companion; - public fun ()V -} - -public final class cases/companions/PublicClasses$PublicCompanion { - public static final field Companion Lcases/companions/PublicClasses$PublicCompanion$Companion; - public fun ()V -} - -public final class cases/companions/PublicClasses$PublicCompanion$Companion { -} - -public final class cases/companions/PublicInterfaces { - public static final field INSTANCE Lcases/companions/PublicInterfaces; -} - -public abstract interface class cases/companions/PublicInterfaces$PrivateCompanion { - public static final field Companion Lcases/companions/PublicInterfaces$PrivateCompanion$Companion; -} - -public abstract interface class cases/companions/PublicInterfaces$PublicCompanion { - public static final field Companion Lcases/companions/PublicInterfaces$PublicCompanion$Companion; -} - -public final class cases/companions/PublicInterfaces$PublicCompanion$Companion { -} - diff --git a/binary-compatibility-validator/test/cases/inline/inline.txt b/binary-compatibility-validator/test/cases/inline/inline.txt deleted file mode 100644 index 4961dbcfd4..0000000000 --- a/binary-compatibility-validator/test/cases/inline/inline.txt +++ /dev/null @@ -1,9 +0,0 @@ -public final class cases/inline/InlineExposedKt { - public static final fun exposedForInline ()V -} - -public final class cases/inline/InternalClassExposed { - public fun ()V - public final fun funExposed ()V -} - diff --git a/binary-compatibility-validator/test/cases/inline/inlineExposed.kt b/binary-compatibility-validator/test/cases/inline/inlineExposed.kt deleted file mode 100644 index 2e017b3832..0000000000 --- a/binary-compatibility-validator/test/cases/inline/inlineExposed.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.inline - -@PublishedApi -internal fun exposedForInline() {} - -@PublishedApi -internal class InternalClassExposed - @PublishedApi - internal constructor() { - - @PublishedApi - internal fun funExposed() {} - - // TODO: Cover unsupported cases: requires correctly reflecting annotations from properties - /* - @PublishedApi - internal var propertyExposed: String? = null - - @JvmField - @PublishedApi - internal var fieldExposed: String? = null - */ - -} diff --git a/binary-compatibility-validator/test/cases/inline/inlineOnly.kt b/binary-compatibility-validator/test/cases/inline/inlineOnly.kt deleted file mode 100644 index 9c1f01eb0e..0000000000 --- a/binary-compatibility-validator/test/cases/inline/inlineOnly.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.inline - -@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") -@kotlin.internal.InlineOnly -public inline fun inlineOnly(f: () -> Unit) = f() \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/interfaces/interfaceWithEmptyImpls.kt b/binary-compatibility-validator/test/cases/interfaces/interfaceWithEmptyImpls.kt deleted file mode 100644 index 96a1628c82..0000000000 --- a/binary-compatibility-validator/test/cases/interfaces/interfaceWithEmptyImpls.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.interfaces - -public interface EmptyImpls { - @SinceKotlin("1.1") - val property: String -} diff --git a/binary-compatibility-validator/test/cases/interfaces/interfaceWithImpls.kt b/binary-compatibility-validator/test/cases/interfaces/interfaceWithImpls.kt deleted file mode 100644 index d2e4ad0c36..0000000000 --- a/binary-compatibility-validator/test/cases/interfaces/interfaceWithImpls.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.interfaces - -public interface BaseWithImpl { - fun foo() = 42 -} - -public interface DerivedWithImpl : BaseWithImpl { - override fun foo(): Int { - return super.foo() + 1 - } -} - -public interface DerivedWithoutImpl : BaseWithImpl - diff --git a/binary-compatibility-validator/test/cases/interfaces/interfaces.txt b/binary-compatibility-validator/test/cases/interfaces/interfaces.txt deleted file mode 100644 index 4f37b42f3a..0000000000 --- a/binary-compatibility-validator/test/cases/interfaces/interfaces.txt +++ /dev/null @@ -1,27 +0,0 @@ -public abstract interface class cases/interfaces/BaseWithImpl { - public abstract fun foo ()I -} - -public final class cases/interfaces/BaseWithImpl$DefaultImpls { - public static fun foo (Lcases/interfaces/BaseWithImpl;)I -} - -public abstract interface class cases/interfaces/DerivedWithImpl : cases/interfaces/BaseWithImpl { - public abstract fun foo ()I -} - -public final class cases/interfaces/DerivedWithImpl$DefaultImpls { - public static fun foo (Lcases/interfaces/DerivedWithImpl;)I -} - -public abstract interface class cases/interfaces/DerivedWithoutImpl : cases/interfaces/BaseWithImpl { -} - -public final class cases/interfaces/DerivedWithoutImpl$DefaultImpls { - public static fun foo (Lcases/interfaces/DerivedWithoutImpl;)I -} - -public abstract interface class cases/interfaces/EmptyImpls { - public abstract fun getProperty ()Ljava/lang/String; -} - diff --git a/binary-compatibility-validator/test/cases/internal/internal.txt b/binary-compatibility-validator/test/cases/internal/internal.txt deleted file mode 100644 index 2ebfa3aff3..0000000000 --- a/binary-compatibility-validator/test/cases/internal/internal.txt +++ /dev/null @@ -1,3 +0,0 @@ -public final class cases/internal/PublicClass { -} - diff --git a/binary-compatibility-validator/test/cases/internal/internalClass.kt b/binary-compatibility-validator/test/cases/internal/internalClass.kt deleted file mode 100644 index 2410b65791..0000000000 --- a/binary-compatibility-validator/test/cases/internal/internalClass.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.internal - -internal class InternalClass { - public val property = 1 - - public fun function() = property -} \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/internal/internalMultifile1.kt b/binary-compatibility-validator/test/cases/internal/internalMultifile1.kt deleted file mode 100644 index b4622b3afd..0000000000 --- a/binary-compatibility-validator/test/cases/internal/internalMultifile1.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:JvmName("MultifileKt") -@file:JvmMultifileClass -package cases.internal - -internal fun internalFun1() = internalVal diff --git a/binary-compatibility-validator/test/cases/internal/internalMultifile2.kt b/binary-compatibility-validator/test/cases/internal/internalMultifile2.kt deleted file mode 100644 index c375c01e16..0000000000 --- a/binary-compatibility-validator/test/cases/internal/internalMultifile2.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:JvmName("MultifileKt") -@file:JvmMultifileClass -package cases.internal - -internal val internalVal = "Internal" diff --git a/binary-compatibility-validator/test/cases/internal/internalPart.kt b/binary-compatibility-validator/test/cases/internal/internalPart.kt deleted file mode 100644 index b95ba6830e..0000000000 --- a/binary-compatibility-validator/test/cases/internal/internalPart.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.internal - -internal fun internalFun() { - -} - -// TODO: var, val, const \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/internal/publicClassInternalMember.kt b/binary-compatibility-validator/test/cases/internal/publicClassInternalMember.kt deleted file mode 100644 index 11aac7c5cb..0000000000 --- a/binary-compatibility-validator/test/cases/internal/publicClassInternalMember.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.internal - -public class PublicClass internal constructor() { - - internal val property = 1 - - internal fun function() = property - -} diff --git a/binary-compatibility-validator/test/cases/java/Facade.java b/binary-compatibility-validator/test/cases/java/Facade.java deleted file mode 100644 index d11c16cd7f..0000000000 --- a/binary-compatibility-validator/test/cases/java/Facade.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.java; - -class Part1 { - public static void publicMethod(int param) { } - - public static class Part2 extends Part1 { - public static void publicMethod(String param) { } - } -} - - -public class Facade extends Part1.Part2 { } diff --git a/binary-compatibility-validator/test/cases/java/java.txt b/binary-compatibility-validator/test/cases/java/java.txt deleted file mode 100644 index 75bfd3179f..0000000000 --- a/binary-compatibility-validator/test/cases/java/java.txt +++ /dev/null @@ -1,6 +0,0 @@ -public class cases/java/Facade { - public fun ()V - public static fun publicMethod (I)V - public static fun publicMethod (Ljava/lang/String;)V -} - diff --git a/binary-compatibility-validator/test/cases/localClasses/fromStdlib.kt b/binary-compatibility-validator/test/cases/localClasses/fromStdlib.kt deleted file mode 100644 index 29f6994ec3..0000000000 --- a/binary-compatibility-validator/test/cases/localClasses/fromStdlib.kt +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.localClasses - -private val COMPARER = compareBy { it.length } \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/localClasses/lambdas.kt b/binary-compatibility-validator/test/cases/localClasses/lambdas.kt deleted file mode 100644 index a99c4497ff..0000000000 --- a/binary-compatibility-validator/test/cases/localClasses/lambdas.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.localClasses - - -class L { - internal fun a(lambda: () -> Unit) = lambda() - - @Suppress("NOTHING_TO_INLINE") - internal inline fun inlineLambda() { - a { - println("OK") - } - } -} - -fun box() { - L().inlineLambda() -} - - -// TODO: inline lambda from stdlib \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/localClasses/localClasses.kt b/binary-compatibility-validator/test/cases/localClasses/localClasses.kt deleted file mode 100644 index 1af4b77df9..0000000000 --- a/binary-compatibility-validator/test/cases/localClasses/localClasses.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.localClasses - -class A { - fun a() : String { - class B() { - fun s() : String = "OK" - - inner class C {} - - } - return B().s() - } -} - - -class B { - fun a(p: String) : String { - class B() { - fun s() : String = p - } - return B().s() - } -} diff --git a/binary-compatibility-validator/test/cases/localClasses/localClasses.txt b/binary-compatibility-validator/test/cases/localClasses/localClasses.txt deleted file mode 100644 index da0d668ced..0000000000 --- a/binary-compatibility-validator/test/cases/localClasses/localClasses.txt +++ /dev/null @@ -1,18 +0,0 @@ -public final class cases/localClasses/A { - public fun ()V - public final fun a ()Ljava/lang/String; -} - -public final class cases/localClasses/B { - public fun ()V - public final fun a (Ljava/lang/String;)Ljava/lang/String; -} - -public final class cases/localClasses/L { - public fun ()V -} - -public final class cases/localClasses/LambdasKt { - public static final fun box ()V -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/internalClass.kt b/binary-compatibility-validator/test/cases/nestedClasses/internalClass.kt deleted file mode 100644 index 7af2dda914..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/internalClass.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -internal class InternalClass { - public object ObjPublic - internal object ObjInternal - protected object ObjProtected - private object ObjPrivate - - public class NestedPublic - internal class NestedInternal - protected class NestedProtected - private class NestedPrivate - - public interface NestedPublicInterface - internal interface NestedInternalInterface - protected interface NestedProtectedInterface - private interface NestedPrivateInterface - - public inner class InnerPublic - internal inner class InnerInternal - protected inner class InnerProtected - private inner class InnerPrivate -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/internalInterface.kt b/binary-compatibility-validator/test/cases/nestedClasses/internalInterface.kt deleted file mode 100644 index a0affc53a6..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/internalInterface.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -internal interface InternalInterface { - public object ObjPublic - private object ObjPrivate - - public class NestedPublic - private class NestedPrivate - - public interface NestedPublicInterface - private interface NestedPrivateInterface - -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/internalObject.kt b/binary-compatibility-validator/test/cases/nestedClasses/internalObject.kt deleted file mode 100644 index ca3fd8344b..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/internalObject.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -internal object InternalObject { - - public object ObjPublic - internal object ObjInternal - private object ObjPrivate - - public class NestedPublic - internal class NestedInternal - private class NestedPrivate - - public interface NestedPublicInterface - internal interface NestedInternalInterface - private interface NestedPrivateInterface -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/nestedClasses.txt b/binary-compatibility-validator/test/cases/nestedClasses/nestedClasses.txt deleted file mode 100644 index 4ba38c780f..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/nestedClasses.txt +++ /dev/null @@ -1,86 +0,0 @@ -public abstract class cases/nestedClasses/PublicAbstractClass { - public fun ()V -} - -protected final class cases/nestedClasses/PublicAbstractClass$InnerProtected { - public fun (Lcases/nestedClasses/PublicAbstractClass;)V -} - -protected final class cases/nestedClasses/PublicAbstractClass$NestedProtected { - public fun ()V -} - -protected abstract interface class cases/nestedClasses/PublicAbstractClass$NestedProtectedInterface { -} - -protected final class cases/nestedClasses/PublicAbstractClass$ObjProtected { - public static final field INSTANCE Lcases/nestedClasses/PublicAbstractClass$ObjProtected; -} - -public final class cases/nestedClasses/PublicClass { - public fun ()V -} - -public final class cases/nestedClasses/PublicClass$InnerPublic { - public fun (Lcases/nestedClasses/PublicClass;)V -} - -public final class cases/nestedClasses/PublicClass$NestedPublic { - public fun ()V -} - -public abstract interface class cases/nestedClasses/PublicClass$NestedPublicInterface { -} - -public final class cases/nestedClasses/PublicClass$ObjPublic { - public static final field INSTANCE Lcases/nestedClasses/PublicClass$ObjPublic; -} - -public abstract interface class cases/nestedClasses/PublicInterface { -} - -public final class cases/nestedClasses/PublicInterface$NestedPublic { - public fun ()V -} - -public abstract interface class cases/nestedClasses/PublicInterface$NestedPublicInterface { -} - -public final class cases/nestedClasses/PublicInterface$ObjPublic { - public static final field INSTANCE Lcases/nestedClasses/PublicInterface$ObjPublic; -} - -public final class cases/nestedClasses/PublicObject { - public static final field INSTANCE Lcases/nestedClasses/PublicObject; -} - -public final class cases/nestedClasses/PublicObject$NestedPublic { - public fun ()V -} - -public abstract interface class cases/nestedClasses/PublicObject$NestedPublicInterface { -} - -public final class cases/nestedClasses/PublicObject$ObjPublic { - public static final field INSTANCE Lcases/nestedClasses/PublicObject$ObjPublic; -} - -public class cases/nestedClasses/PublicOpenClass { - public fun ()V -} - -protected final class cases/nestedClasses/PublicOpenClass$InnerProtected { - public fun (Lcases/nestedClasses/PublicOpenClass;)V -} - -protected final class cases/nestedClasses/PublicOpenClass$NestedProtected { - public fun ()V -} - -protected abstract interface class cases/nestedClasses/PublicOpenClass$NestedProtectedInterface { -} - -protected final class cases/nestedClasses/PublicOpenClass$ObjProtected { - public static final field INSTANCE Lcases/nestedClasses/PublicOpenClass$ObjProtected; -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/privateClass.kt b/binary-compatibility-validator/test/cases/nestedClasses/privateClass.kt deleted file mode 100644 index 1e1fa8a8e3..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/privateClass.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -private class PrivateClass { - public object ObjPublic - internal object ObjInternal - protected object ObjProtected - private object ObjPrivate - - public class NestedPublic - internal class NestedInternal - protected class NestedProtected - private class NestedPrivate - - public interface NestedPublicInterface - internal interface NestedInternalInterface - protected interface NestedProtectedInterface - private interface NestedPrivateInterface - - public inner class InnerPublic - internal inner class InnerInternal - protected inner class InnerProtected - private inner class InnerPrivate -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/privateInterface.kt b/binary-compatibility-validator/test/cases/nestedClasses/privateInterface.kt deleted file mode 100644 index 8c936a1fdb..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/privateInterface.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -private interface PrivateInterface { - public object ObjPublic - private object ObjPrivate - - public class NestedPublic - private class NestedPrivate - - public interface NestedPublicInterface - private interface NestedPrivateInterface - -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/privateObject.kt b/binary-compatibility-validator/test/cases/nestedClasses/privateObject.kt deleted file mode 100644 index 4251d25e78..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/privateObject.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -private object PrivateObject { - - public object ObjPublic - internal object ObjInternal - private object ObjPrivate - - public class NestedPublic - internal class NestedInternal - private class NestedPrivate - - public interface NestedPublicInterface - internal interface NestedInternalInterface - private interface NestedPrivateInterface -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/publicAbstractClass.kt b/binary-compatibility-validator/test/cases/nestedClasses/publicAbstractClass.kt deleted file mode 100644 index 1da59a5b02..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/publicAbstractClass.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -public abstract class PublicAbstractClass { - protected object ObjProtected - - protected class NestedProtected - - protected interface NestedProtectedInterface - - protected inner class InnerProtected -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/publicClass.kt b/binary-compatibility-validator/test/cases/nestedClasses/publicClass.kt deleted file mode 100644 index 64f487d970..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/publicClass.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -public class PublicClass { - public object ObjPublic - internal object ObjInternal - protected object ObjProtected - private object ObjPrivate - - public class NestedPublic - internal class NestedInternal - protected class NestedProtected - private class NestedPrivate - - public interface NestedPublicInterface - internal interface NestedInternalInterface - protected interface NestedProtectedInterface - private interface NestedPrivateInterface - - public inner class InnerPublic - internal inner class InnerInternal - protected inner class InnerProtected - private inner class InnerPrivate -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/publicInterface.kt b/binary-compatibility-validator/test/cases/nestedClasses/publicInterface.kt deleted file mode 100644 index 3ee24f549a..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/publicInterface.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -public interface PublicInterface { - public object ObjPublic - private object ObjPrivate - - public class NestedPublic - private class NestedPrivate - - public interface NestedPublicInterface - private interface NestedPrivateInterface - -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/publicObject.kt b/binary-compatibility-validator/test/cases/nestedClasses/publicObject.kt deleted file mode 100644 index 6ce2bcdd04..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/publicObject.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -public object PublicObject { - - public object ObjPublic - internal object ObjInternal - private object ObjPrivate - - public class NestedPublic - internal class NestedInternal - private class NestedPrivate - - public interface NestedPublicInterface - internal interface NestedInternalInterface - private interface NestedPrivateInterface -} - diff --git a/binary-compatibility-validator/test/cases/nestedClasses/publicOpenClass.kt b/binary-compatibility-validator/test/cases/nestedClasses/publicOpenClass.kt deleted file mode 100644 index 1c9edef504..0000000000 --- a/binary-compatibility-validator/test/cases/nestedClasses/publicOpenClass.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.nestedClasses - -public open class PublicOpenClass { - protected object ObjProtected - - protected class NestedProtected - - protected interface NestedProtectedInterface - - protected inner class InnerProtected -} - diff --git a/binary-compatibility-validator/test/cases/private/private.txt b/binary-compatibility-validator/test/cases/private/private.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/binary-compatibility-validator/test/cases/private/privateClassMembers.kt b/binary-compatibility-validator/test/cases/private/privateClassMembers.kt deleted file mode 100644 index 92dd618372..0000000000 --- a/binary-compatibility-validator/test/cases/private/privateClassMembers.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.private - -private open class PrivateClass public constructor() { - internal val internalVal = 1 - - protected fun protectedFun() = internalVal -} diff --git a/binary-compatibility-validator/test/cases/private/privateMultifile1.kt b/binary-compatibility-validator/test/cases/private/privateMultifile1.kt deleted file mode 100644 index 8f7535f869..0000000000 --- a/binary-compatibility-validator/test/cases/private/privateMultifile1.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:JvmName("MultifileKt") -@file:JvmMultifileClass -package cases.private - -private val privateVal: Any? = 1 -private var privateVar: Any? = 1 - - diff --git a/binary-compatibility-validator/test/cases/private/privateMultifile2.kt b/binary-compatibility-validator/test/cases/private/privateMultifile2.kt deleted file mode 100644 index ee0a08049c..0000000000 --- a/binary-compatibility-validator/test/cases/private/privateMultifile2.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:JvmName("MultifileKt") -@file:JvmMultifileClass -package cases.private - - -// const -private const val privateConst: Int = 4 - -// fun -@Suppress("UNUSED_PARAMETER") -private fun privateFun(x: Any) {} - - -private class PrivateClassInMultifile { - internal fun accessUsage() { - privateFun(privateConst) - } - -} diff --git a/binary-compatibility-validator/test/cases/private/privatePart.kt b/binary-compatibility-validator/test/cases/private/privatePart.kt deleted file mode 100644 index 93d4ec14a0..0000000000 --- a/binary-compatibility-validator/test/cases/private/privatePart.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.private - -// properties -private val privateVal: Any? = 1 -private var privateVar: Any? = 1 - -// constants - -private const val privateConst: Int = 4 - -// fun - -@Suppress("UNUSED_PARAMETER") -private fun privateFun(a: Any?) = privateConst - -// access -private class PrivateClassInPart { - internal fun accessUsage() { - privateFun(privateVal) - privateFun(privateVar) - privateFun(privateConst) - } - -} \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/protected/protected.txt b/binary-compatibility-validator/test/cases/protected/protected.txt deleted file mode 100644 index 3c28d7e163..0000000000 --- a/binary-compatibility-validator/test/cases/protected/protected.txt +++ /dev/null @@ -1,19 +0,0 @@ -public abstract class cases/protected/PublicAbstractClass { - protected fun ()V - protected abstract fun getProtectedVal ()I - protected abstract fun getProtectedVar ()Ljava/lang/Object; - protected abstract fun protectedFun ()V - protected abstract fun setProtectedVar (Ljava/lang/Object;)V -} - -public final class cases/protected/PublicFinalClass { -} - -public class cases/protected/PublicOpenClass { - protected fun ()V - protected final fun getProtectedVal ()I - protected final fun getProtectedVar ()I - protected final fun protectedFun ()I - protected final fun setProtectedVar (I)V -} - diff --git a/binary-compatibility-validator/test/cases/protected/protectedInAbstract.kt b/binary-compatibility-validator/test/cases/protected/protectedInAbstract.kt deleted file mode 100644 index ab4e26fef6..0000000000 --- a/binary-compatibility-validator/test/cases/protected/protectedInAbstract.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.protected - -public abstract class PublicAbstractClass protected constructor() { - protected abstract val protectedVal: Int - protected abstract var protectedVar: Any? - - protected abstract fun protectedFun() -} diff --git a/binary-compatibility-validator/test/cases/protected/protectedInFinal.kt b/binary-compatibility-validator/test/cases/protected/protectedInFinal.kt deleted file mode 100644 index 419e3f420c..0000000000 --- a/binary-compatibility-validator/test/cases/protected/protectedInFinal.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.protected - -public class PublicFinalClass protected constructor() { - protected val protectedVal = 1 - protected var protectedVar = 2 - - protected fun protectedFun() = protectedVal -} diff --git a/binary-compatibility-validator/test/cases/protected/protectedInOpen.kt b/binary-compatibility-validator/test/cases/protected/protectedInOpen.kt deleted file mode 100644 index ee6868354f..0000000000 --- a/binary-compatibility-validator/test/cases/protected/protectedInOpen.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.protected - -public open class PublicOpenClass protected constructor() { - protected val protectedVal = 1 - protected var protectedVar = 2 - - protected fun protectedFun() = protectedVal -} diff --git a/binary-compatibility-validator/test/cases/public/public.txt b/binary-compatibility-validator/test/cases/public/public.txt deleted file mode 100644 index c9dd5dd2b7..0000000000 --- a/binary-compatibility-validator/test/cases/public/public.txt +++ /dev/null @@ -1,9 +0,0 @@ -public final class cases/public/MultifileKt { - public static final fun getPublicVal ()Ljava/lang/String; - public static final fun publicFun1 ()Ljava/lang/String; -} - -public final class cases/public/PublicPartKt { - public static final fun publicFun ()V -} - diff --git a/binary-compatibility-validator/test/cases/public/publicMultifile1.kt b/binary-compatibility-validator/test/cases/public/publicMultifile1.kt deleted file mode 100644 index ccc6823c3e..0000000000 --- a/binary-compatibility-validator/test/cases/public/publicMultifile1.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:JvmName("MultifileKt") -@file:JvmMultifileClass -package cases.public - -public fun publicFun1() = publicVal diff --git a/binary-compatibility-validator/test/cases/public/publicMultifile2.kt b/binary-compatibility-validator/test/cases/public/publicMultifile2.kt deleted file mode 100644 index 174bd43d39..0000000000 --- a/binary-compatibility-validator/test/cases/public/publicMultifile2.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:JvmName("MultifileKt") -@file:JvmMultifileClass -package cases.public - -public val publicVal = "Public" diff --git a/binary-compatibility-validator/test/cases/public/publicPart.kt b/binary-compatibility-validator/test/cases/public/publicPart.kt deleted file mode 100644 index 3ad78362d1..0000000000 --- a/binary-compatibility-validator/test/cases/public/publicPart.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.public - -public fun publicFun() { - -} \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/special/hidden.kt b/binary-compatibility-validator/test/cases/special/hidden.kt deleted file mode 100644 index cb389b8d0d..0000000000 --- a/binary-compatibility-validator/test/cases/special/hidden.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.special - -@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) -public class HiddenClass - @Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) - public constructor() { - - @Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) - val hiddenVal = 1 - - @Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) - var hiddenVar = 2 - - @Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) - fun hiddenFun() {} - - public var varWithHiddenAccessors: String = "" - @Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) - get - @Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) - set -} - -@Deprecated("For binary compatibility", level = DeprecationLevel.HIDDEN) -fun hiddenTopLevelFun() {} diff --git a/binary-compatibility-validator/test/cases/special/internalLateinitMember.kt b/binary-compatibility-validator/test/cases/special/internalLateinitMember.kt deleted file mode 100644 index e9819fa4e8..0000000000 --- a/binary-compatibility-validator/test/cases/special/internalLateinitMember.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.special - -public class ClassWithLateInitMembers internal constructor() { - - public lateinit var publicLateInitWithInternalSet: String - internal set - - internal lateinit var internalLateInit: String - -} \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/special/jvmField.kt b/binary-compatibility-validator/test/cases/special/jvmField.kt deleted file mode 100644 index 9a8c911711..0000000000 --- a/binary-compatibility-validator/test/cases/special/jvmField.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.special - -public open class JvmFieldsClass { - @JvmField - public var publicField = "x" - - @JvmField - internal var internalField = "y" - - @JvmField - protected var protectedField = "y" - - public companion object JvmFieldsCompanion { - @JvmField - public var publicСField = "x" - - @JvmField - internal var internalСField = "y" - - @JvmField - protected var protectedСField = "y" - - public const val publicConst = 1 - internal const val internalConst = 2 - protected const val protectedConst = 3 - private const val privateConst = 4 - } -} - -public object JvmFieldsObject { - @JvmField - public var publicField = "x" - - @JvmField - internal var internalField = "y" - - public const val publicConst = 1 - internal const val internalConst = 2 - private const val privateConst = 4 -} - - -@JvmField -public var publicField = "x" - -@JvmField -internal var internalField = "y" - -public const val publicConst = 1 -internal const val internalConst = 2 -private const val privateConst = 4 diff --git a/binary-compatibility-validator/test/cases/special/jvmNames.kt b/binary-compatibility-validator/test/cases/special/jvmNames.kt deleted file mode 100644 index e304de01fe..0000000000 --- a/binary-compatibility-validator/test/cases/special/jvmNames.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.special - -@JvmName("internalFun") -internal fun internalRenamedFun() {} - -internal var internalVar: Int = 1 - @JvmName("internalVarGetter") - get - @JvmName("internalVarSetter") - set - -@JvmName("publicFun") -public fun publicRenamedFun() {} - -public var publicVar: Int = 1 - @JvmName("publicVarGetter") - get - @JvmName("publicVarSetter") - set - - - diff --git a/binary-compatibility-validator/test/cases/special/jvmOverloads.kt b/binary-compatibility-validator/test/cases/special/jvmOverloads.kt deleted file mode 100644 index 8f238138a2..0000000000 --- a/binary-compatibility-validator/test/cases/special/jvmOverloads.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:Suppress("UNUSED_PARAMETER") - -package cases.special - - -@JvmOverloads -public fun publicFunWithOverloads(a: Int = 0, b: String? = null) {} - -@JvmOverloads -internal fun internalFunWithOverloads(a: Int = 0, b: String? = null) {} - -public class ClassWithOverloads - @JvmOverloads - internal constructor(val a: Int = 0, val b: String? = null) { - - @JvmOverloads - internal fun internalFunWithOverloads(a: Int = 0, b: String? = null) {} - -} \ No newline at end of file diff --git a/binary-compatibility-validator/test/cases/special/special.txt b/binary-compatibility-validator/test/cases/special/special.txt deleted file mode 100644 index 40c074d245..0000000000 --- a/binary-compatibility-validator/test/cases/special/special.txt +++ /dev/null @@ -1,61 +0,0 @@ -public final class cases/special/ClassWithLateInitMembers { - public final fun getPublicLateInitWithInternalSet ()Ljava/lang/String; -} - -public final class cases/special/ClassWithOverloads { - public final fun getA ()I - public final fun getB ()Ljava/lang/String; -} - -public final class cases/special/HiddenClass { - public synthetic fun ()V - public final synthetic fun getHiddenVal ()I - public final synthetic fun getHiddenVar ()I - public final synthetic fun getVarWithHiddenAccessors ()Ljava/lang/String; - public final synthetic fun hiddenFun ()V - public final synthetic fun setHiddenVar (I)V - public final synthetic fun setVarWithHiddenAccessors (Ljava/lang/String;)V -} - -public final class cases/special/HiddenKt { - public static final synthetic fun hiddenTopLevelFun ()V -} - -public final class cases/special/JvmFieldKt { - public static final field publicConst I - public static field publicField Ljava/lang/String; -} - -public class cases/special/JvmFieldsClass { - public static final field JvmFieldsCompanion Lcases/special/JvmFieldsClass$JvmFieldsCompanion; - protected static final field protectedConst I - protected field protectedField Ljava/lang/String; - protected static field protectedСField Ljava/lang/String; - public static final field publicConst I - public field publicField Ljava/lang/String; - public static field publicСField Ljava/lang/String; - public fun ()V -} - -public final class cases/special/JvmFieldsClass$JvmFieldsCompanion { -} - -public final class cases/special/JvmFieldsObject { - public static final field INSTANCE Lcases/special/JvmFieldsObject; - public static final field publicConst I - public static field publicField Ljava/lang/String; -} - -public final class cases/special/JvmNamesKt { - public static final fun publicFun ()V - public static final fun publicVarGetter ()I - public static final fun publicVarSetter (I)V -} - -public final class cases/special/JvmOverloadsKt { - public static final fun publicFunWithOverloads ()V - public static final fun publicFunWithOverloads (I)V - public static final fun publicFunWithOverloads (ILjava/lang/String;)V - public static synthetic fun publicFunWithOverloads$default (ILjava/lang/String;ILjava/lang/Object;)V -} - diff --git a/binary-compatibility-validator/test/cases/whenMappings/enumWhen.kt b/binary-compatibility-validator/test/cases/whenMappings/enumWhen.kt deleted file mode 100644 index ff3a1d01b5..0000000000 --- a/binary-compatibility-validator/test/cases/whenMappings/enumWhen.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.whenMappings - -enum class SampleEnum { - A, - B, - C -} - -fun SampleEnum.deacronimize() = when (this) { - SampleEnum.A -> "Apple" - SampleEnum.B -> "Biscuit" - SampleEnum.C -> "Cinnamon" -} - - -inline fun SampleEnum.switch(thenA: () -> Unit, thenB: () -> Unit, thenC: () -> Unit) = when (this) { - SampleEnum.C -> thenC() - SampleEnum.B -> thenB() - SampleEnum.A -> thenA() -} diff --git a/binary-compatibility-validator/test/cases/whenMappings/sealedClassWhen.kt b/binary-compatibility-validator/test/cases/whenMappings/sealedClassWhen.kt deleted file mode 100644 index 5cd80b5d8d..0000000000 --- a/binary-compatibility-validator/test/cases/whenMappings/sealedClassWhen.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package cases.whenMappings - -sealed class SampleSealed { - class A : SampleSealed() - class B : SampleSealed() - class C : SampleSealed() -} - -fun SampleSealed.deacronimize() = when (this) { - is SampleSealed.A -> "Apple" - is SampleSealed.B -> "Biscuit" - is SampleSealed.C -> "Cinnamon" -} - - -inline fun SampleSealed.switch(thenA: () -> Unit, thenB: () -> Unit, thenC: () -> Unit) = when (this) { - is SampleSealed.C -> thenC() - is SampleSealed.B -> thenB() - is SampleSealed.A -> thenA() -} diff --git a/binary-compatibility-validator/test/cases/whenMappings/whenMappings.txt b/binary-compatibility-validator/test/cases/whenMappings/whenMappings.txt deleted file mode 100644 index 1975cf1364..0000000000 --- a/binary-compatibility-validator/test/cases/whenMappings/whenMappings.txt +++ /dev/null @@ -1,33 +0,0 @@ -public final class cases/whenMappings/EnumWhenKt { - public static final fun deacronimize (Lcases/whenMappings/SampleEnum;)Ljava/lang/String; - public static final fun switch (Lcases/whenMappings/SampleEnum;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V -} - -public final class cases/whenMappings/SampleEnum : java/lang/Enum { - public static final field A Lcases/whenMappings/SampleEnum; - public static final field B Lcases/whenMappings/SampleEnum; - public static final field C Lcases/whenMappings/SampleEnum; - public static fun valueOf (Ljava/lang/String;)Lcases/whenMappings/SampleEnum; - public static fun values ()[Lcases/whenMappings/SampleEnum; -} - -public abstract class cases/whenMappings/SampleSealed { -} - -public final class cases/whenMappings/SampleSealed$A : cases/whenMappings/SampleSealed { - public fun ()V -} - -public final class cases/whenMappings/SampleSealed$B : cases/whenMappings/SampleSealed { - public fun ()V -} - -public final class cases/whenMappings/SampleSealed$C : cases/whenMappings/SampleSealed { - public fun ()V -} - -public final class cases/whenMappings/SealedClassWhenKt { - public static final fun deacronimize (Lcases/whenMappings/SampleSealed;)Ljava/lang/String; - public static final fun switch (Lcases/whenMappings/SampleSealed;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V -} - diff --git a/binary-compatibility-validator/test/utils.kt b/binary-compatibility-validator/test/utils.kt deleted file mode 100644 index c7844108b1..0000000000 --- a/binary-compatibility-validator/test/utils.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.coroutines.tools - -import java.io.* -import kotlin.test.* - -private val OVERWRITE_EXPECTED_OUTPUT = - System.getProperty("overwrite.output")?.toBoolean() ?: false // use -Doverwrite.output=true - -fun List.dumpAndCompareWith(to: File) { - if (!to.exists()) { - to.parentFile?.mkdirs() - to.bufferedWriter().use { dump(to = it) } - fail("Expected data file did not exist. Generated: $to") - } else { - val actual = dump(to = StringBuilder()) - assertEqualsToFile(to, actual) - } -} - -private fun assertEqualsToFile(to: File, actual: CharSequence) { - val actualText = actual.trimTrailingWhitespacesAndAddNewlineAtEOF() - val expectedText = to.readText().trimTrailingWhitespacesAndAddNewlineAtEOF() - if (expectedText == actualText) return // Ok - // Difference - if (OVERWRITE_EXPECTED_OUTPUT) { - to.writeText(actualText) - println("Generated: $to") - return // make test pass when overwriting output - } - // Fail on difference - assertEquals( - expectedText, - actualText, - "Actual data differs from file content: ${to.name}\nTo overwrite the expected API rerun with -Doverwrite.output=true parameter\n" - ) -} - -private fun CharSequence.trimTrailingWhitespacesAndAddNewlineAtEOF(): String = - this.lineSequence().map { it.trimEnd() }.joinToString(separator = "\n").let { - if (it.endsWith("\n")) it else it + "\n" - } - - -private val UPPER_CASE_CHARS = Regex("[A-Z]+") diff --git a/build.gradle b/build.gradle index 94db6c08c8..e03179dddb 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ def rootModule = "kotlinx.coroutines" def coreModule = "kotlinx-coroutines-core" // Not applicable for Kotlin plugin def sourceless = ['kotlinx.coroutines', 'site', 'kotlinx-coroutines-bom'] -def internal = ['kotlinx.coroutines', 'site', 'benchmarks', 'knit', 'js-stub', 'stdlib-stubs', 'binary-compatibility-validator'] +def internal = ['kotlinx.coroutines', 'site', 'benchmarks', 'knit', 'js-stub', 'stdlib-stubs'] // Not published def unpublished = internal + ['example-frontend-js', 'android-unit-tests'] @@ -68,6 +68,7 @@ buildscript { classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version" classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version" classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version" + classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version" // JMH plugins classpath "com.github.jengelman.gradle.plugins:shadow:5.1.0" @@ -119,6 +120,14 @@ allprojects { } } +apply plugin: "binary-compatibility-validator" +apiValidation { + ignoredProjects += ["stdlib-stubs", "benchmarks", "knit", "site", + "kotlinx-coroutines-bom", "android-unit-tests", "js-stub"] + ignoredPackages += "kotlinx.coroutines.internal" +} + + allprojects { apply plugin: 'kotlinx-atomicfu' // it also adds all the necessary dependencies def projectName = it.name diff --git a/gradle.properties b/gradle.properties index 6d8456a5a8..b693ededcd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,7 @@ byte_buddy_version=1.9.3 reactor_vesion=3.2.5.RELEASE reactive_streams_version=1.0.2 rxjava2_version=2.2.8 +binary_compatibility_validator_version=0.1.1 # JS gradle_node_version=1.2.0 @@ -32,4 +33,4 @@ kotlin.incremental.multiplatform=true kotlin.native.ignoreDisabledTargets=true # Site deneration -jekyll_version=4.0 \ No newline at end of file +jekyll_version=4.0 diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt b/integration/kotlinx-coroutines-guava/api/kotlinx-coroutines-guava.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt rename to integration/kotlinx-coroutines-guava/api/kotlinx-coroutines-guava.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt b/integration/kotlinx-coroutines-jdk8/api/kotlinx-coroutines-jdk8.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt rename to integration/kotlinx-coroutines-jdk8/api/kotlinx-coroutines-jdk8.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-play-services.txt b/integration/kotlinx-coroutines-play-services/api/kotlinx-coroutines-play-services.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-play-services.txt rename to integration/kotlinx-coroutines-play-services/api/kotlinx-coroutines-play-services.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-slf4j.txt b/integration/kotlinx-coroutines-slf4j/api/kotlinx-coroutines-slf4j.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-slf4j.txt rename to integration/kotlinx-coroutines-slf4j/api/kotlinx-coroutines-slf4j.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt rename to kotlinx-coroutines-core/api/kotlinx-coroutines-core.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt b/kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt rename to kotlinx-coroutines-debug/api/kotlinx-coroutines-debug.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-test.txt b/kotlinx-coroutines-test/api/kotlinx-coroutines-test.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-test.txt rename to kotlinx-coroutines-test/api/kotlinx-coroutines-test.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactive.txt b/reactive/kotlinx-coroutines-reactive/api/kotlinx-coroutines-reactive.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactive.txt rename to reactive/kotlinx-coroutines-reactive/api/kotlinx-coroutines-reactive.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt b/reactive/kotlinx-coroutines-reactor/api/kotlinx-coroutines-reactor.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt rename to reactive/kotlinx-coroutines-reactor/api/kotlinx-coroutines-reactor.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt b/reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt rename to reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api diff --git a/settings.gradle b/settings.gradle index e161cfeada..2925355dc1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,8 +18,6 @@ include('benchmarks') include('knit') include('site') -module('binary-compatibility-validator') - include "kotlinx-coroutines-core" module('kotlinx-coroutines-test') diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt b/ui/kotlinx-coroutines-android/api/kotlinx-coroutines-android.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt rename to ui/kotlinx-coroutines-android/api/kotlinx-coroutines-android.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt b/ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt rename to ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt b/ui/kotlinx-coroutines-swing/api/kotlinx-coroutines-swing.api similarity index 100% rename from binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt rename to ui/kotlinx-coroutines-swing/api/kotlinx-coroutines-swing.api From 387d1dde1cb4cd8027e72cca8b81e7caeefcd889 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Mon, 10 Feb 2020 18:42:28 +0300 Subject: [PATCH 22/50] Improve test style Get rid of Hamcrest, which is uncommon in this codebase, and replace as many `assert` statements from other testing frameworks as is reasonable with little automation by calls to `kotlin.test.*`. --- .../test/ListenableFutureTest.kt | 35 ++++++-------- .../test/future/AsFutureTest.kt | 4 +- .../test/future/FutureExceptionsTest.kt | 4 +- .../test/future/FutureTest.kt | 34 +++++++------- .../test/MDCContextTest.kt | 4 +- .../common/test/AbstractCoroutineTest.kt | 6 +-- .../common/test/CompletableDeferredTest.kt | 2 +- .../common/test/WithTimeoutOrNullTest.kt | 10 ++-- .../common/test/channels/ArrayChannelTest.kt | 6 +-- .../common/test/channels/ChannelsTest.kt | 10 ++-- .../test/channels/RendezvousChannelTest.kt | 6 +-- .../operators/FlowContextOptimizationsTest.kt | 6 +-- .../jvm/test/CommonPoolTest.kt | 5 +- .../jvm/test/DelayJvmTest.kt | 11 ++--- .../jvm/test/ExecutorsTest.kt | 4 +- .../jvm/test/WithTimeoutOrNullJvmTest.kt | 2 +- .../WithTimeoutOrNullThreadDispatchTest.kt | 2 +- .../jvm/test/channels/ActorLazyTest.kt | 43 +++++++++-------- .../jvm/test/channels/ActorTest.kt | 37 +++++++-------- .../channels/ChannelAtomicCancelStressTest.kt | 5 +- .../test/channels/ChannelSelectStressTest.kt | 5 +- .../channels/ChannelSendReceiveStressTest.kt | 6 +-- .../jvm/test/channels/ChannelsConsumeTest.kt | 14 +++--- ...nflatedBroadcastChannelNotifyStressTest.kt | 11 ++--- .../test/channels/ProduceConsumeJvmTest.kt | 4 +- .../test/channels/SimpleSendReceiveJvmTest.kt | 10 ++-- .../jvm/test/guide/test/TestUtil.kt | 10 ++-- .../LockFreeLinkedListAtomicLFStressTest.kt | 2 +- .../LockFreeLinkedListShortStressTest.kt | 4 +- .../test/internal/LockFreeLinkedListTest.kt | 4 +- .../jvm/test/internal/SegmentQueueTest.kt | 10 ++-- .../jvm/test/internal/ThreadSafeHeapTest.kt | 6 +-- .../selects/SelectPhilosophersStressTest.kt | 6 +-- .../jvm/test/test/TestCoroutineContextTest.kt | 7 +-- .../test/TestBuildersTest.kt | 4 +- .../tools/MavenPublicationValidator.kt | 1 - .../tools/NpmPublicationValidator.kt | 1 - .../test/IntegrationTest.kt | 47 +++++++++---------- .../test/IterableFlowTckTest.kt | 4 +- .../test/PublishTest.kt | 11 ++--- .../test/PublisherMultiTest.kt | 7 ++- .../test/PublisherSubscriptionSelectTest.kt | 4 +- .../test/ConvertTest.kt | 7 +-- .../test/FluxMultiTest.kt | 3 +- .../test/FluxSingleTest.kt | 3 +- .../test/FluxTest.kt | 7 ++- .../test/MonoTest.kt | 10 ++-- .../test/SchedulerTest.kt | 8 ++-- .../test/CompletableTest.kt | 11 ++--- .../test/ConvertTest.kt | 9 ++-- .../test/FlowAsObservableTest.kt | 7 ++- .../test/FlowableTest.kt | 7 ++- .../test/IntegrationTest.kt | 47 +++++++++---------- .../kotlinx-coroutines-rx2/test/MaybeTest.kt | 10 ++-- .../test/ObservableMultiTest.kt | 5 +- .../test/ObservableSingleTest.kt | 3 +- .../test/ObservableSubscriptionSelectTest.kt | 4 +- .../test/ObservableTest.kt | 7 ++- .../test/SchedulerTest.kt | 8 ++-- .../kotlinx-coroutines-rx2/test/SingleTest.kt | 10 ++-- 60 files changed, 281 insertions(+), 299 deletions(-) diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt index 80cc22a7bb..a9a7f7ba9d 100644 --- a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt +++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt @@ -6,12 +6,11 @@ package kotlinx.coroutines.guava import com.google.common.util.concurrent.* import kotlinx.coroutines.* -import org.hamcrest.core.* import org.junit.* -import org.junit.Assert.* import org.junit.Test import java.util.concurrent.* import java.util.concurrent.CancellationException +import kotlin.test.* class ListenableFutureTest : TestBase() { @Before @@ -27,7 +26,7 @@ class ListenableFutureTest : TestBase() { "O" }).await() + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -64,7 +63,7 @@ class ListenableFutureTest : TestBase() { val future = GlobalScope.future { toAwait.await() + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -75,7 +74,7 @@ class ListenableFutureTest : TestBase() { } assertFalse(future.isDone) toAwait.set("O") - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -86,11 +85,11 @@ class ListenableFutureTest : TestBase() { try { toAwait.await() } catch (e: RuntimeException) { - assertThat(e, IsInstanceOf(IllegalArgumentException::class.java)) + assertTrue(e is IllegalArgumentException) e.message!! } + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -100,13 +99,13 @@ class ListenableFutureTest : TestBase() { try { toAwait.await() } catch (e: RuntimeException) { - assertThat(e, IsInstanceOf(IllegalArgumentException::class.java)) + assertTrue(e is IllegalArgumentException) e.message!! } + "K" } assertFalse(future.isDone) toAwait.setException(IllegalArgumentException("O")) - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -122,8 +121,8 @@ class ListenableFutureTest : TestBase() { future.get() fail("'get' should've throw an exception") } catch (e: ExecutionException) { - assertThat(e.cause, IsInstanceOf(IllegalStateException::class.java)) - assertThat(e.cause!!.message, IsEqual("OK")) + assertTrue(e.cause is IllegalStateException) + assertEquals("OK", e.cause!!.message) } } @@ -134,7 +133,7 @@ class ListenableFutureTest : TestBase() { GlobalScope.future(start = CoroutineStart.LAZY) {} } - assertThat(e.message, IsEqual("LAZY start is not supported")) + assertEquals("LAZY start is not supported", e.message) finish(2) } @@ -147,7 +146,7 @@ class ListenableFutureTest : TestBase() { } expect(3) val future = deferred.asListenableFuture() - assertThat(future.await(), IsEqual("OK")) + assertEquals("OK", future.await()) finish(4) } @@ -160,7 +159,7 @@ class ListenableFutureTest : TestBase() { } expect(2) val future = deferred.asListenableFuture() - assertThat(future.await(), IsEqual("OK")) // await yields main thread to deferred coroutine + assertEquals("OK", future.await()) // await yields main thread to deferred coroutine finish(4) } @@ -370,9 +369,7 @@ class ListenableFutureTest : TestBase() { assertTrue(asFutureAsDeferred.isCompleted) // By documentation, join() shouldn't throw when asDeferred is already complete. asFutureAsDeferred.join() - assertThat( - asFutureAsDeferred.getCompletionExceptionOrNull(), - IsInstanceOf(CancellationException::class.java)) + assertTrue(asFutureAsDeferred.getCompletionExceptionOrNull() is CancellationException) } @Test @@ -395,9 +392,7 @@ class ListenableFutureTest : TestBase() { assertTrue(asDeferred.isCompleted) // By documentation, join() shouldn't throw when asDeferred is already complete. asDeferred.join() - assertThat( - asDeferred.getCompletionExceptionOrNull(), - IsInstanceOf(CancellationException::class.java)) + assertTrue(asDeferred.getCompletionExceptionOrNull() is CancellationException) } @Test diff --git a/integration/kotlinx-coroutines-jdk8/test/future/AsFutureTest.kt b/integration/kotlinx-coroutines-jdk8/test/future/AsFutureTest.kt index 72a1228b95..743816fa85 100644 --- a/integration/kotlinx-coroutines-jdk8/test/future/AsFutureTest.kt +++ b/integration/kotlinx-coroutines-jdk8/test/future/AsFutureTest.kt @@ -5,10 +5,10 @@ package kotlinx.coroutines.future import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.concurrent.* import java.util.concurrent.CancellationException +import kotlin.test.* class AsFutureTest : TestBase() { diff --git a/integration/kotlinx-coroutines-jdk8/test/future/FutureExceptionsTest.kt b/integration/kotlinx-coroutines-jdk8/test/future/FutureExceptionsTest.kt index 86b60e5ff4..0c919b1846 100644 --- a/integration/kotlinx-coroutines-jdk8/test/future/FutureExceptionsTest.kt +++ b/integration/kotlinx-coroutines-jdk8/test/future/FutureExceptionsTest.kt @@ -5,10 +5,10 @@ package kotlinx.coroutines.future import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.io.* import java.util.concurrent.* +import kotlin.test.* class FutureExceptionsTest : TestBase() { diff --git a/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt b/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt index 4649645efb..f75c96746c 100644 --- a/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt +++ b/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt @@ -6,9 +6,8 @@ package kotlinx.coroutines.future import kotlinx.coroutines.* import kotlinx.coroutines.CancellationException -import org.hamcrest.core.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.concurrent.* import java.util.concurrent.atomic.* import java.util.concurrent.locks.* @@ -16,6 +15,7 @@ import java.util.function.* import kotlin.concurrent.* import kotlin.coroutines.* import kotlin.reflect.* +import kotlin.test.* class FutureTest : TestBase() { @Before @@ -30,7 +30,7 @@ class FutureTest : TestBase() { "O" }.await() + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -40,7 +40,7 @@ class FutureTest : TestBase() { val future = GlobalScope.future { toAwait.await() + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -51,7 +51,7 @@ class FutureTest : TestBase() { val future = GlobalScope.future { toAwait.await() + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -62,7 +62,7 @@ class FutureTest : TestBase() { } assertFalse(future.isDone) toAwait.complete("O") - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -74,7 +74,7 @@ class FutureTest : TestBase() { } assertFalse(future.isDone) completable.complete("O") - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -88,7 +88,7 @@ class FutureTest : TestBase() { e.message!! } + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -104,7 +104,7 @@ class FutureTest : TestBase() { e.message!! } + "K" } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -125,7 +125,7 @@ class FutureTest : TestBase() { assertFalse(future.isDone) toAwait.completeExceptionally(TestException("O")) yield() // to future coroutine - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) finish(5) } @@ -142,7 +142,7 @@ class FutureTest : TestBase() { } assertFalse(future.isDone) completable.completeExceptionally(TestException("O")) - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test @@ -158,7 +158,7 @@ class FutureTest : TestBase() { fail("'get' should've throw an exception") } catch (e: ExecutionException) { assertTrue(e.cause is IllegalStateException) - assertThat(e.cause!!.message, IsEqual("OK")) + assertEquals("OK", e.cause!!.message) } } @@ -191,22 +191,22 @@ class FutureTest : TestBase() { it() depth.andDecrement }) { - assertEquals("Part before first suspension must be wrapped", 1, depth.get()) + assertEquals(1, depth.get(), "Part before first suspension must be wrapped") val result = CompletableFuture.supplyAsync { while (depth.get() > 0); - assertEquals("Part inside suspension point should not be wrapped", 0, depth.get()) + assertEquals(0, depth.get(), "Part inside suspension point should not be wrapped") "OK" }.await() - assertEquals("Part after first suspension should be wrapped", 1, depth.get()) + assertEquals(1, depth.get(), "Part after first suspension should be wrapped") CompletableFuture.supplyAsync { while (depth.get() > 0); - assertEquals("Part inside suspension point should not be wrapped", 0, depth.get()) + assertEquals(0, depth.get(), "Part inside suspension point should not be wrapped") "ignored" }.await() result } - assertThat(future.get(), IsEqual("OK")) + assertEquals("OK", future.get()) } @Test diff --git a/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt b/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt index f3ed957bfb..7d18359c5d 100644 --- a/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt +++ b/integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt @@ -28,7 +28,7 @@ class MDCContextTest : TestBase() { MDC.put("myKey", "myValue") // Standalone launch GlobalScope.launch { - assertEquals(null, MDC.get("myKey")) + assertNull(MDC.get("myKey")) expect(2) }.join() finish(3) @@ -92,7 +92,7 @@ class MDCContextTest : TestBase() { @Test fun testContextMayBeEmpty() { runBlocking(MDCContext()) { - assertEquals(null, MDC.get("myKey")) + assertNull(MDC.get("myKey")) } } diff --git a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt index ffde0f9635..ce20837e25 100644 --- a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt +++ b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt @@ -19,7 +19,7 @@ class AbstractCoroutineTest : TestBase() { } override fun onCancelling(cause: Throwable?) { - assertEquals(null, cause) + assertNull(cause) expect(5) } @@ -34,12 +34,12 @@ class AbstractCoroutineTest : TestBase() { } coroutine.invokeOnCompletion(onCancelling = true) { - assertEquals(null, it) + assertNull(it) expect(7) } coroutine.invokeOnCompletion { - assertEquals(null, it) + assertNull(it) expect(8) } expect(2) diff --git a/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt b/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt index f751660756..1f3978d301 100644 --- a/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt +++ b/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt @@ -50,7 +50,7 @@ class CompletableDeferredTest : TestBase() { assertEquals(false, c.isCancelled) assertEquals(true, c.isCompleted) assertTrue(c.getCancellationException() is JobCancellationException) - assertEquals(null, c.getCompletionExceptionOrNull()) + assertNull(c.getCompletionExceptionOrNull()) } private fun checkCancel(c: CompletableDeferred) { diff --git a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt index 5d41efc07c..3faf900cb9 100644 --- a/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt +++ b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt @@ -77,7 +77,7 @@ class WithTimeoutOrNullTest : TestBase() { yield() } } - assertEquals(null, result) + assertNull(result) finish(2) } @@ -135,11 +135,11 @@ class WithTimeoutOrNullTest : TestBase() { yield() } } - assertEquals(null, inner) + assertNull(inner) counter++ } } - assertEquals(null, result) + assertNull(result) check(counter in 1..2) {"Executed: $counter times"} } @@ -167,7 +167,7 @@ class WithTimeoutOrNullTest : TestBase() { expectUnreached() "OK" } - assertEquals(null, result) + assertNull(result) finish(3) } @@ -183,7 +183,7 @@ class WithTimeoutOrNullTest : TestBase() { } "OK" } - assertEquals(null, result) + assertNull(result) finish(4) } diff --git a/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt index ceef21edcb..a57b519f61 100644 --- a/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt @@ -48,7 +48,7 @@ class ArrayChannelTest : TestBase() { assertEquals(42, q.receiveOrNull()) expect(6) check(!q.isEmpty && q.isClosedForSend && q.isClosedForReceive) - assertEquals(null, q.receiveOrNull()) + assertNull(q.receiveOrNull()) expect(7) } expect(2) @@ -94,13 +94,13 @@ class ArrayChannelTest : TestBase() { expect(3) assertEquals(1, q.poll()) expect(4) - assertEquals(null, q.poll()) + assertNull(q.poll()) expect(5) assertEquals(2, q.receive()) // suspends expect(9) assertEquals(3, q.poll()) expect(10) - assertEquals(null, q.poll()) + assertNull(q.poll()) expect(11) } expect(2) diff --git a/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt index 42cc85558b..ba786d53cc 100644 --- a/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt @@ -258,8 +258,8 @@ class ChannelsTest: TestBase() { testList.indices.forEach { i -> assertEquals(testList[i], testList.asReceiveChannel().elementAtOrNull(i)) } - assertEquals(null, testList.asReceiveChannel().elementAtOrNull(-1)) - assertEquals(null, testList.asReceiveChannel().elementAtOrNull(testList.size)) + assertNull(testList.asReceiveChannel().elementAtOrNull(-1)) + assertNull(testList.asReceiveChannel().elementAtOrNull(testList.size)) } @Test @@ -310,14 +310,14 @@ class ChannelsTest: TestBase() { @Test fun testLastOrNull() = runTest { assertEquals(testList.lastOrNull(), testList.asReceiveChannel().lastOrNull()) - assertEquals(null, emptyList().asReceiveChannel().lastOrNull()) + assertNull(emptyList().asReceiveChannel().lastOrNull()) } @Test fun testSingleOrNull() = runTest { assertEquals(1, listOf(1).asReceiveChannel().singleOrNull()) - assertEquals(null, listOf(1, 2).asReceiveChannel().singleOrNull()) - assertEquals(null, emptyList().asReceiveChannel().singleOrNull()) + assertNull(listOf(1, 2).asReceiveChannel().singleOrNull()) + assertNull(emptyList().asReceiveChannel().singleOrNull()) repeat(testList.size + 1) { i -> assertEquals(testList.singleOrNull { it == i }, testList.asReceiveChannel().singleOrNull { it == i }) diff --git a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt index 54d6938481..d036af9395 100644 --- a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt @@ -44,7 +44,7 @@ class RendezvousChannelTest : TestBase() { expect(3) assertEquals(42, q.receiveOrNull()) expect(4) - assertEquals(null, q.receiveOrNull()) + assertNull(q.receiveOrNull()) expect(6) } expect(2) @@ -86,11 +86,11 @@ class RendezvousChannelTest : TestBase() { expect(1) launch { expect(3) - assertEquals(null, q.poll()) + assertNull(q.poll()) expect(4) assertEquals(2, q.receive()) expect(7) - assertEquals(null, q.poll()) + assertNull(q.poll()) yield() expect(9) assertEquals(3, q.poll()) diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt index bf5297408f..7194a70d15 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/FlowContextOptimizationsTest.kt @@ -80,7 +80,7 @@ class FlowContextOptimizationsTest : TestBase() { } .flowOn(CoroutineName("Name")) .collect { value -> - assertEquals(null, currentContext[CoroutineName]?.name) + assertNull(currentContext[CoroutineName]?.name) if (value == 1) expect(2) else expect(4) } @@ -102,8 +102,8 @@ class FlowContextOptimizationsTest : TestBase() { .flowOn(CoroutineName("Name2")) .flowOn(CoroutineName("Name3") + CustomContextElement("OK")) // but this is not lost .collect { value -> - assertEquals(null, currentContext[CoroutineName]?.name) - assertEquals(null, currentContext[CustomContextElement]?.str) + assertNull(currentContext[CoroutineName]?.name) + assertNull(currentContext[CustomContextElement]?.str) if (value == 1) expect(2) else expect(4) } diff --git a/kotlinx-coroutines-core/jvm/test/CommonPoolTest.kt b/kotlinx-coroutines-core/jvm/test/CommonPoolTest.kt index 9af8c28555..8f9f855477 100644 --- a/kotlinx-coroutines-core/jvm/test/CommonPoolTest.kt +++ b/kotlinx-coroutines-core/jvm/test/CommonPoolTest.kt @@ -4,11 +4,10 @@ package kotlinx.coroutines -import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.lang.reflect.* import java.util.concurrent.* +import kotlin.test.* @Suppress("DEPRECATION") class CommonPoolTest { diff --git a/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt b/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt index 642e504967..2906c316ef 100644 --- a/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt @@ -4,11 +4,10 @@ package kotlinx.coroutines -import org.hamcrest.MatcherAssert.* -import org.hamcrest.core.* import org.junit.* import java.util.concurrent.* import kotlin.coroutines.* +import kotlin.test.assertEquals class DelayJvmTest : TestBase() { /** @@ -22,12 +21,12 @@ class DelayJvmTest : TestBase() { } val context = CustomInterceptor(pool) val c = async(context) { - assertThat(Thread.currentThread(), IsEqual(thread)) + assertEquals(thread, Thread.currentThread()) delay(100) - assertThat(Thread.currentThread(), IsEqual(thread)) + assertEquals(thread, Thread.currentThread()) 42 } - assertThat(c.await(), IsEqual(42)) + assertEquals(42, c.await()) pool.shutdown() } @@ -38,7 +37,7 @@ class DelayJvmTest : TestBase() { delay(100) 42 } - assertThat(c.await(), IsEqual(42)) + assertEquals(42, c.await()) } @Test diff --git a/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt index 2cf4361867..033b9b7bc9 100644 --- a/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt +++ b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt @@ -4,10 +4,10 @@ package kotlinx.coroutines -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.concurrent.* import kotlin.coroutines.* +import kotlin.test.* class ExecutorsTest : TestBase() { private fun checkThreadName(prefix: String) { diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt index 5c55bd0aa6..377fcf462e 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt @@ -19,7 +19,7 @@ class WithTimeoutOrNullJvmTest : TestBase() { expectUnreached() // should not be reached, because it is outer timeout } // outer timeout results in null - assertEquals(null, result) + assertNull(result) } @Test diff --git a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt index 5d8c0221a7..ea1ba1a9bb 100644 --- a/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt +++ b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt @@ -74,7 +74,7 @@ class WithTimeoutOrNullThreadDispatchTest : TestBase() { } } assertEquals(thread, Thread.currentThread()) - assertEquals(null, result) + assertNull(result) expect(5) } finish(6) diff --git a/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt index 1ec96ee5ab..ae95e694cd 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt @@ -5,9 +5,8 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class ActorLazyTest : TestBase() { @Test @@ -17,22 +16,22 @@ class ActorLazyTest : TestBase() { expect(5) } actor as Job // type assertion - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertFalse(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(2) yield() // to actor code --> nothing happens (not started!) - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertFalse(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(3) // start actor explicitly actor.start() expect(4) yield() // to started actor - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(true)) - assertThat(actor.isClosedForSend, IsEqual(true)) + assertFalse(actor.isActive) + assertTrue(actor.isCompleted) + assertTrue(actor.isClosedForSend) finish(6) } @@ -41,24 +40,24 @@ class ActorLazyTest : TestBase() { expect(1) val actor = actor(start = CoroutineStart.LAZY) { expect(4) - assertThat(receive(), IsEqual("OK")) + assertEquals("OK", receive()) expect(5) } actor as Job // type assertion - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertFalse(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(2) yield() // to actor code --> nothing happens (not started!) - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertFalse(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(3) // send message to actor --> should start it actor.send("OK") - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(true)) - assertThat(actor.isClosedForSend, IsEqual(true)) + assertFalse(actor.isActive) + assertTrue(actor.isCompleted) + assertTrue(actor.isClosedForSend) finish(6) } diff --git a/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt index 18349dddb6..bdca5039d2 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt @@ -5,12 +5,11 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* import java.io.* +import kotlin.test.* @RunWith(Parameterized::class) class ActorTest(private val capacity: Int) : TestBase() { @@ -28,14 +27,14 @@ class ActorTest(private val capacity: Int) : TestBase() { expect(3) } actor as Job // type assertion - assertThat(actor.isActive, IsEqual(true)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertTrue(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(2) yield() // to actor code - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(true)) - assertThat(actor.isClosedForSend, IsEqual(true)) + assertFalse(actor.isActive) + assertTrue(actor.isCompleted) + assertTrue(actor.isClosedForSend) finish(4) } @@ -44,26 +43,26 @@ class ActorTest(private val capacity: Int) : TestBase() { expect(1) val actor = actor(capacity = capacity) { expect(3) - assertThat(receive(), IsEqual("OK")) + assertEquals("OK", receive()) expect(6) } actor as Job // type assertion - assertThat(actor.isActive, IsEqual(true)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertTrue(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(2) yield() // to actor code - assertThat(actor.isActive, IsEqual(true)) - assertThat(actor.isCompleted, IsEqual(false)) - assertThat(actor.isClosedForSend, IsEqual(false)) + assertTrue(actor.isActive) + assertFalse(actor.isCompleted) + assertFalse(actor.isClosedForSend) expect(4) // send message to actor actor.send("OK") expect(5) yield() // to actor code - assertThat(actor.isActive, IsEqual(false)) - assertThat(actor.isCompleted, IsEqual(true)) - assertThat(actor.isClosedForSend, IsEqual(true)) + assertFalse(actor.isActive) + assertTrue(actor.isCompleted) + assertTrue(actor.isClosedForSend) finish(7) } diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelAtomicCancelStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelAtomicCancelStressTest.kt index 5afac37c9c..6556888a0f 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelAtomicCancelStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelAtomicCancelStressTest.kt @@ -6,12 +6,13 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* import kotlinx.coroutines.selects.* -import org.junit.* -import org.junit.Assert.* +import org.junit.After +import org.junit.Test import org.junit.runner.* import org.junit.runners.* import kotlin.random.Random import java.util.concurrent.atomic.* +import kotlin.test.* /** * Tests cancel atomicity for channel send & receive operations, including their select versions. diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt index c835250e3e..a44ff6cdc6 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSelectStressTest.kt @@ -7,9 +7,10 @@ package kotlinx.coroutines.channels import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlinx.coroutines.selects.* -import org.junit.* -import org.junit.Assert.* +import org.junit.After +import org.junit.Test import java.util.concurrent.atomic.AtomicLongArray +import kotlin.test.* class ChannelSelectStressTest : TestBase() { private val pairedCoroutines = 3 diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt index 1bd6060a8c..5fc87abfd6 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt @@ -6,11 +6,11 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* import kotlinx.coroutines.selects.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* import java.util.concurrent.atomic.* +import kotlin.test.* @RunWith(Parameterized::class) class ChannelSendReceiveStressTest( @@ -101,7 +101,7 @@ class ChannelSendReceiveStressTest( assertEquals(nEvents, sentTotal.get()) if (!kind.isConflated) assertEquals(nEvents, receivedTotal.get()) repeat(nReceivers) { receiveIndex -> - assertTrue("Each receiver should have received something", receivedBy[receiveIndex] > 0) + assertTrue(receivedBy[receiveIndex] > 0, "Each receiver should have received something") } } diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelsConsumeTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelsConsumeTest.kt index d9ef22b10e..cb19b36a13 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelsConsumeTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelsConsumeTest.kt @@ -76,7 +76,7 @@ class ChannelsConsumeTest : TestBase() { assertEquals(4, elementAtOrNull(3)) } checkTerminal { - assertEquals(null, elementAtOrNull(10)) + assertNull(elementAtOrNull(10)) } } @@ -124,7 +124,7 @@ class ChannelsConsumeTest : TestBase() { assertEquals(3, firstOrNull { it % 3 == 0 }) } checkTerminal { - assertEquals(null, firstOrNull { it > 10 }) + assertNull(firstOrNull { it > 10 }) } } @@ -195,7 +195,7 @@ class ChannelsConsumeTest : TestBase() { assertEquals(9, lastOrNull { it % 3 == 0 }) } checkTerminal { - assertEquals(null, lastOrNull { it > 10 }) + assertNull(lastOrNull { it > 10 }) } } @@ -222,7 +222,7 @@ class ChannelsConsumeTest : TestBase() { @Test fun testSingleOrNull() { checkTerminal { - assertEquals(null, singleOrNull()) + assertNull(singleOrNull()) } } @@ -232,10 +232,10 @@ class ChannelsConsumeTest : TestBase() { assertEquals(7, singleOrNull { it % 7 == 0 }) } checkTerminal { - assertEquals(null, singleOrNull { it % 3 == 0 }) + assertNull(singleOrNull { it % 3 == 0 }) } checkTerminal { - assertEquals(null, singleOrNull { it > 10 }) + assertNull(singleOrNull { it > 10 }) } } @@ -898,7 +898,7 @@ class ChannelsConsumeTest : TestBase() { res.cancel() } else { // then check that result is closed - assertEquals(null, res.receiveOrNull(), "Result has unexpected values") + assertNull(res.receiveOrNull(), "Result has unexpected values") } src } diff --git a/kotlinx-coroutines-core/jvm/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt index 4d09e3751e..eb7be57500 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt @@ -5,10 +5,9 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* -import org.hamcrest.MatcherAssert.* -import org.hamcrest.core.* -import org.junit.* +import org.junit.Test import java.util.concurrent.atomic.* +import kotlin.test.* class ConflatedBroadcastChannelNotifyStressTest : TestBase() { private val nSenders = 2 @@ -76,9 +75,9 @@ class ConflatedBroadcastChannelNotifyStressTest : TestBase() { println("Completed successfully ${receiversCompleted.get()} receiver coroutines") println(" Sent ${sentTotal.get()} events") println(" Received ${receivedTotal.get()} events") - assertThat(sendersCompleted.get(), IsEqual(nSenders)) - assertThat(receiversCompleted.get(), IsEqual(nReceivers)) - assertThat(sentTotal.get(), IsEqual(nEvents)) + assertEquals(nSenders, sendersCompleted.get()) + assertEquals(nReceivers, receiversCompleted.get()) + assertEquals(nEvents, sentTotal.get()) } private suspend fun waitForEvent(): Int = diff --git a/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt index 1ae62d811b..61c6635e8a 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt @@ -5,10 +5,10 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* +import kotlin.test.* @RunWith(Parameterized::class) class ProduceConsumeJvmTest( diff --git a/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt index 54023a3e23..07c431bb4d 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt @@ -5,12 +5,10 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* -import kotlin.coroutines.* +import kotlin.test.* @RunWith(Parameterized::class) class SimpleSendReceiveJvmTest( @@ -42,14 +40,14 @@ class SimpleSendReceiveJvmTest( var expected = 0 for (x in channel) { if (!kind.isConflated) { - assertThat(x, IsEqual(expected++)) + assertEquals(expected++, x) } else { assertTrue(x >= expected) expected = x + 1 } } if (!kind.isConflated) { - assertThat(expected, IsEqual(n)) + assertEquals(n, expected) } } } diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt b/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt index bd7159fb08..11fe97e91c 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt @@ -7,9 +7,9 @@ package kotlinx.coroutines.guide.test import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.scheduling.* -import org.junit.Assert.* import java.io.* import java.util.concurrent.* +import kotlin.test.* fun wrapTask(block: Runnable) = kotlinx.coroutines.wrapTask(block) @@ -145,7 +145,7 @@ private fun List.verifyCommonLines(expected: Array, mode: Sa for (i in 0 until n) { val exp = sanitize(expected[i], mode) val act = sanitize(get(i), mode) - assertEquals("Line ${i + 1}", exp, act) + assertEquals(exp, act, "Line ${i + 1}") } } @@ -163,7 +163,7 @@ fun List.verifyLines(vararg expected: String) = verify { fun List.verifyLinesStartWith(vararg expected: String) = verify { verifyCommonLines(expected) - assertTrue("Number of lines", expected.size <= size) + assertTrue(expected.size <= size, "Number of lines") } fun List.verifyLinesArbitraryTime(vararg expected: String) = verify { @@ -197,7 +197,7 @@ fun List.verifyExceptions(vararg expected: String) { for (i in 0 until n) { val exp = sanitize(expected[i], SanitizeMode.FLEXIBLE_THREAD) val act = sanitize(actual[i], SanitizeMode.FLEXIBLE_THREAD) - assertEquals("Line ${i + 1}", exp, act) + assertEquals(exp, act, "Line ${i + 1}") } } @@ -207,7 +207,7 @@ fun List.verifyLinesStart(vararg expected: String) = verify { for (i in 0 until n) { val exp = sanitize(expected[i], SanitizeMode.FLEXIBLE_THREAD) val act = sanitize(get(i), SanitizeMode.FLEXIBLE_THREAD) - assertEquals("Line ${i + 1}", exp, act.substring(0, minOf(act.length, exp.length))) + assertEquals(exp, act.substring(0, minOf(act.length, exp.length)), "Line ${i + 1}") } checkEqualNumberOfLines(expected) } diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt index e5c4c2c898..b967c46a8f 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt @@ -6,11 +6,11 @@ package kotlinx.coroutines.internal import kotlinx.atomicfu.LockFreedomTestEnvironment import kotlinx.coroutines.stressTestMultiplier -import org.junit.Assert.* import org.junit.Test import java.util.* import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicReference +import kotlin.test.* /** * This stress test has 4 threads adding randomly to the list and them immediately undoing diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListShortStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListShortStressTest.kt index 54932ec1d5..2ac51b9b1d 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListShortStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListShortStressTest.kt @@ -5,11 +5,11 @@ package kotlinx.coroutines.internal import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.* import java.util.concurrent.atomic.* import kotlin.concurrent.* +import kotlin.test.* /** * This stress test has 6 threads adding randomly first to the list and them immediately undoing diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListTest.kt index 9de11f792e..b9011448cd 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListTest.kt @@ -4,8 +4,8 @@ package kotlinx.coroutines.internal -import org.junit.Assert.* import org.junit.Test +import kotlin.test.* class LockFreeLinkedListTest { data class IntNode(val i: Int) : LockFreeLinkedListNode() @@ -79,7 +79,7 @@ class LockFreeLinkedListTest { var index = 0 list.forEach { actual[index++] = it.i } assertEquals(n, index) - for (i in 0 until n) assertEquals("item i", expected[i], actual[i]) + for (i in 0 until n) assertEquals(expected[i], actual[i], "item $i") assertEquals(expected.isEmpty(), list.isEmpty) } } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt b/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt index 89cd83dac8..b59a6488a0 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt @@ -7,14 +7,14 @@ import java.util.concurrent.CyclicBarrier import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.thread import kotlin.random.Random -import kotlin.test.assertEquals +import kotlin.test.* class SegmentQueueTest : TestBase() { @Test fun testSimpleTest() { val q = SegmentBasedQueue() assertEquals(1, q.numberOfSegments) - assertEquals(null, q.dequeue()) + assertNull(q.dequeue()) q.enqueue(1) assertEquals(1, q.numberOfSegments) q.enqueue(2) @@ -23,7 +23,7 @@ class SegmentQueueTest : TestBase() { assertEquals(2, q.numberOfSegments) assertEquals(2, q.dequeue()) assertEquals(1, q.numberOfSegments) - assertEquals(null, q.dequeue()) + assertNull(q.dequeue()) } @Test @@ -37,7 +37,7 @@ class SegmentQueueTest : TestBase() { assertEquals(2, q.numberOfSegments) assertEquals(1, q.dequeue()) assertEquals(3, q.dequeue()) - assertEquals(null, q.dequeue()) + assertNull(q.dequeue()) } @Test @@ -49,7 +49,7 @@ class SegmentQueueTest : TestBase() { q.enqueue(3) s.removeSegment() assertEquals(3, q.dequeue()) - assertEquals(null, q.dequeue()) + assertNull(q.dequeue()) } @Test diff --git a/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt index 12b3540547..be7ed91a3f 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt @@ -21,7 +21,7 @@ class ThreadSafeHeapTest : TestBase() { @Test fun testBasic() { val h = ThreadSafeHeap() - assertEquals(null, h.peek()) + assertNull(h.peek()) val n1 = Node(1) h.addLast(n1) assertEquals(n1, h.peek()) @@ -47,7 +47,7 @@ class ThreadSafeHeapTest : TestBase() { h.remove(n3) assertEquals(n5, h.peek()) h.remove(n5) - assertEquals(null, h.peek()) + assertNull(h.peek()) } @Test @@ -59,7 +59,7 @@ class ThreadSafeHeapTest : TestBase() { repeat(n) { h.addLast(Node(a[it])) } a.sort() repeat(n) { assertEquals(Node(a[it]), h.removeFirstOrNull()) } - assertEquals(null, h.peek()) + assertNull(h.peek()) } @Test diff --git a/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt index eaff30c16d..22179f34ad 100644 --- a/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt @@ -6,8 +6,8 @@ package kotlinx.coroutines.selects import kotlinx.coroutines.* import kotlinx.coroutines.sync.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class SelectPhilosophersStressTest : TestBase() { private val TEST_DURATION = 3000L * stressTestMultiplier @@ -59,7 +59,7 @@ class SelectPhilosophersStressTest : TestBase() { val eats = withTimeout(5 * TEST_DURATION) { philosophers.map { it.await() } } debugJob.cancel() eats.withIndex().forEach { (id, eats) -> - assertTrue("$id shall not starve", eats > 0) + assertTrue(eats > 0, "$id shall not starve") } } } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/test/TestCoroutineContextTest.kt b/kotlinx-coroutines-core/jvm/test/test/TestCoroutineContextTest.kt index 25b909148d..4a6f4d24df 100644 --- a/kotlinx-coroutines-core/jvm/test/test/TestCoroutineContextTest.kt +++ b/kotlinx-coroutines-core/jvm/test/test/TestCoroutineContextTest.kt @@ -6,8 +6,9 @@ package kotlinx.coroutines.test import kotlinx.coroutines.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import kotlin.coroutines.* +import kotlin.test.* class TestCoroutineContextTest { private val injectedContext = TestCoroutineContext() @@ -309,7 +310,7 @@ class TestCoroutineContextTest { advanceTimeBy(delay) val e = result.getCompletionExceptionOrNull() - assertTrue("Expected to be thrown: '$expectedError' but was '$e'", expectedError === e) + assertTrue(expectedError === e, "Expected to be thrown: '$expectedError' but was '$e'") } @Test @@ -341,7 +342,7 @@ class TestCoroutineContextTest { } catch (e: AssertionError) { throw e } catch (e: Throwable) { - assertTrue("Expected to be thrown: '$expectedError' but was '$e'", expectedError === e) + assertTrue(expectedError === e, "Expected to be thrown: '$expectedError' but was '$e'") } } diff --git a/kotlinx-coroutines-test/test/TestBuildersTest.kt b/kotlinx-coroutines-test/test/TestBuildersTest.kt index 1f163eeff1..27c8f5fb19 100644 --- a/kotlinx-coroutines-test/test/TestBuildersTest.kt +++ b/kotlinx-coroutines-test/test/TestBuildersTest.kt @@ -5,9 +5,9 @@ package kotlinx.coroutines.test import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import kotlin.coroutines.* +import kotlin.test.* class TestBuildersTest { diff --git a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt index b7f97f033e..0fe44672f4 100644 --- a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt +++ b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt @@ -5,7 +5,6 @@ package kotlinx.coroutines.validator import org.junit.* -import org.junit.Assert.* import java.io.* import java.util.jar.* diff --git a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt index 2c2351f754..a50bd14d86 100644 --- a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt +++ b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt @@ -7,7 +7,6 @@ package kotlinx.coroutines.validator import com.google.gson.* import org.apache.commons.compress.archivers.tar.* import org.junit.* -import org.junit.Assert.* import java.io.* import java.util.zip.* diff --git a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt index aaeaa009b3..3ec0b93481 100644 --- a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt @@ -5,13 +5,12 @@ package kotlinx.coroutines.reactive import kotlinx.coroutines.* -import org.hamcrest.MatcherAssert.* -import org.hamcrest.core.* -import org.junit.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* import org.reactivestreams.* import kotlin.coroutines.* +import kotlin.test.* @RunWith(Parameterized::class) class IntegrationTest( @@ -44,14 +43,14 @@ class IntegrationTest( // does not send anything } assertNSE { pub.awaitFirst() } - assertThat(pub.awaitFirstOrDefault("OK"), IsEqual("OK")) - assertThat(pub.awaitFirstOrNull(), IsNull()) - assertThat(pub.awaitFirstOrElse { "ELSE" }, IsEqual("ELSE")) + assertEquals("OK", pub.awaitFirstOrDefault("OK")) + assertNull(pub.awaitFirstOrNull()) + assertEquals("ELSE", pub.awaitFirstOrElse { "ELSE" }) assertNSE { pub.awaitLast() } assertNSE { pub.awaitSingle() } var cnt = 0 pub.collect { cnt++ } - assertThat(cnt, IsEqual(0)) + assertEquals(0, cnt) } @Test @@ -60,18 +59,18 @@ class IntegrationTest( if (delay) delay(1) send("OK") } - assertThat(pub.awaitFirst(), IsEqual("OK")) - assertThat(pub.awaitFirstOrDefault("!"), IsEqual("OK")) - assertThat(pub.awaitFirstOrNull(), IsEqual("OK")) - assertThat(pub.awaitFirstOrElse { "ELSE" }, IsEqual("OK")) - assertThat(pub.awaitLast(), IsEqual("OK")) - assertThat(pub.awaitSingle(), IsEqual("OK")) + assertEquals("OK", pub.awaitFirst()) + assertEquals("OK", pub.awaitFirstOrDefault("!")) + assertEquals("OK", pub.awaitFirstOrNull()) + assertEquals("OK", pub.awaitFirstOrElse { "ELSE" }) + assertEquals("OK", pub.awaitLast()) + assertEquals("OK", pub.awaitSingle()) var cnt = 0 pub.collect { - assertThat(it, IsEqual("OK")) + assertEquals("OK", it) cnt++ } - assertThat(cnt, IsEqual(1)) + assertEquals(1, cnt) } @Test @@ -83,11 +82,11 @@ class IntegrationTest( if (delay) delay(1) } } - assertThat(pub.awaitFirst(), IsEqual(1)) - assertThat(pub.awaitFirstOrDefault(0), IsEqual(1)) - assertThat(pub.awaitLast(), IsEqual(n)) - assertThat(pub.awaitFirstOrNull(), IsEqual(1)) - assertThat(pub.awaitFirstOrElse { 0 }, IsEqual(1)) + assertEquals(1, pub.awaitFirst()) + assertEquals(1, pub.awaitFirstOrDefault(0)) + assertEquals(n, pub.awaitLast()) + assertEquals(1, pub.awaitFirstOrNull()) + assertEquals(1, pub.awaitFirstOrElse { 0 }) assertIAE { pub.awaitSingle() } checkNumbers(n, pub) val channel = pub.openSubscription() @@ -125,9 +124,9 @@ class IntegrationTest( private suspend fun checkNumbers(n: Int, pub: Publisher) { var last = 0 pub.collect { - assertThat(it, IsEqual(++last)) + assertEquals(++last, it) } - assertThat(last, IsEqual(n)) + assertEquals(n, last) } private inline fun assertIAE(block: () -> Unit) { @@ -135,7 +134,7 @@ class IntegrationTest( block() expectUnreached() } catch (e: Throwable) { - assertThat(e, IsInstanceOf(IllegalArgumentException::class.java)) + assertTrue(e is IllegalArgumentException) } } @@ -144,7 +143,7 @@ class IntegrationTest( block() expectUnreached() } catch (e: Throwable) { - assertThat(e, IsInstanceOf(NoSuchElementException::class.java)) + assertTrue(e is NoSuchElementException) } } } \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt b/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt index 5dfd9d537d..906b2579d7 100644 --- a/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/IterableFlowTckTest.kt @@ -8,16 +8,18 @@ package kotlinx.coroutines.reactive import kotlinx.coroutines.flow.* import org.junit.* +import org.junit.Ignore +import org.junit.Test import org.reactivestreams.* import org.reactivestreams.tck.* -import org.junit.Assert.* import org.reactivestreams.Subscription import org.reactivestreams.Subscriber import java.util.ArrayList import java.util.concurrent.* import java.util.concurrent.CountDownLatch import java.util.concurrent.ForkJoinPool.commonPool +import kotlin.test.* class IterableFlowTckTest : PublisherVerification(TestEnvironment()) { diff --git a/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt index 4ffa0746ca..9e3c07b6b7 100644 --- a/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/PublishTest.kt @@ -5,10 +5,9 @@ package kotlinx.coroutines.reactive import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.reactivestreams.* +import kotlin.test.* class PublishTest : TestBase() { @Test @@ -45,7 +44,7 @@ class PublishTest : TestBase() { } override fun onNext(t: Int) { expect(6) - assertThat(t, IsEqual(42)) + assertEquals(42, t) } override fun onComplete() { expect(8) } override fun onError(t: Throwable?) { expectUnreached() } @@ -72,8 +71,8 @@ class PublishTest : TestBase() { override fun onComplete() { expectUnreached() } override fun onError(t: Throwable) { expect(6) - assertThat(t, IsInstanceOf(RuntimeException::class.java)) - assertThat(t.message, IsEqual("OK")) + assertTrue(t is RuntimeException) + assertEquals("OK", t.message) } }) expect(4) diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt index e238d396a8..e3b1d3b384 100644 --- a/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/PublisherMultiTest.kt @@ -5,9 +5,8 @@ package kotlinx.coroutines.reactive import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class PublisherMultiTest : TestBase() { @Test @@ -27,6 +26,6 @@ class PublisherMultiTest : TestBase() { observable.collect { assertTrue(resultSet.add(it)) } - assertThat(resultSet.size, IsEqual(n)) + assertEquals(n, resultSet.size) } } diff --git a/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt index ef1784776d..110718ac55 100644 --- a/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/PublisherSubscriptionSelectTest.kt @@ -6,10 +6,10 @@ package kotlinx.coroutines.reactive import kotlinx.coroutines.* import kotlinx.coroutines.selects.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* +import kotlin.test.* @RunWith(Parameterized::class) class PublisherSubscriptionSelectTest(private val request: Int) : TestBase() { diff --git a/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt b/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt index 10e05b7658..82664a2dee 100644 --- a/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/ConvertTest.kt @@ -8,7 +8,8 @@ import kotlinx.coroutines.* import kotlinx.coroutines.channels.* import kotlinx.coroutines.reactive.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class ConvertTest : TestBase() { @Test @@ -66,9 +67,9 @@ class ConvertTest : TestBase() { null } val mono1 = d.asMono(Dispatchers.Unconfined) - checkMonoValue(mono1, ::assertNull) + checkMonoValue(mono1, Assert::assertNull) val mono2 = d.asMono(Dispatchers.Unconfined) - checkMonoValue(mono2, ::assertNull) + checkMonoValue(mono2, Assert::assertNull) } @Test diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt index 7203120dae..0d5f9e2c18 100644 --- a/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/FluxMultiTest.kt @@ -7,9 +7,10 @@ package kotlinx.coroutines.reactor import kotlinx.coroutines.* import kotlinx.coroutines.reactive.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import reactor.core.publisher.* import java.io.* +import kotlin.test.* class FluxMultiTest : TestBase() { @Test diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt index a3e9658930..3879c62c71 100644 --- a/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/FluxSingleTest.kt @@ -7,9 +7,10 @@ package kotlinx.coroutines.reactor import kotlinx.coroutines.* import kotlinx.coroutines.reactive.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import reactor.core.publisher.* import java.time.Duration.* +import kotlin.test.* class FluxSingleTest : TestBase() { diff --git a/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt b/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt index 2562c9d3db..31f5f5d979 100644 --- a/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/FluxTest.kt @@ -7,7 +7,6 @@ package kotlinx.coroutines.reactor import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.reactive.* -import org.hamcrest.core.* import org.junit.* import org.junit.Test import kotlin.test.* @@ -23,7 +22,7 @@ class FluxTest : TestBase() { expect(2) flux.subscribe { value -> expect(5) - Assert.assertThat(value, IsEqual("OK")) + assertEquals("OK", value) } expect(3) yield() // to started coroutine @@ -42,8 +41,8 @@ class FluxTest : TestBase() { expectUnreached() }, { error -> expect(5) - Assert.assertThat(error, IsInstanceOf(RuntimeException::class.java)) - Assert.assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to started coroutine diff --git a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt index 223ba7be5d..551988b814 100644 --- a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt @@ -7,15 +7,15 @@ package kotlinx.coroutines.reactor import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.reactive.* -import org.hamcrest.core.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import org.reactivestreams.* import reactor.core.publisher.* import reactor.util.context.* import java.time.* import java.time.Duration.* import java.util.function.* +import kotlin.test.* class MonoTest : TestBase() { @Before @@ -33,7 +33,7 @@ class MonoTest : TestBase() { expect(2) mono.subscribe { value -> expect(5) - assertThat(value, IsEqual("OK")) + assertEquals("OK", value) } expect(3) yield() // to started coroutine @@ -52,8 +52,8 @@ class MonoTest : TestBase() { expectUnreached() }, { error -> expect(5) - assertThat(error, IsInstanceOf(RuntimeException::class.java)) - assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to started coroutine diff --git a/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt b/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt index 8bc72c2f1f..bed607c9ed 100644 --- a/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/SchedulerTest.kt @@ -5,12 +5,10 @@ package kotlinx.coroutines.reactor import kotlinx.coroutines.* -import org.hamcrest.core.IsEqual -import org.hamcrest.core.IsNot -import org.junit.Assert.assertThat import org.junit.Before import org.junit.Test import reactor.core.scheduler.Schedulers +import kotlin.test.* class SchedulerTest : TestBase() { @Before @@ -24,11 +22,11 @@ class SchedulerTest : TestBase() { val mainThread = Thread.currentThread() withContext(Schedulers.single().asCoroutineDispatcher()) { val t1 = Thread.currentThread() - assertThat(t1, IsNot(IsEqual(mainThread))) + assertNotSame(t1, mainThread) expect(2) delay(100) val t2 = Thread.currentThread() - assertThat(t2, IsNot(IsEqual(mainThread))) + assertNotSame(t2, mainThread) expect(3) } finish(4) diff --git a/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt b/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt index 04e869758c..298b32bf32 100644 --- a/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt @@ -8,9 +8,8 @@ import io.reactivex.* import io.reactivex.disposables.* import io.reactivex.exceptions.* import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class CompletableTest : TestBase() { @Test @@ -40,8 +39,8 @@ class CompletableTest : TestBase() { expectUnreached() }, { error -> expect(5) - assertThat(error, IsInstanceOf(RuntimeException::class.java)) - assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to completable coroutine @@ -95,7 +94,7 @@ class CompletableTest : TestBase() { expectUnreached() } catch (e: RuntimeException) { finish(4) - assertThat(e.message, IsEqual("OK")) + assertEquals("OK", e.message) } } diff --git a/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt b/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt index 758b632604..a43366555e 100644 --- a/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/ConvertTest.kt @@ -6,8 +6,9 @@ package kotlinx.coroutines.rx2 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Assert +import org.junit.Test +import kotlin.test.* class ConvertTest : TestBase() { @Test @@ -64,9 +65,9 @@ class ConvertTest : TestBase() { null } val maybe1 = d.asMaybe(Dispatchers.Unconfined) - checkMaybeValue(maybe1, ::assertNull) + checkMaybeValue(maybe1, Assert::assertNull) val maybe2 = d.asMaybe(Dispatchers.Unconfined) - checkMaybeValue(maybe2, ::assertNull) + checkMaybeValue(maybe2, Assert::assertNull) } @Test diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt index ab9e402893..0908b34cf2 100644 --- a/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/FlowAsObservableTest.kt @@ -6,9 +6,8 @@ package kotlinx.coroutines.rx2 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import org.hamcrest.core.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class FlowAsObservableTest : TestBase() { @Test @@ -39,7 +38,7 @@ class FlowAsObservableTest : TestBase() { expect(2) observable.subscribe({ expectUnreached() }, { error -> expect(4) - assertThat(error, IsInstanceOf(RuntimeException::class.java)) + assertTrue(error is RuntimeException) assertEquals("OK", error.message) }) finish(5) diff --git a/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt b/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt index aebf9993cc..148d1f9999 100644 --- a/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/FlowableTest.kt @@ -6,7 +6,6 @@ package kotlinx.coroutines.rx2 import kotlinx.coroutines.* import kotlinx.coroutines.reactive.* -import org.hamcrest.core.* import org.junit.* import org.junit.Test import kotlin.test.* @@ -22,7 +21,7 @@ class FlowableTest : TestBase() { expect(2) observable.subscribe { value -> expect(5) - Assert.assertThat(value, IsEqual("OK")) + assertEquals("OK", value) } expect(3) yield() // to started coroutine @@ -41,8 +40,8 @@ class FlowableTest : TestBase() { expectUnreached() }, { error -> expect(5) - Assert.assertThat(error, IsInstanceOf(RuntimeException::class.java)) - Assert.assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to started coroutine diff --git a/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt index ca7c0ca5ce..4faebbd251 100644 --- a/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/IntegrationTest.kt @@ -6,12 +6,11 @@ package kotlinx.coroutines.rx2 import io.reactivex.* import kotlinx.coroutines.* -import org.hamcrest.MatcherAssert.* -import org.hamcrest.core.* -import org.junit.* +import org.junit.Test import org.junit.runner.* import org.junit.runners.* import kotlin.coroutines.* +import kotlin.test.* @RunWith(Parameterized::class) class IntegrationTest( @@ -44,16 +43,16 @@ class IntegrationTest( // does not send anything } assertNSE { observable.awaitFirst() } - assertThat(observable.awaitFirstOrDefault("OK"), IsEqual("OK")) - assertThat(observable.awaitFirstOrNull(), IsNull()) - assertThat(observable.awaitFirstOrElse { "ELSE" }, IsEqual("ELSE")) + assertEquals("OK", observable.awaitFirstOrDefault("OK")) + assertNull(observable.awaitFirstOrNull()) + assertEquals("ELSE", observable.awaitFirstOrElse { "ELSE" }) assertNSE { observable.awaitLast() } assertNSE { observable.awaitSingle() } var cnt = 0 observable.collect { cnt++ } - assertThat(cnt, IsEqual(0)) + assertEquals(0, cnt) } @Test @@ -62,18 +61,18 @@ class IntegrationTest( if (delay) delay(1) send("OK") } - assertThat(observable.awaitFirst(), IsEqual("OK")) - assertThat(observable.awaitFirstOrDefault("OK"), IsEqual("OK")) - assertThat(observable.awaitFirstOrNull(), IsEqual("OK")) - assertThat(observable.awaitFirstOrElse { "ELSE" }, IsEqual("OK")) - assertThat(observable.awaitLast(), IsEqual("OK")) - assertThat(observable.awaitSingle(), IsEqual("OK")) + assertEquals("OK", observable.awaitFirst()) + assertEquals("OK", observable.awaitFirstOrDefault("OK")) + assertEquals("OK", observable.awaitFirstOrNull()) + assertEquals("OK", observable.awaitFirstOrElse { "ELSE" }) + assertEquals("OK", observable.awaitLast()) + assertEquals("OK", observable.awaitSingle()) var cnt = 0 observable.collect { - assertThat(it, IsEqual("OK")) + assertEquals("OK", it) cnt++ } - assertThat(cnt, IsEqual(1)) + assertEquals(1, cnt) } @Test @@ -85,11 +84,11 @@ class IntegrationTest( if (delay) delay(1) } } - assertThat(observable.awaitFirst(), IsEqual(1)) - assertThat(observable.awaitFirstOrDefault(0), IsEqual(1)) - assertThat(observable.awaitFirstOrNull(), IsEqual(1)) - assertThat(observable.awaitFirstOrElse { 0 }, IsEqual(1)) - assertThat(observable.awaitLast(), IsEqual(n)) + assertEquals(1, observable.awaitFirst()) + assertEquals(1, observable.awaitFirstOrDefault(0)) + assertEquals(1, observable.awaitFirstOrNull()) + assertEquals(1, observable.awaitFirstOrElse { 0 }) + assertEquals(n, observable.awaitLast()) assertIAE { observable.awaitSingle() } checkNumbers(n, observable) val channel = observable.openSubscription() @@ -127,9 +126,9 @@ class IntegrationTest( private suspend fun checkNumbers(n: Int, observable: Observable) { var last = 0 observable.collect { - assertThat(it, IsEqual(++last)) + assertEquals(++last, it) } - assertThat(last, IsEqual(n)) + assertEquals(n, last) } @@ -138,7 +137,7 @@ class IntegrationTest( block() expectUnreached() } catch (e: Throwable) { - assertThat(e, IsInstanceOf(IllegalArgumentException::class.java)) + assertTrue(e is IllegalArgumentException) } } @@ -147,7 +146,7 @@ class IntegrationTest( block() expectUnreached() } catch (e: Throwable) { - assertThat(e, IsInstanceOf(NoSuchElementException::class.java)) + assertTrue(e is NoSuchElementException) } } } \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt b/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt index deca961e6d..08427dcf3d 100644 --- a/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt @@ -10,11 +10,11 @@ import io.reactivex.exceptions.* import io.reactivex.functions.* import io.reactivex.internal.functions.Functions.* import kotlinx.coroutines.* -import org.hamcrest.core.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.concurrent.* import java.util.concurrent.CancellationException +import kotlin.test.* class MaybeTest : TestBase() { @Before @@ -32,7 +32,7 @@ class MaybeTest : TestBase() { expect(2) maybe.subscribe { value -> expect(5) - assertThat(value, IsEqual("OK")) + assertEquals("OK", value) } expect(3) yield() // to started coroutine @@ -67,8 +67,8 @@ class MaybeTest : TestBase() { expectUnreached() }, { error -> expect(5) - assertThat(error, IsInstanceOf(RuntimeException::class.java)) - assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to started coroutine diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt index 6971918723..074fcf4900 100644 --- a/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/ObservableMultiTest.kt @@ -6,10 +6,9 @@ package kotlinx.coroutines.rx2 import io.reactivex.* import kotlinx.coroutines.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.io.* -import kotlin.experimental.* +import kotlin.test.* /** * Test emitting multiple values with [rxObservable]. diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt index 7604b4ac26..4454190f8f 100644 --- a/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/ObservableSingleTest.kt @@ -7,8 +7,9 @@ package kotlinx.coroutines.rx2 import io.reactivex.* import kotlinx.coroutines.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.concurrent.* +import kotlin.test.* class ObservableSingleTest : TestBase() { @Before diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt index 28eb8074f9..3cd3bbffff 100644 --- a/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/ObservableSubscriptionSelectTest.kt @@ -6,8 +6,8 @@ package kotlinx.coroutines.rx2 import kotlinx.coroutines.* import kotlinx.coroutines.selects.* -import org.junit.* -import org.junit.Assert.* +import org.junit.Test +import kotlin.test.* class ObservableSubscriptionSelectTest : TestBase() { @Test diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt index b9f6fe35a6..4f7fa547d2 100644 --- a/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/ObservableTest.kt @@ -8,7 +8,6 @@ import io.reactivex.* import io.reactivex.plugins.* import kotlinx.coroutines.* import kotlinx.coroutines.CancellationException -import org.hamcrest.core.* import org.junit.* import org.junit.Test import java.util.concurrent.* @@ -30,7 +29,7 @@ class ObservableTest : TestBase() { expect(2) observable.subscribe { value -> expect(5) - Assert.assertThat(value, IsEqual("OK")) + assertEquals("OK", value) } expect(3) yield() // to started coroutine @@ -49,8 +48,8 @@ class ObservableTest : TestBase() { expectUnreached() }, { error -> expect(5) - Assert.assertThat(error, IsInstanceOf(RuntimeException::class.java)) - Assert.assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to started coroutine diff --git a/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt b/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt index ca98b45d48..26dbe8f4cf 100644 --- a/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/SchedulerTest.kt @@ -6,11 +6,9 @@ package kotlinx.coroutines.rx2 import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.* -import org.hamcrest.core.IsEqual -import org.hamcrest.core.IsNot -import org.junit.Assert.assertThat import org.junit.Before import org.junit.Test +import kotlin.test.* class SchedulerTest : TestBase() { @Before @@ -24,11 +22,11 @@ class SchedulerTest : TestBase() { val mainThread = Thread.currentThread() withContext(Schedulers.io().asCoroutineDispatcher()) { val t1 = Thread.currentThread() - assertThat(t1, IsNot(IsEqual(mainThread))) + assertNotSame(t1, mainThread) expect(2) delay(100) val t2 = Thread.currentThread() - assertThat(t2, IsNot(IsEqual(mainThread))) + assertNotSame(t2, mainThread) expect(3) } finish(4) diff --git a/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt b/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt index d9581f86f9..c66188a183 100644 --- a/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt @@ -9,10 +9,10 @@ import io.reactivex.disposables.* import io.reactivex.exceptions.* import io.reactivex.functions.* import kotlinx.coroutines.* -import org.hamcrest.core.* import org.junit.* -import org.junit.Assert.* +import org.junit.Test import java.util.concurrent.* +import kotlin.test.* class SingleTest : TestBase() { @Before @@ -30,7 +30,7 @@ class SingleTest : TestBase() { expect(2) single.subscribe { value -> expect(5) - assertThat(value, IsEqual("OK")) + assertEquals("OK", value) } expect(3) yield() // to started coroutine @@ -49,8 +49,8 @@ class SingleTest : TestBase() { expectUnreached() }, { error -> expect(5) - assertThat(error, IsInstanceOf(RuntimeException::class.java)) - assertThat(error.message, IsEqual("OK")) + assertTrue(error is RuntimeException) + assertEquals("OK", error.message) }) expect(3) yield() // to started coroutine From 91e4d770dfe98e0b50d8e01c22d262e442590913 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Tue, 11 Feb 2020 18:29:19 +0300 Subject: [PATCH 23/50] Fix failing publication validation --- .../kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt | 1 + .../kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt | 1 + 2 files changed, 2 insertions(+) diff --git a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt index 0fe44672f4..53fd65d31f 100644 --- a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt +++ b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/MavenPublicationValidator.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.validator import org.junit.* +import org.junit.Assert.assertTrue import java.io.* import java.util.jar.* diff --git a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt index a50bd14d86..052d745bb8 100644 --- a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt +++ b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt @@ -9,6 +9,7 @@ import org.apache.commons.compress.archivers.tar.* import org.junit.* import java.io.* import java.util.zip.* +import org.junit.Assert.* class NpmPublicationValidator { private val VERSION = System.getenv("DeployVersion") From 90a9faf2fb121aec46891a5e03944970bf7cab71 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 12 Feb 2020 16:38:26 +0300 Subject: [PATCH 24/50] Update module name for kotlinx-coroutines-core-common artifact Fixes #1797 --- kotlinx-coroutines-core/build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index 6fedd7c016..d4b2b8974b 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -46,6 +46,14 @@ configurations { configureKotlinJvmPlatform(kotlinCompilerPluginClasspath) } +// Update module name for metadata artifact to avoid conflicts +// see https://github.com/Kotlin/kotlinx.coroutines/issues/1797 +compileKotlinMetadata { + kotlinOptions { + freeCompilerArgs += ["-module-name", "kotlinx-coroutines-core-common"] + } +} + kotlin.sourceSets { jvmTest.dependencies { api "org.jetbrains.kotlinx:lincheck:$lincheck_version" From 0126dba9d288fcf69cf86a74bf5060d064d9ee5d Mon Sep 17 00:00:00 2001 From: SokolovaMaria Date: Tue, 26 Nov 2019 01:04:07 +0300 Subject: [PATCH 25/50] ConflatedChannel with lock to protect the one-element buffer, double-linked list used for suspending receivers only. --- kotlinx-coroutines-core/build.gradle | 2 +- .../common/src/channels/ConflatedChannel.kt | 164 +++++++++++------- .../jvm/test/channels/ChannelLFStressTest.kt | 8 - .../linearizability/ChannelsLCStressTest.kt | 6 +- 4 files changed, 106 insertions(+), 74 deletions(-) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index d4b2b8974b..832321493a 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -107,7 +107,7 @@ task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) { testClassesDirs = files { jvmTest.testClassesDirs } executable = "$System.env.JDK_16/bin/java" exclude '**/*LFStressTest.*' // lock-freedom tests use LockFreedomTestEnvironment which needs JDK8 - exclude '**/*LCStressTest.*' // lic-check tests use LinChecker which needs JDK8 + exclude '**/*LCStressTest.*' // lin-check tests use LinChecker which needs JDK8 exclude '**/exceptions/**' // exceptions tests check suppressed exception which needs JDK8 exclude '**/ExceptionsGuideTest.*' } diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt index c04ccc4c39..ed0f3705a7 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt @@ -1,11 +1,9 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - package kotlinx.coroutines.channels -import kotlinx.coroutines.selects.* +import kotlinx.coroutines.* import kotlinx.coroutines.internal.* +import kotlinx.coroutines.selects.* +import kotlin.native.concurrent.SharedImmutable /** * Channel that buffers at most one element and conflates all subsequent `send` and `offer` invocations, @@ -15,80 +13,124 @@ import kotlinx.coroutines.internal.* * Sender to this channel never suspends and [offer] always returns `true`. * * This channel is created by `Channel(Channel.CONFLATED)` factory function invocation. - * - * This implementation is fully lock-free. */ internal open class ConflatedChannel : AbstractChannel() { - protected final override val isBufferAlwaysEmpty: Boolean get() = true - protected final override val isBufferEmpty: Boolean get() = true + protected final override val isBufferAlwaysEmpty: Boolean get() = false + protected final override val isBufferEmpty: Boolean get() = value === EMPTY protected final override val isBufferAlwaysFull: Boolean get() = false protected final override val isBufferFull: Boolean get() = false - override fun onClosedIdempotent(closed: LockFreeLinkedListNode) { - @Suppress("UNCHECKED_CAST") - (closed.prevNode as? SendBuffered)?.let { lastBuffered -> - conflatePreviousSendBuffered(lastBuffered) - } - } + override val isEmpty: Boolean get() = lock.withLock { isEmptyImpl } - /** - * Queues conflated element, returns null on success or - * returns node reference if it was already closed or is waiting for receive. - */ - private fun sendConflated(element: E): ReceiveOrClosed<*>? { - val node = SendBuffered(element) - queue.addLastIfPrev(node) { prev -> - if (prev is ReceiveOrClosed<*>) return@sendConflated prev - true - } - conflatePreviousSendBuffered(node) - return null + private val lock = ReentrantLock() + + private var value: Any? = EMPTY + + private companion object { + @SharedImmutable + private val EMPTY = Symbol("EMPTY") } - private fun conflatePreviousSendBuffered(node: SendBuffered) { - // Conflate all previous SendBuffered, helping other sends to conflate - var prev = node.prevNode - while (prev is SendBuffered<*>) { - if (!prev.remove()) { - prev.helpRemove() + // result is `OFFER_SUCCESS | Closed` + protected override fun offerInternal(element: E): Any { + var receive: ReceiveOrClosed? = null + lock.withLock { + closedForSend?.let { return it } + // if there is no element written in buffer + if (value === EMPTY) { + // check for receivers that were waiting on the empty buffer + loop@ while(true) { + receive = takeFirstReceiveOrPeekClosed() ?: break@loop // break when no receivers queued + if (receive is Closed) { + return receive!! + } + val token = receive!!.tryResumeReceive(element, null) + if (token != null) { + assert { token === RESUME_TOKEN } + return@withLock + } + } } - prev = prev.prevNode + value = element + return OFFER_SUCCESS } + // breaks here if offer meets receiver + receive!!.completeResumeReceive(element) + return receive!!.offerResult } - // result is always `OFFER_SUCCESS | Closed` - protected override fun offerInternal(element: E): Any { - while (true) { - val result = super.offerInternal(element) - when { - result === OFFER_SUCCESS -> return OFFER_SUCCESS - result === OFFER_FAILED -> { // try to buffer - when (val sendResult = sendConflated(element)) { - null -> return OFFER_SUCCESS - is Closed<*> -> return sendResult + // result is `ALREADY_SELECTED | OFFER_SUCCESS | Closed` + protected override fun offerSelectInternal(element: E, select: SelectInstance<*>): Any { + var receive: ReceiveOrClosed? = null + lock.withLock { + closedForSend?.let { return it } + if (value === EMPTY) { + loop@ while(true) { + val offerOp = describeTryOffer(element) + val failure = select.performAtomicTrySelect(offerOp) + when { + failure == null -> { // offered successfully + receive = offerOp.result + return@withLock + } + failure === OFFER_FAILED -> break@loop // cannot offer -> Ok to queue to buffer + failure === RETRY_ATOMIC -> {} // retry + failure === ALREADY_SELECTED || failure is Closed<*> -> return failure + else -> error("performAtomicTrySelect(describeTryOffer) returned $failure") } - // otherwise there was receiver in queue, retry super.offerInternal } - result is Closed<*> -> return result - else -> error("Invalid offerInternal result $result") } + // try to select sending this element to buffer + if (!select.trySelect()) { + return ALREADY_SELECTED + } + value = element + return OFFER_SUCCESS } + // breaks here if offer meets receiver + receive!!.completeResumeReceive(element) + return receive!!.offerResult } - // result is always `ALREADY_SELECTED | OFFER_SUCCESS | Closed`. - protected override fun offerSelectInternal(element: E, select: SelectInstance<*>): Any { - while (true) { - val result = if (hasReceiveOrClosed) - super.offerSelectInternal(element, select) else - (select.performAtomicTrySelect(describeSendConflated(element)) ?: OFFER_SUCCESS) - when { - result === ALREADY_SELECTED -> return ALREADY_SELECTED - result === OFFER_SUCCESS -> return OFFER_SUCCESS - result === OFFER_FAILED -> {} // retry - result === RETRY_ATOMIC -> {} // retry - result is Closed<*> -> return result - else -> error("Invalid result $result") + // result is `E | POLL_FAILED | Closed` + protected override fun pollInternal(): Any? { + var result: Any? = null + lock.withLock { + if (value === EMPTY) return closedForSend ?: POLL_FAILED + result = value + value = EMPTY + } + return result + } + + // result is `E | POLL_FAILED | Closed` + protected override fun pollSelectInternal(select: SelectInstance<*>): Any? { + var result: Any? = null + lock.withLock { + if (value === EMPTY) return closedForSend ?: POLL_FAILED + if (!select.trySelect()) + return ALREADY_SELECTED + result = value + value = EMPTY + } + return result + } + + protected override fun onCancelIdempotent(wasClosed: Boolean) { + if (wasClosed) { + lock.withLock { + value = EMPTY } } + super.onCancelIdempotent(wasClosed) } -} + + override fun enqueueReceiveInternal(receive: Receive): Boolean = lock.withLock { + super.enqueueReceiveInternal(receive) + } + + // ------ debug ------ + + override val bufferDebugString: String + get() = "(value=$value)" +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelLFStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelLFStressTest.kt index 75e34e5a5e..256ef62132 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelLFStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelLFStressTest.kt @@ -41,14 +41,6 @@ class ChannelLFStressTest : TestBase() { checkAllReceived() } - @Test - fun testConflatedLockFreedom() { - // This test does not really verify that all sent elements were received - // and checks only LF property - channel = Channel(Channel.CONFLATED) - performLockFreedomTest() - } - private fun performLockFreedomTest() { env.onCompletion { // We must cancel the channel to abort both senders & receivers diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt index 625c620497..8836fdc7be 100644 --- a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlinx.lincheck.paramgen.* import org.jetbrains.kotlinx.lincheck.verifier.* import org.junit.* - class RendezvousChannelLCStressTest : ChannelLCStressTestBase( c = Channel(RENDEZVOUS), sequentialSpecification = SequentialRendezvousChannel::class.java @@ -48,7 +47,6 @@ class ConflatedChannelLCStressTest : ChannelLCStressTestBase( ) class SequentialConflatedChannel : SequentialIntChannelBase(CONFLATED) - @Param.Params( Param(name = "value", gen = IntGen::class, conf = "1:5"), Param(name = "closeToken", gen = IntGen::class, conf = "1:3") @@ -105,10 +103,10 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val // @Operation fun cancel(@Param(name = "closeToken") token: Int) = c.cancel(NumberedCancellationException(token)) -// @Operation + // @Operation fun isClosedForReceive() = c.isClosedForReceive -// @Operation + // @Operation fun isClosedForSend() = c.isClosedForSend // TODO: this operation should be (and can be!) linearizable, but is not From 4aa38803af953684e4f670d7f30d78d277c486f0 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 13 Feb 2020 15:42:58 +0300 Subject: [PATCH 26/50] =?UTF-8?q?Detect=20missing=20awaitClose=20calls=20i?= =?UTF-8?q?n=20callbackFlow=20and=20close=20channel=20wit=E2=80=A6=20(#177?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1762 Fixes #1770 --- .../common/src/channels/Channel.kt | 2 +- .../common/src/channels/Produce.kt | 2 +- .../common/src/flow/Builders.kt | 69 ++++++++++++++----- .../common/src/flow/internal/ChannelFlow.kt | 21 +++--- .../common/test/channels/ProduceTest.kt | 16 ++++- .../test/flow/channels/ChannelFlowTest.kt | 34 +++++++++ .../test/flow/channels/FlowCallbackTest.kt | 24 +++++-- .../jvm/src/channels/Channels.kt | 4 +- .../jvm/test/AsyncJvmTest.kt | 34 ++------- .../jvm/test/flow/CallbackFlowTest.kt | 4 +- 10 files changed, 139 insertions(+), 71 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 07e05f07d9..27334fee72 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -586,4 +586,4 @@ public class ClosedSendChannelException(message: String?) : IllegalStateExceptio * * This exception is a subclass of [NoSuchElementException] to be consistent with plain collections. */ -public class ClosedReceiveChannelException(message: String?) : NoSuchElementException(message) \ No newline at end of file +public class ClosedReceiveChannelException(message: String?) : NoSuchElementException(message) diff --git a/kotlinx-coroutines-core/common/src/channels/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt index 68fb09a41c..a0c3284240 100644 --- a/kotlinx-coroutines-core/common/src/channels/Produce.kt +++ b/kotlinx-coroutines-core/common/src/channels/Produce.kt @@ -27,7 +27,7 @@ public interface ProducerScope : CoroutineScope, SendChannel { /** * Suspends the current coroutine until the channel is either [closed][SendChannel.close] or [cancelled][ReceiveChannel.cancel] - * and invokes the given [block] before resuming the coroutine. + * and invokes the given [block] before resuming the coroutine. This suspending function is cancellable. * * Note that when the producer channel is cancelled, this function resumes with a cancellation exception. * Therefore, in case of cancellation, no code after the call to this function will be executed. diff --git a/kotlinx-coroutines-core/common/src/flow/Builders.kt b/kotlinx-coroutines-core/common/src/flow/Builders.kt index 49ad2922e9..d8e82d65ff 100644 --- a/kotlinx-coroutines-core/common/src/flow/Builders.kt +++ b/kotlinx-coroutines-core/common/src/flow/Builders.kt @@ -11,9 +11,9 @@ import kotlinx.coroutines.* import kotlinx.coroutines.channels.* import kotlinx.coroutines.channels.Channel.Factory.BUFFERED import kotlinx.coroutines.flow.internal.* -import kotlinx.coroutines.flow.internal.unsafeFlow as flow import kotlin.coroutines.* import kotlin.jvm.* +import kotlinx.coroutines.flow.internal.unsafeFlow as flow /** * Creates a flow from the given suspendable [block]. @@ -259,10 +259,16 @@ public fun channelFlow(@BuilderInference block: suspend ProducerScope.() * * This builder ensures thread-safety and context preservation, thus the provided [ProducerScope] can be used * from any context, e.g. from a callback-based API. - * The resulting flow completes as soon as the code in the [block] and all its children completes. - * Use [awaitClose] as the last statement to keep it running. - * The [awaitClose] argument is called either when a flow consumer cancels the flow collection - * or when a callback-based API invokes [SendChannel.close] manually. + * The resulting flow completes as soon as the code in the [block] completes. + * [awaitClose] should be used to keep the flow running, otherwise the channel will be closed immediately + * when block completes. + * [awaitClose] argument is called either when a flow consumer cancels the flow collection + * or when a callback-based API invokes [SendChannel.close] manually and is typically used + * to cleanup the resources after the completion, e.g. unregister a callback. + * Using [awaitClose] is mandatory in order to prevent memory leaks when the flow collection is cancelled, + * otherwise the callback may keep running even when the flow collector is already completed. + * To avoid such leaks, this method throws [IllegalStateException] if block returns, but the channel + * is not closed yet. * * A channel with the [default][Channel.BUFFERED] buffer size is used. Use the [buffer] operator on the * resulting flow to specify a user-defined value and to control what happens when data is produced faster @@ -277,9 +283,13 @@ public fun channelFlow(@BuilderInference block: suspend ProducerScope.() * fun flowFrom(api: CallbackBasedApi): Flow = callbackFlow { * val callback = object : Callback { // implementation of some callback interface * override fun onNextValue(value: T) { - * // Note: offer drops value when buffer is full - * // Use either buffer(Channel.CONFLATED) or buffer(Channel.UNLIMITED) to avoid overfill - * offer(value) + * // To avoid blocking you can configure channel capacity using + * // either buffer(Channel.CONFLATED) or buffer(Channel.UNLIMITED) to avoid overfill + * try { + * sendBlocking(value) + * } catch (e: Exception) { + * // Handle exception from the channel: failure in flow or premature closing + * } * } * override fun onApiError(cause: Throwable) { * cancel(CancellationException("API Error", cause)) @@ -287,21 +297,20 @@ public fun channelFlow(@BuilderInference block: suspend ProducerScope.() * override fun onCompleted() = channel.close() * } * api.register(callback) - * // Suspend until either onCompleted or external cancellation are invoked + * /* + * * Suspends until either 'onCompleted'/'onApiError' from the callback is invoked + * * or flow collector is cancelled (e.g. by 'take(1)' or because a collector's coroutine was cancelled). + * * In both cases, callback will be properly unregistered. + * */ * awaitClose { api.unregister(callback) } * } * ``` - * - * This function is an alias for [channelFlow], it has a separate name to reflect - * the intent of the usage (integration with a callback-based API) better. */ -@Suppress("NOTHING_TO_INLINE") @ExperimentalCoroutinesApi -public inline fun callbackFlow(@BuilderInference noinline block: suspend ProducerScope.() -> Unit): Flow = - channelFlow(block) +public fun callbackFlow(@BuilderInference block: suspend ProducerScope.() -> Unit): Flow = CallbackFlowBuilder(block) // ChannelFlow implementation that is the first in the chain of flow operations and introduces (builds) a flow -private class ChannelFlowBuilder( +private open class ChannelFlowBuilder( private val block: suspend ProducerScope.() -> Unit, context: CoroutineContext = EmptyCoroutineContext, capacity: Int = BUFFERED @@ -315,3 +324,31 @@ private class ChannelFlowBuilder( override fun toString(): String = "block[$block] -> ${super.toString()}" } + +private class CallbackFlowBuilder( + private val block: suspend ProducerScope.() -> Unit, + context: CoroutineContext = EmptyCoroutineContext, + capacity: Int = BUFFERED +) : ChannelFlowBuilder(block, context, capacity) { + + override suspend fun collectTo(scope: ProducerScope) { + super.collectTo(scope) + /* + * We expect user either call `awaitClose` from within a block (then the channel is closed at this moment) + * or being closed/cancelled externally/manually. Otherwise "user forgot to call + * awaitClose and receives unhelpful ClosedSendChannelException exceptions" situation is detected. + */ + if (!scope.isClosedForSend) { + throw IllegalStateException( + """ + 'awaitClose { yourCallbackOrListener.cancel() }' should be used in the end of callbackFlow block. + Otherwise, a callback/listener may leak in case of external cancellation. + See callbackFlow API documentation for the details. + """.trimIndent() + ) + } + } + + override fun create(context: CoroutineContext, capacity: Int): ChannelFlow = + CallbackFlowBuilder(block, context, capacity) +} diff --git a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt index 4711b88418..8b79c09b6e 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt @@ -27,6 +27,14 @@ public abstract class ChannelFlow( // buffer capacity between upstream and downstream context @JvmField val capacity: Int ) : Flow { + + // shared code to create a suspend lambda from collectTo function in one place + internal val collectToFun: suspend (ProducerScope) -> Unit + get() = { collectTo(it) } + + private val produceCapacity: Int + get() = if (capacity == Channel.OPTIONAL_CHANNEL) Channel.BUFFERED else capacity + public fun update( context: CoroutineContext = EmptyCoroutineContext, capacity: Int = Channel.OPTIONAL_CHANNEL @@ -57,13 +65,6 @@ public abstract class ChannelFlow( protected abstract suspend fun collectTo(scope: ProducerScope) - // shared code to create a suspend lambda from collectTo function in one place - internal val collectToFun: suspend (ProducerScope) -> Unit - get() = { collectTo(it) } - - private val produceCapacity: Int - get() = if (capacity == Channel.OPTIONAL_CHANNEL) Channel.BUFFERED else capacity - open fun broadcastImpl(scope: CoroutineScope, start: CoroutineStart): BroadcastChannel = scope.broadcast(context, produceCapacity, start, block = collectToFun) @@ -75,11 +76,11 @@ public abstract class ChannelFlow( collector.emitAll(produceImpl(this)) } + open fun additionalToStringProps() = "" + // debug toString override fun toString(): String = "$classSimpleName[${additionalToStringProps()}context=$context, capacity=$capacity]" - - open fun additionalToStringProps() = "" } // ChannelFlow implementation that operates on another flow before it @@ -161,7 +162,7 @@ private suspend fun withContextUndispatched( countOrElement: Any = threadContextElements(newContext), // can be precomputed for speed block: suspend (V) -> T, value: V ): T = - suspendCoroutineUninterceptedOrReturn sc@{ uCont -> + suspendCoroutineUninterceptedOrReturn { uCont -> withCoroutineContext(newContext, countOrElement) { block.startCoroutineUninterceptedOrReturn(value, Continuation(newContext) { uCont.resumeWith(it) diff --git a/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt index bf85c74f64..885f1d6c8f 100644 --- a/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* import kotlin.coroutines.* import kotlin.test.* @@ -143,9 +144,20 @@ class ProduceTest : TestBase() { @Test fun testAwaitIllegalState() = runTest { - val channel = produce { } - @Suppress("RemoveExplicitTypeArguments") // KT-31525 + val channel = produce { } assertFailsWith { (channel as ProducerScope<*>).awaitClose() } + callbackFlow { + expect(1) + launch { + expect(2) + assertFailsWith { + awaitClose { expectUnreached() } + expectUnreached() + } + } + close() + }.collect() + finish(3) } private suspend fun cancelOnCompletion(coroutineContext: CoroutineContext) = CoroutineScope(coroutineContext).apply { diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt index 32c2afc65b..b115150a0b 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelFlowTest.kt @@ -160,4 +160,38 @@ class ChannelFlowTest : TestBase() { finish(6) } + + @Test + fun testClosedPrematurely() = runTest(unhandled = listOf({ e -> e is ClosedSendChannelException })) { + val outerScope = this + val flow = channelFlow { + // ~ callback-based API, no children + outerScope.launch(Job()) { + expect(2) + send(1) + expectUnreached() + } + expect(1) + } + assertEquals(emptyList(), flow.toList()) + finish(3) + } + + @Test + fun testNotClosedPrematurely() = runTest { + val outerScope = this + val flow = channelFlow { + // ~ callback-based API + outerScope.launch(Job()) { + expect(2) + send(1) + close() + } + expect(1) + awaitClose() + } + + assertEquals(listOf(1), flow.toList()) + finish(3) + } } diff --git a/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt index a6b5340555..cfbf242c35 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/FlowCallbackTest.kt @@ -12,25 +12,35 @@ import kotlin.test.* class FlowCallbackTest : TestBase() { @Test - fun testClosedPrematurely() = runTest(unhandled = listOf({ e -> e is ClosedSendChannelException })) { + fun testClosedPrematurely() = runTest { val outerScope = this - val flow = channelFlow { + val flow = callbackFlow { // ~ callback-based API outerScope.launch(Job()) { expect(2) - send(1) - expectUnreached() + try { + send(1) + expectUnreached() + } catch (e: IllegalStateException) { + expect(3) + assertTrue(e.message!!.contains("awaitClose")) + } } expect(1) } - assertEquals(emptyList(), flow.toList()) - finish(3) + try { + flow.collect() + } catch (e: IllegalStateException) { + expect(4) + assertTrue(e.message!!.contains("awaitClose")) + } + finish(5) } @Test fun testNotClosedPrematurely() = runTest { val outerScope = this - val flow = channelFlow { + val flow = callbackFlow { // ~ callback-based API outerScope.launch(Job()) { expect(2) diff --git a/kotlinx-coroutines-core/jvm/src/channels/Channels.kt b/kotlinx-coroutines-core/jvm/src/channels/Channels.kt index 78889e70ab..2c9499597f 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -9,8 +9,6 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* -// -------- Operations on SendChannel -------- - /** * Adds [element] into to this channel, **blocking** the caller while this channel [Channel.isFull], * or throws exception if the channel [Channel.isClosedForSend] (see [Channel.close] for details). diff --git a/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt index dab7d5d033..9c37b7bf50 100644 --- a/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt @@ -10,36 +10,12 @@ class AsyncJvmTest : TestBase() { // This must be a common test but it fails on JS because of KT-21961 @Test fun testAsyncWithFinally() = runTest { - expect(1) + launch(Dispatchers.Default) { + + } + + launch(Dispatchers.IO) { - @Suppress("UNREACHABLE_CODE") - val d = async { - expect(3) - try { - yield() // to main, will cancel - } finally { - expect(6) // will go there on await - return@async "Fail" // result will not override cancellation - } - expectUnreached() - "Fail2" - } - expect(2) - yield() // to async - expect(4) - check(d.isActive && !d.isCompleted && !d.isCancelled) - d.cancel() - check(!d.isActive && !d.isCompleted && d.isCancelled) - check(!d.isActive && !d.isCompleted && d.isCancelled) - expect(5) - try { - d.await() // awaits - expectUnreached() // does not complete normally - } catch (e: Throwable) { - expect(7) - check(e is CancellationException) } - check(!d.isActive && d.isCompleted && d.isCancelled) - finish(8) } } diff --git a/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt b/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt index f71040343d..e3db2626ce 100644 --- a/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt +++ b/kotlinx-coroutines-core/jvm/test/flow/CallbackFlowTest.kt @@ -39,7 +39,7 @@ class CallbackFlowTest : TestBase() { runCatching { it.offer(++i) } } - val flow = channelFlow { + val flow = callbackFlow { api.start(channel) awaitClose { api.stop() @@ -118,7 +118,7 @@ class CallbackFlowTest : TestBase() { } } - private fun Flow.merge(other: Flow): Flow = callbackFlow { + private fun Flow.merge(other: Flow): Flow = channelFlow { launch { collect { send(it) } } From b64a23bcb32fc135c6666945cb7a4f1157b4e8a1 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Thu, 13 Feb 2020 15:51:14 +0300 Subject: [PATCH 27/50] Improve FieldWalker, don't access JDK classes (#1799) * Improve FieldWalker, don't access JDK classes * Works on future JDKs that forbid reflective access to JDK classes * Show human-readable path to field is something fails --- .../jvm/test/FieldWalker.kt | 185 +++++++++++------- .../ReusableCancellableContinuationTest.kt | 20 +- .../jvm/test/flow/ConsumeAsFlowLeakTest.kt | 2 +- 3 files changed, 123 insertions(+), 84 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/test/FieldWalker.kt b/kotlinx-coroutines-core/jvm/test/FieldWalker.kt index bb8b855498..12fd4dea04 100644 --- a/kotlinx-coroutines-core/jvm/test/FieldWalker.kt +++ b/kotlinx-coroutines-core/jvm/test/FieldWalker.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -7,109 +7,148 @@ package kotlinx.coroutines import java.lang.reflect.* import java.util.* import java.util.Collections.* +import java.util.concurrent.atomic.* import kotlin.collections.ArrayList +import kotlin.test.* object FieldWalker { + sealed class Ref { + object RootRef : Ref() + class FieldRef(val parent: Any, val name: String) : Ref() + class ArrayRef(val parent: Any, val index: Int) : Ref() + } + + private val fieldsCache = HashMap, List>() + + init { + // excluded/terminal classes (don't walk them) + fieldsCache += listOf(Any::class, String::class, Thread::class, Throwable::class) + .map { it.java } + .associateWith { emptyList() } + } /* * Reflectively starts to walk through object graph and returns identity set of all reachable objects. + * Use [walkRefs] if you need a path from root for debugging. + */ + public fun walk(root: Any?): Set = walkRefs(root).keys + + public fun assertReachableCount(expected: Int, root: Any?, predicate: (Any) -> Boolean) { + val visited = walkRefs(root) + val actual = visited.keys.filter(predicate) + if (actual.size != expected) { + val textDump = actual.joinToString("") { "\n\t" + showPath(it, visited) } + assertEquals( + expected, actual.size, + "Unexpected number objects. Expected $expected, found ${actual.size}$textDump" + ) + } + } + + /* + * Reflectively starts to walk through object graph and map to all the reached object to their path + * in from root. Use [showPath] do display a path if needed. */ - public fun walk(root: Any): Set { - val result = newSetFromMap(IdentityHashMap()) - result.add(root) + private fun walkRefs(root: Any?): Map { + val visited = IdentityHashMap() + if (root == null) return visited + visited[root] = Ref.RootRef val stack = ArrayDeque() stack.addLast(root) while (stack.isNotEmpty()) { val element = stack.removeLast() - val type = element.javaClass - type.visit(element, result, stack) + try { + visit(element, visited, stack) + } catch (e: Exception) { + error("Failed to visit element ${showPath(element, visited)}: $e") + } } - return result + return visited } - private fun Class<*>.visit( - element: Any, - result: MutableSet, - stack: ArrayDeque - ) { - val fields = fields() - fields.forEach { - it.isAccessible = true - val value = it.get(element) ?: return@forEach - if (result.add(value)) { - stack.addLast(value) + private fun showPath(element: Any, visited: Map): String { + val path = ArrayList() + var cur = element + while (true) { + val ref = visited.getValue(cur) + if (ref is Ref.RootRef) break + when (ref) { + is Ref.FieldRef -> { + cur = ref.parent + path += ".${ref.name}" + } + is Ref.ArrayRef -> { + cur = ref.parent + path += "[${ref.index}]" + } } } + path.reverse() + return path.joinToString("") + } - if (isArray && !componentType.isPrimitive) { - val array = element as Array - array.filterNotNull().forEach { - if (result.add(it)) { - stack.addLast(it) + private fun visit(element: Any, visited: IdentityHashMap, stack: ArrayDeque) { + val type = element.javaClass + when { + // Special code for arrays + type.isArray && !type.componentType.isPrimitive -> { + @Suppress("UNCHECKED_CAST") + val array = element as Array + array.forEachIndexed { index, value -> + push(value, visited, stack) { Ref.ArrayRef(element, index) } + } + } + // Special code for platform types that cannot be reflectively accessed on modern JDKs + type.name.startsWith("java.") && element is Collection<*> -> { + element.forEachIndexed { index, value -> + push(value, visited, stack) { Ref.ArrayRef(element, index) } + } + } + type.name.startsWith("java.") && element is Map<*, *> -> { + push(element.keys, visited, stack) { Ref.FieldRef(element, "keys") } + push(element.values, visited, stack) { Ref.FieldRef(element, "values") } + } + element is AtomicReference<*> -> { + push(element.get(), visited, stack) { Ref.FieldRef(element, "value") } + } + // All the other classes are reflectively scanned + else -> fields(type).forEach { field -> + push(field.get(element), visited, stack) { Ref.FieldRef(element, field.name) } + // special case to scan Throwable cause (cannot get it reflectively) + if (element is Throwable) { + push(element.cause, visited, stack) { Ref.FieldRef(element, "cause") } } } } } - private fun Class<*>.fields(): List { + private inline fun push(value: Any?, visited: IdentityHashMap, stack: ArrayDeque, ref: () -> Ref) { + if (value != null && !visited.containsKey(value)) { + visited[value] = ref() + stack.addLast(value) + } + } + + private fun fields(type0: Class<*>): List { + fieldsCache[type0]?.let { return it } val result = ArrayList() - var type = this - while (type != Any::class.java) { + var type = type0 + while (true) { val fields = type.declaredFields.filter { !it.type.isPrimitive && !Modifier.isStatic(it.modifiers) && !(it.type.isArray && it.type.componentType.isPrimitive) } + fields.forEach { it.isAccessible = true } // make them all accessible result.addAll(fields) type = type.superclass - } - - return result - } - - // Debugging-only - @Suppress("UNUSED") - fun printPath(from: Any, to: Any) { - val pathNodes = ArrayList() - val visited = newSetFromMap(IdentityHashMap()) - visited.add(from) - if (findPath(from, to, visited, pathNodes)) { - pathNodes.reverse() - println(pathNodes.joinToString(" -> ", from.javaClass.simpleName + " -> ", "-> " + to.javaClass.simpleName)) - } else { - println("Path from $from to $to not found") - } - } - - private fun findPath(from: Any, to: Any, visited: MutableSet, pathNodes: MutableList): Boolean { - if (from === to) { - return true - } - - val type = from.javaClass - if (type.isArray) { - if (type.componentType.isPrimitive) return false - val array = from as Array - array.filterNotNull().forEach { - if (findPath(it, to, visited, pathNodes)) { - return true - } + val superFields = fieldsCache[type] // will stop at Any anyway + if (superFields != null) { + result.addAll(superFields) + break } - return false } - - val fields = type.fields() - fields.forEach { - it.isAccessible = true - val value = it.get(from) ?: return@forEach - if (!visited.add(value)) return@forEach - val found = findPath(value, to, visited, pathNodes) - if (found) { - pathNodes += from.javaClass.simpleName + ":" + it.name - return true - } - } - - return false + fieldsCache[type0] = result + return result } } diff --git a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt index b324e7ed3a..997f746118 100644 --- a/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt +++ b/kotlinx-coroutines-core/jvm/test/ReusableCancellableContinuationTest.kt @@ -76,7 +76,7 @@ class ReusableCancellableContinuationTest : TestBase() { expect(4) ensureActive() // Verify child was bound - assertNotNull(FieldWalker.walk(coroutineContext[Job]!!).single { it === continuation }) + FieldWalker.assertReachableCount(1, coroutineContext[Job]) { it === continuation } suspendAtomicCancellableCoroutineReusable { expect(5) coroutineContext[Job]!!.cancel() @@ -97,7 +97,7 @@ class ReusableCancellableContinuationTest : TestBase() { cont = it } ensureActive() - assertTrue { FieldWalker.walk(coroutineContext[Job]!!).contains(cont!!) } + assertTrue { FieldWalker.walk(coroutineContext[Job]).contains(cont!!) } finish(2) } @@ -112,7 +112,7 @@ class ReusableCancellableContinuationTest : TestBase() { cont = it } ensureActive() - assertFalse { FieldWalker.walk(coroutineContext[Job]!!).contains(cont!!) } + FieldWalker.assertReachableCount(0, coroutineContext[Job]) { it === cont } finish(2) } @@ -127,7 +127,7 @@ class ReusableCancellableContinuationTest : TestBase() { } expectUnreached() } catch (e: CancellationException) { - assertFalse { FieldWalker.walk(coroutineContext[Job]!!).contains(cont!!) } + FieldWalker.assertReachableCount(0, coroutineContext[Job]) { it === cont } finish(2) } } @@ -148,19 +148,19 @@ class ReusableCancellableContinuationTest : TestBase() { expect(4) ensureActive() // Verify child was bound - assertEquals(1, FieldWalker.walk(currentJob).count { it is CancellableContinuation<*> }) + FieldWalker.assertReachableCount(1, currentJob) { it is CancellableContinuation<*> } currentJob.cancel() assertFalse(isActive) // Child detached - assertEquals(0, FieldWalker.walk(currentJob).count { it is CancellableContinuation<*> }) + FieldWalker.assertReachableCount(0, currentJob) { it is CancellableContinuation<*> } suspendAtomicCancellableCoroutineReusable { it.resume(Unit) } suspendAtomicCancellableCoroutineReusable { it.resume(Unit) } - assertEquals(0, FieldWalker.walk(currentJob).count { it is CancellableContinuation<*> }) + FieldWalker.assertReachableCount(0, currentJob) { it is CancellableContinuation<*> } try { suspendAtomicCancellableCoroutineReusable {} } catch (e: CancellationException) { - assertEquals(0, FieldWalker.walk(currentJob).count { it is CancellableContinuation<*> }) + FieldWalker.assertReachableCount(0, currentJob) { it is CancellableContinuation<*> } finish(5) } } @@ -184,12 +184,12 @@ class ReusableCancellableContinuationTest : TestBase() { expect(2) val job = coroutineContext[Job]!! // 1 for reusable CC, another one for outer joiner - assertEquals(2, FieldWalker.walk(job).count { it is CancellableContinuation<*> }) + FieldWalker.assertReachableCount(2, job) { it is CancellableContinuation<*> } } expect(1) receiver.join() // Reference should be claimed at this point - assertEquals(0, FieldWalker.walk(receiver).count { it is CancellableContinuation<*> }) + FieldWalker.assertReachableCount(0, receiver) { it is CancellableContinuation<*> } finish(3) } } diff --git a/kotlinx-coroutines-core/jvm/test/flow/ConsumeAsFlowLeakTest.kt b/kotlinx-coroutines-core/jvm/test/flow/ConsumeAsFlowLeakTest.kt index 3fcceaf1fb..c037be1e6d 100644 --- a/kotlinx-coroutines-core/jvm/test/flow/ConsumeAsFlowLeakTest.kt +++ b/kotlinx-coroutines-core/jvm/test/flow/ConsumeAsFlowLeakTest.kt @@ -41,7 +41,7 @@ class ConsumeAsFlowLeakTest : TestBase() { if (shouldSuspendOnSend) yield() channel.send(second) yield() - assertEquals(0, FieldWalker.walk(channel).count { it === second }) + FieldWalker.assertReachableCount(0, channel) { it === second } finish(6) job.cancelAndJoin() } From de491d25764fca8afbece56950f623f4c3155542 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 13 Feb 2020 16:02:42 +0300 Subject: [PATCH 28/50] =?UTF-8?q?Make=20SafeCollector=20platform-specific?= =?UTF-8?q?=20declaration=20and=20enforce=20exceptio=E2=80=A6=20(#1793)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make SafeCollector platform-specific declaration and enforce exception transparency invariant on JVM * Make it in an allocation-free manner by using a crafty trick with casting KSuspendFunction to Function and pass a reusable object as a completion Fixes #1657 --- .../api/kotlinx-coroutines-core.api | 2 +- .../common/src/flow/Builders.kt | 7 +- .../common/src/flow/Flow.kt | 13 +- .../src/flow/internal/SafeCollector.common.kt | 111 +++++++++++++++ .../common/src/flow/internal/SafeCollector.kt | 124 ---------------- .../common/src/flow/operators/Emitters.kt | 14 +- .../common/test/TestBase.common.kt | 2 +- .../common/test/flow/FlowInvariantsTest.kt | 27 +--- .../common/test/flow/SafeFlowTest.kt | 31 ++++ .../js/src/flow/internal/SafeCollector.kt | 30 ++++ .../jvm/src/flow/internal/SafeCollector.kt | 134 ++++++++++++++++++ .../test/flow/ExceptionTransparencyTest.kt | 77 ++++++++++ .../native/src/flow/internal/SafeCollector.kt | 30 ++++ 13 files changed, 446 insertions(+), 156 deletions(-) create mode 100644 kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt delete mode 100644 kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.kt create mode 100644 kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt create mode 100644 kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt create mode 100644 kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt create mode 100644 kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt create mode 100644 kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt diff --git a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api index 6df47e179f..04a4e99c9a 100644 --- a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api +++ b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api @@ -1001,7 +1001,7 @@ public final class kotlinx/coroutines/flow/internal/FlowExceptions_commonKt { public static final fun checkIndexOverflow (I)I } -public final class kotlinx/coroutines/flow/internal/SafeCollectorKt { +public final class kotlinx/coroutines/flow/internal/SafeCollector_commonKt { public static final fun unsafeFlow (Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow; } diff --git a/kotlinx-coroutines-core/common/src/flow/Builders.kt b/kotlinx-coroutines-core/common/src/flow/Builders.kt index d8e82d65ff..111bc723b6 100644 --- a/kotlinx-coroutines-core/common/src/flow/Builders.kt +++ b/kotlinx-coroutines-core/common/src/flow/Builders.kt @@ -51,7 +51,12 @@ public fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit // Named anonymous object private class SafeFlow(private val block: suspend FlowCollector.() -> Unit) : Flow { override suspend fun collect(collector: FlowCollector) { - SafeCollector(collector, coroutineContext).block() + val safeCollector = SafeCollector(collector, coroutineContext) + try { + safeCollector.block() + } finally { + safeCollector.releaseIntercepted() + } } } diff --git a/kotlinx-coroutines-core/common/src/flow/Flow.kt b/kotlinx-coroutines-core/common/src/flow/Flow.kt index 6d87c2b9aa..7e98013e83 100644 --- a/kotlinx-coroutines-core/common/src/flow/Flow.kt +++ b/kotlinx-coroutines-core/common/src/flow/Flow.kt @@ -5,7 +5,7 @@ package kotlinx.coroutines.flow import kotlinx.coroutines.* -import kotlinx.coroutines.flow.internal.SafeCollector +import kotlinx.coroutines.flow.internal.* import kotlin.coroutines.* /** @@ -149,8 +149,8 @@ import kotlin.coroutines.* * it hard to reason about the code because an exception in the `collect { ... }` could be somehow "caught" * by an upstream flow, limiting the ability of local reasoning about the code. * - * Currently, the flow infrastructure does not enforce exception transparency contracts, however, it might be enforced - * in the future either at run time or at compile time. + * Flow machinery enforces exception transparency at runtime and throws [IllegalStateException] on any attempt to emit a value, + * if an exception has been thrown on previous attempt. * * ### Reactive streams * @@ -199,7 +199,12 @@ public abstract class AbstractFlow : Flow { @InternalCoroutinesApi public final override suspend fun collect(collector: FlowCollector) { - collectSafely(SafeCollector(collector, collectContext = coroutineContext)) + val safeCollector = SafeCollector(collector, coroutineContext) + try { + collectSafely(safeCollector) + } finally { + safeCollector.releaseIntercepted() + } } /** diff --git a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt new file mode 100644 index 0000000000..c89e94f592 --- /dev/null +++ b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.common.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.flow.internal + +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.internal.ScopeCoroutine +import kotlin.coroutines.* +import kotlin.jvm.* + +internal expect class SafeCollector( + collector: FlowCollector, + collectContext: CoroutineContext +) : FlowCollector { + internal val collector: FlowCollector + internal val collectContext: CoroutineContext + internal val collectContextSize: Int + public fun releaseIntercepted() +} + +@JvmName("checkContext") // For prettier stack traces +internal fun SafeCollector<*>.checkContext(currentContext: CoroutineContext) { + val result = currentContext.fold(0) fold@{ count, element -> + val key = element.key + val collectElement = collectContext[key] + if (key !== Job) { + return@fold if (element !== collectElement) Int.MIN_VALUE + else count + 1 + } + + val collectJob = collectElement as Job? + val emissionParentJob = (element as Job).transitiveCoroutineParent(collectJob) + /* + * Code like + * ``` + * coroutineScope { + * launch { + * emit(1) + * } + * + * launch { + * emit(2) + * } + * } + * ``` + * is prohibited because 'emit' is not thread-safe by default. Use 'channelFlow' instead if you need concurrent emission + * or want to switch context dynamically (e.g. with `withContext`). + * + * Note that collecting from another coroutine is allowed, e.g.: + * ``` + * coroutineScope { + * val channel = produce { + * collect { value -> + * send(value) + * } + * } + * channel.consumeEach { value -> + * emit(value) + * } + * } + * ``` + * is a completely valid. + */ + if (emissionParentJob !== collectJob) { + error( + "Flow invariant is violated:\n" + + "\t\tEmission from another coroutine is detected.\n" + + "\t\tChild of $emissionParentJob, expected child of $collectJob.\n" + + "\t\tFlowCollector is not thread-safe and concurrent emissions are prohibited.\n" + + "\t\tTo mitigate this restriction please use 'channelFlow' builder instead of 'flow'" + ) + } + + /* + * If collect job is null (-> EmptyCoroutineContext, probably run from `suspend fun main`), then invariant is maintained + * (common transitive parent is "null"), but count check will fail, so just do not count job context element when + * flow is collected from EmptyCoroutineContext + */ + if (collectJob == null) count else count + 1 + } + if (result != collectContextSize) { + error( + "Flow invariant is violated:\n" + + "\t\tFlow was collected in $collectContext,\n" + + "\t\tbut emission happened in $currentContext.\n" + + "\t\tPlease refer to 'flow' documentation or use 'flowOn' instead" + ) + } +} + +internal tailrec fun Job?.transitiveCoroutineParent(collectJob: Job?): Job? { + if (this === null) return null + if (this === collectJob) return this + if (this !is ScopeCoroutine<*>) return this + return parent.transitiveCoroutineParent(collectJob) +} + +/** + * An analogue of the [flow] builder that does not check the context of execution of the resulting flow. + * Used in our own operators where we trust the context of invocations. + */ +@PublishedApi +internal inline fun unsafeFlow(@BuilderInference crossinline block: suspend FlowCollector.() -> Unit): Flow { + return object : Flow { + override suspend fun collect(collector: FlowCollector) { + collector.block() + } + } +} diff --git a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.kt deleted file mode 100644 index fec0ee96e0..0000000000 --- a/kotlinx-coroutines-core/common/src/flow/internal/SafeCollector.kt +++ /dev/null @@ -1,124 +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.flow.internal - -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.internal.* -import kotlin.coroutines.* - -internal class SafeCollector( - private val collector: FlowCollector, - private val collectContext: CoroutineContext -) : FlowCollector { - - // Note, it is non-capturing lambda, so no extra allocation during init of SafeCollector - private val collectContextSize = collectContext.fold(0) { count, _ -> count + 1 } - private var lastEmissionContext: CoroutineContext? = null - - override suspend fun emit(value: T) { - /* - * Benign data-race here: - * We read potentially racy published coroutineContext, but we only use it for - * referential comparison (=> thus safe) and are not using it for structural comparisons. - */ - val currentContext = coroutineContext - // This check is triggered once per flow on happy path. - if (lastEmissionContext !== currentContext) { - checkContext(currentContext) - lastEmissionContext = currentContext - } - collector.emit(value) // TCE - } - - private fun checkContext(currentContext: CoroutineContext) { - val result = currentContext.fold(0) fold@{ count, element -> - val key = element.key - val collectElement = collectContext[key] - if (key !== Job) { - return@fold if (element !== collectElement) Int.MIN_VALUE - else count + 1 - } - - val collectJob = collectElement as Job? - val emissionParentJob = (element as Job).transitiveCoroutineParent(collectJob) - /* - * Things like - * ``` - * coroutineScope { - * launch { - * emit(1) - * } - * - * launch { - * emit(2) - * } - * } - * ``` - * are prohibited because 'emit' is not thread-safe by default. Use channelFlow instead if you need concurrent emission - * or want to switch context dynamically (e.g. with `withContext`). - * - * Note that collecting from another coroutine is allowed, e.g.: - * ``` - * coroutineScope { - * val channel = produce { - * collect { value -> - * send(value) - * } - * } - * channel.consumeEach { value -> - * emit(value) - * } - * } - * ``` - * is a completely valid. - */ - if (emissionParentJob !== collectJob) { - error( - "Flow invariant is violated:\n" + - "\t\tEmission from another coroutine is detected.\n" + - "\t\tChild of $emissionParentJob, expected child of $collectJob.\n" + - "\t\tFlowCollector is not thread-safe and concurrent emissions are prohibited.\n" + - "\t\tTo mitigate this restriction please use 'channelFlow' builder instead of 'flow'" - ) - } - - /* - * If collect job is null (-> EmptyCoroutineContext, probably run from `suspend fun main`), then invariant is maintained - * (common transitive parent is "null"), but count check will fail, so just do not count job context element when - * flow is collected from EmptyCoroutineContext - */ - if (collectJob == null) count else count + 1 - } - if (result != collectContextSize) { - error( - "Flow invariant is violated:\n" + - "\t\tFlow was collected in $collectContext,\n" + - "\t\tbut emission happened in $currentContext.\n" + - "\t\tPlease refer to 'flow' documentation or use 'flowOn' instead" - ) - } - } - - private tailrec fun Job?.transitiveCoroutineParent(collectJob: Job?): Job? { - if (this === null) return null - if (this === collectJob) return this - if (this !is ScopeCoroutine<*>) return this - return parent.transitiveCoroutineParent(collectJob) - } -} - -/** - * An analogue of the [flow] builder that does not check the context of execution of the resulting flow. - * Used in our own operators where we trust the context of invocations. - */ -@PublishedApi -internal inline fun unsafeFlow(@BuilderInference crossinline block: suspend FlowCollector.() -> Unit): Flow { - return object : Flow { - override suspend fun collect(collector: FlowCollector) { - collector.block() - } - } -} diff --git a/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt index 6a910764b7..e87e4802d0 100644 --- a/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt +++ b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt @@ -71,7 +71,12 @@ internal inline fun Flow.unsafeTransform( public fun Flow.onStart( action: suspend FlowCollector.() -> Unit ): Flow = unsafeFlow { // Note: unsafe flow is used here, but safe collector is used to invoke start action - SafeCollector(this, coroutineContext).action() + val safeCollector = SafeCollector(this, coroutineContext) + try { + safeCollector.action() + } finally { + safeCollector.releaseIntercepted() + } collect(this) // directly delegate } @@ -141,7 +146,12 @@ public fun Flow.onCompletion( throw e } // Exception from the upstream or normal completion - SafeCollector(this, coroutineContext).invokeSafely(action, exception) + val safeCollector = SafeCollector(this, coroutineContext) + try { + safeCollector.invokeSafely(action, exception) + } finally { + safeCollector.releaseIntercepted() + } exception?.let { throw it } } diff --git a/kotlinx-coroutines-core/common/test/TestBase.common.kt b/kotlinx-coroutines-core/common/test/TestBase.common.kt index 0fdce91fb4..a6119ee8a6 100644 --- a/kotlinx-coroutines-core/common/test/TestBase.common.kt +++ b/kotlinx-coroutines-core/common/test/TestBase.common.kt @@ -50,7 +50,7 @@ public suspend inline fun assertFailsWith(flow: Flow<*>) flow.collect() fail("Should be unreached") } catch (e: Throwable) { - assertTrue(e is T) + assertTrue(e is T, "Expected exception ${T::class}, but had $e instead") } } diff --git a/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt b/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt index 5dbc6e24ef..ce93f1fdb2 100644 --- a/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt @@ -59,25 +59,6 @@ class FlowInvariantsTest : TestBase() { } } - @Test - fun testCachedInvariantCheckResult() = runParametrizedTest { flow -> - flow { - emit(1) - try { - withContext(NamedDispatchers("foo")) { - emit(1) - } - fail() - } catch (e: IllegalStateException) { - expect(2) - } - emit(3) - }.collect { - expect(it) - } - finish(4) - } - @Test fun testWithNameContractViolated() = runParametrizedTest(IllegalStateException::class) { flow -> flow { @@ -146,9 +127,9 @@ class FlowInvariantsTest : TestBase() { } } - val flow = flowOf(1) - assertFailsWith { flow.merge(flow).toList() } - assertFailsWith { flow.trickyMerge(flow).toList() } + val flowInstance = flowOf(1) + assertFailsWith { flowInstance.merge(flowInstance).toList() } + assertFailsWith { flowInstance.trickyMerge(flowInstance).toList() } } @Test @@ -237,7 +218,7 @@ class FlowInvariantsTest : TestBase() { emptyContextTest { transform { expect(it) - kotlinx.coroutines.withContext(Dispatchers.Unconfined) { + withContext(Dispatchers.Unconfined) { emit(it + 1) } } diff --git a/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt new file mode 100644 index 0000000000..eaba11b950 --- /dev/null +++ b/kotlinx-coroutines-core/common/test/flow/SafeFlowTest.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.flow + +import kotlinx.coroutines.* +import kotlin.test.* + +class SafeFlowTest : TestBase() { + + @Test + fun testEmissionsFromDifferentStateMachine() = runTest { + val result = flow { + emit1(1) + emit2(2) + }.onEach { yield() }.toList() + assertEquals(listOf(1, 2), result) + finish(3) + } + + private suspend fun FlowCollector.emit1(expect: Int) { + emit(expect) + expect(expect) + } + + private suspend fun FlowCollector.emit2(expect: Int) { + emit(expect) + expect(expect) + } +} diff --git a/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt new file mode 100644 index 0000000000..78f1bdb2a9 --- /dev/null +++ b/kotlinx-coroutines-core/js/src/flow/internal/SafeCollector.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.flow.internal + +import kotlinx.coroutines.flow.* +import kotlin.coroutines.* + +internal actual class SafeCollector actual constructor( + internal actual val collector: FlowCollector, + internal actual val collectContext: CoroutineContext +) : FlowCollector { + + // Note, it is non-capturing lambda, so no extra allocation during init of SafeCollector + internal actual val collectContextSize = collectContext.fold(0) { count, _ -> count + 1 } + private var lastEmissionContext: CoroutineContext? = null + + override suspend fun emit(value: T) { + val currentContext = coroutineContext + if (lastEmissionContext !== currentContext) { + checkContext(currentContext) + lastEmissionContext = currentContext + } + collector.emit(value) + } + + public actual fun releaseIntercepted() { + } +} diff --git a/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt new file mode 100644 index 0000000000..4647a14245 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/src/flow/internal/SafeCollector.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.flow.internal + +import kotlinx.coroutines.flow.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* +import kotlin.coroutines.jvm.internal.* + +@Suppress("UNCHECKED_CAST") +private val emitFun = + FlowCollector::emit as Function3, Any?, Continuation, Any?> +/* + * Implementor of ContinuationImpl (that will be preserved as ABI nearly forever) + * in order to properly control 'intercepted()' lifecycle. + */ +@Suppress("CANNOT_OVERRIDE_INVISIBLE_MEMBER", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNCHECKED_CAST") +internal actual class SafeCollector actual constructor( + @JvmField internal actual val collector: FlowCollector, + @JvmField internal actual val collectContext: CoroutineContext +) : FlowCollector, ContinuationImpl(NoOpContinuation, EmptyCoroutineContext) { + + @JvmField // Note, it is non-capturing lambda, so no extra allocation during init of SafeCollector + internal actual val collectContextSize = collectContext.fold(0) { count, _ -> count + 1 } + private var lastEmissionContext: CoroutineContext? = null + private var completion: Continuation? = null + + // ContinuationImpl + override val context: CoroutineContext + get() = completion?.context ?: EmptyCoroutineContext + + override fun invokeSuspend(result: Result): Any? { + result.onFailure { lastEmissionContext = DownstreamExceptionElement(it) } + completion?.resumeWith(result as Result) + return COROUTINE_SUSPENDED + } + + // Escalate visibility to manually release intercepted continuation + public actual override fun releaseIntercepted() { + super.releaseIntercepted() + } + + /** + * This is a crafty implementation of state-machine reusing. + * First it checks that it is not used concurrently (which we explicitly prohibit) and + * then just cache an instance of the completion in order to avoid extra allocation on each emit, + * making it effectively garbage-free on its hot-path. + */ + override suspend fun emit(value: T) { + return suspendCoroutineUninterceptedOrReturn sc@{ uCont -> + try { + emit(uCont, value) + } catch (e: Throwable) { + // Save the fact that exception from emit (or even check context) has been thrown + lastEmissionContext = DownstreamExceptionElement(e) + throw e + } + } + } + + private fun emit(uCont: Continuation, value: T): Any? { + val currentContext = uCont.context + // This check is triggered once per flow on happy path. + val previousContext = lastEmissionContext + if (previousContext !== currentContext) { + checkContext(currentContext, previousContext, value) + } + completion = uCont + return emitFun(collector as FlowCollector, value, this as Continuation) + } + + private fun checkContext( + currentContext: CoroutineContext, + previousContext: CoroutineContext?, + value: T + ) { + if (previousContext is DownstreamExceptionElement) { + exceptionTransparencyViolated(previousContext, value) + } + checkContext(currentContext) + lastEmissionContext = currentContext + } + + private fun exceptionTransparencyViolated(exception: DownstreamExceptionElement, value: Any?) { + /* + * Exception transparency ensures that if a `collect` block or any intermediate operator + * throws an exception, then no more values will be received by it. + * For example, the following code: + * ``` + * val flow = flow { + * emit(1) + * try { + * emit(2) + * } catch (e: Exception) { + * emit(3) + * } + * } + * // Collector + * flow.collect { value -> + * if (value == 2) { + * throw CancellationException("No more elements required, received enough") + * } else { + * println("Collected $value") + * } + * } + * ``` + * is expected to print "Collected 1" and then "No more elements required, received enough" exception, + * but if exception transparency wasn't enforced, "Collected 1" and "Collected 3" would be printed instead. + */ + error(""" + Flow exception transparency is violated: + Previous 'emit' call has thrown exception ${exception.e}, but then emission attempt of value '$value' has been detected. + Emissions from 'catch' blocks are prohibited in order to avoid unspecified behaviour, 'Flow.catch' operator can be used instead. + For a more detailed explanation, please refer to Flow documentation. + """.trimIndent()) + } + +} + +internal class DownstreamExceptionElement(@JvmField val e: Throwable) : CoroutineContext.Element { + companion object Key : CoroutineContext.Key + + override val key: CoroutineContext.Key<*> = Key +} + +private object NoOpContinuation : Continuation { + override val context: CoroutineContext = EmptyCoroutineContext + + override fun resumeWith(result: Result) { + // Nothing + } +} diff --git a/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt b/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt new file mode 100644 index 0000000000..aca9eb9a1f --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/flow/ExceptionTransparencyTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.flow + +import kotlinx.coroutines.* +import kotlin.test.* + +class ExceptionTransparencyTest : TestBase() { + + @Test + fun testViolation() = runTest { + val flow = flow { + try { + expect(1) + emit(1) + expectUnreached() + } catch (e: CancellationException) { + expect(3) + emit(2) + } + }.take(1) + + assertFailsWith { flow.collect { expect(2) } } + finish(4) + } + + @Test + fun testViolationResumeWith() = runTest { + val flow = flow { + try { + expect(1) + emit(1) + yield() + expectUnreached() + } catch (e: CancellationException) { + expect(3) + emit(2) + } + }.take(1) + + assertFailsWith { + flow.collect { + yield() + expect(2) + } + } + finish(4) + } + + @Test + fun testViolationAfterInvariantVariation() = runTest { + val flow = flow { + coroutineScope { + try { + expect(1) + launch { + expect(2) + emit(1) + }.join() + expectUnreached() + } catch (e: Throwable) { + try { + emit(2) + } catch (e: IllegalStateException) { + assertTrue { e.message!!.contains("exception transparency") } + emit(3) + } + } + } + } + val e = assertFailsWith { flow.collect { expectUnreached() } } + assertTrue { e.message!!.contains("channelFlow") } + finish(3) + } +} diff --git a/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt b/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt new file mode 100644 index 0000000000..78f1bdb2a9 --- /dev/null +++ b/kotlinx-coroutines-core/native/src/flow/internal/SafeCollector.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.flow.internal + +import kotlinx.coroutines.flow.* +import kotlin.coroutines.* + +internal actual class SafeCollector actual constructor( + internal actual val collector: FlowCollector, + internal actual val collectContext: CoroutineContext +) : FlowCollector { + + // Note, it is non-capturing lambda, so no extra allocation during init of SafeCollector + internal actual val collectContextSize = collectContext.fold(0) { count, _ -> count + 1 } + private var lastEmissionContext: CoroutineContext? = null + + override suspend fun emit(value: T) { + val currentContext = coroutineContext + if (lastEmissionContext !== currentContext) { + checkContext(currentContext) + lastEmissionContext = currentContext + } + collector.emit(value) + } + + public actual fun releaseIntercepted() { + } +} From 9f4fd70597567dc4477e5d935d06a380edd09eae Mon Sep 17 00:00:00 2001 From: dkhalanskyjb <52952525+dkhalanskyjb@users.noreply.github.com> Date: Thu, 13 Feb 2020 16:44:49 +0300 Subject: [PATCH 29/50] Fix a race in some tests for JavaRX integration (#1801) An extremely rare race could happen in any of the tests in `LeakedExceptionTest` in the following case: * `withExceptionHandler` runs the block passed to it; * In one of the last iterations of `repeat`, `select` in `combine` happens on both flows at the same time, that is, the block that was passed to `rx[Something]` runs in two threads simultaneously; * One of these two threads (thread A) runs anomalously slow; * The other thread successfully throws an exception; * This exception is propagated to `catch`, so `collect` is finished; * `repeat` is exited, the block passed to `withExceptionHandler` is done executing; * `withExceptionHandler` sets back the usual exception handler, which fails when an exception in JavaRX happens (see https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling); * Thread A wakes up and throws an exception. This time, it is passed not to `handler`, which is made specifically to deal with this, but to the default handler. As a fix, now a special coroutine context passed to `rx[Something]` ensures that the spawned executions are run in a thread pool that blocks until all the tasks are done. --- .../test/LeakedExceptionTest.kt | 85 +++++++++++++++---- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt b/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt index 1430dbf381..7252ca2132 100644 --- a/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/LeakedExceptionTest.kt @@ -6,12 +6,12 @@ package kotlinx.coroutines.rx2 import io.reactivex.* import io.reactivex.exceptions.* -import io.reactivex.plugins.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.reactive.* import org.junit.Test -import java.io.* +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit import kotlin.test.* // Check that exception is not leaked to the global exception handler @@ -22,37 +22,86 @@ class LeakedExceptionTest : TestBase() { @Test fun testSingle() = withExceptionHandler(handler) { - val flow = rxSingle { throw TestException() }.toFlowable().asFlow() - runBlocking { - repeat(10000) { - combine(flow, flow) { _, _ -> Unit } - .catch {} - .collect { } + withFixedThreadPool(4) { dispatcher -> + val flow = rxSingle(dispatcher) { throw TestException() }.toFlowable().asFlow() + runBlocking { + repeat(10000) { + combine(flow, flow) { _, _ -> Unit } + .catch {} + .collect {} + } } } } @Test fun testObservable() = withExceptionHandler(handler) { - val flow = rxObservable { throw TestException() }.toFlowable(BackpressureStrategy.BUFFER).asFlow() - runBlocking { - repeat(10000) { - combine(flow, flow) { _, _ -> Unit } - .catch {} - .collect { } + withFixedThreadPool(4) { dispatcher -> + val flow = rxObservable(dispatcher) { throw TestException() } + .toFlowable(BackpressureStrategy.BUFFER) + .asFlow() + runBlocking { + repeat(10000) { + combine(flow, flow) { _, _ -> Unit } + .catch {} + .collect {} + } } } } @Test fun testFlowable() = withExceptionHandler(handler) { - val flow = rxFlowable { throw TestException() }.asFlow() - runBlocking { - repeat(10000) { + withFixedThreadPool(4) { dispatcher -> + val flow = rxFlowable(dispatcher) { throw TestException() }.asFlow() + runBlocking { + repeat(10000) { + combine(flow, flow) { _, _ -> Unit } + .catch {} + .collect {} + } + } + } + } + + /** + * This test doesn't test much and was added to display a problem with straighforward use of + * [withExceptionHandler]. + * + * If one was to remove `dispatcher` and launch `rxFlowable` with an empty coroutine context, + * this test would fail fairly often, while other tests were also vulnerable, but the problem is + * much more difficult to reproduce. Thus, this test is a justification for adding `dispatcher` + * to other tests. + * + * See the commit that introduced this test for a better explanation. + */ + @Test + fun testResettingExceptionHandler() = withExceptionHandler(handler) { + withFixedThreadPool(4) { dispatcher -> + val flow = rxFlowable(dispatcher) { + if ((0..1).random() == 0) { + Thread.sleep(100) + } + throw TestException() + }.asFlow() + runBlocking { combine(flow, flow) { _, _ -> Unit } .catch {} - .collect { } + .collect {} } } } + + /** + * Run in a thread pool, then wait for all the tasks to finish. + */ + private fun withFixedThreadPool(numberOfThreads: Int, block: (CoroutineDispatcher) -> Unit) { + val pool = Executors.newFixedThreadPool(numberOfThreads) + val dispatcher = pool.asCoroutineDispatcher() + block(dispatcher) + pool.shutdown() + while (!pool.awaitTermination(10, TimeUnit.SECONDS)) { + /* deliberately empty */ + } + } } From 455c255af1881f1362b1e9dd660d9eeae78e6a01 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 13 Feb 2020 15:38:16 +0300 Subject: [PATCH 30/50] Introduce ExecutorRule for stress-tests for simpler development process --- .../jvm/test/AwaitStressTest.kt | 8 +--- ...llableContinuationResumeCloseStressTest.kt | 12 ++--- .../jvm/test/ExecutorRule.kt | 45 +++++++++++++++++++ 3 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 kotlinx-coroutines-core/jvm/test/ExecutorRule.kt diff --git a/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt b/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt index 1e53c55276..6b711db5a6 100644 --- a/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt @@ -11,12 +11,8 @@ import java.util.concurrent.* class AwaitStressTest : TestBase() { private val iterations = 50_000 * stressTestMultiplier - private val pool = newFixedThreadPoolContext(4, "AwaitStressTest") - - @After - fun tearDown() { - pool.close() - } + @get:Rule + public val pool = ExecutorRule(4) @Test fun testMultipleExceptions() = runTest { diff --git a/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt index 7255b4ab2c..45ff86f5a0 100644 --- a/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt @@ -11,8 +11,9 @@ import kotlin.test.* import kotlin.test.Test class CancellableContinuationResumeCloseStressTest : TestBase() { - private val dispatcher = - newFixedThreadPoolContext(2, "CancellableContinuationResumeCloseStressTest") + @get:Rule + public val dispatcher = ExecutorRule(2) + private val startBarrier = CyclicBarrier(3) private val doneBarrier = CyclicBarrier(2) private val nRepeats = 1_000 * stressTestMultiplier @@ -20,11 +21,6 @@ class CancellableContinuationResumeCloseStressTest : TestBase() { private val closed = atomic(false) private var returnedOk = false - @After - fun tearDown() { - dispatcher.close() - } - @Test @Suppress("BlockingMethodInNonBlockingContext") fun testStress() = runTest { @@ -65,4 +61,4 @@ class CancellableContinuationResumeCloseStressTest : TestBase() { fun close() { assertFalse(closed.getAndSet(true)) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/ExecutorRule.kt b/kotlinx-coroutines-core/jvm/test/ExecutorRule.kt new file mode 100644 index 0000000000..e9cf6bcfc3 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/ExecutorRule.kt @@ -0,0 +1,45 @@ +/* + * 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.junit.rules.* +import org.junit.runner.* +import org.junit.runners.model.* +import java.util.concurrent.* +import kotlin.coroutines.* + +class ExecutorRule(private val numberOfThreads: Int) : TestRule, ExecutorCoroutineDispatcher() { + + private var _executor: ExecutorCoroutineDispatcher? = null + override val executor: Executor + get() = _executor?.executor ?: error("Executor is not initialized") + + override fun apply(base: Statement, description: Description): Statement { + return object : Statement() { + override fun evaluate() { + val threadPrefix = description.className.substringAfterLast(".") + "#" + description.methodName + _executor = newFixedThreadPoolContext(numberOfThreads, threadPrefix) + ignoreLostThreads(threadPrefix) + try { + return base.evaluate() + } finally { + val service = executor as ExecutorService + service.shutdown() + if (!service.awaitTermination(10, TimeUnit.SECONDS)) { + error("Test $description timed out") + } + } + } + } + } + + override fun dispatch(context: CoroutineContext, block: Runnable) { + _executor?.dispatch(context, block) ?: error("Executor is not initialized") + } + + override fun close() { + error("Cannot be closed manually") + } +} From 1ed6fccc202ea641f63d83163413c62cebd860ed Mon Sep 17 00:00:00 2001 From: Marius Volkhart Date: Thu, 13 Feb 2020 14:56:23 +0100 Subject: [PATCH 31/50] Indicate that root README should be updated with new contributions (#1795) --- integration/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/README.md b/integration/README.md index 44f270c059..89100179a8 100644 --- a/integration/README.md +++ b/integration/README.md @@ -23,5 +23,6 @@ Follow the following simple guidelines when contributing integration with your f * List of modules in this document. * List of modules in top-level [`settings.gradle`](../settings.gradle). * List of modules at the root of documentation site in [`site/docs/index.md`](../site/docs/index.md). + * List of integrations in the root [README.md](../README.md). * Update links to documentation website as explained [here](../knit/README.md#usage). * Squash your contribution to a single commit and create pull request to `develop` branch. From 660c2d70dd2f6d7e7c2752d323d8780a1248678b Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 14 Feb 2020 13:18:37 +0300 Subject: [PATCH 32/50] Use a separate Knit tool (#1486) * Use a separate Knit tool version 0.1.2 * Hierarchical knit.properties files are introduced which are gathered while walking up the directory tree with the properties in knit resources being top-level ones. * Freemarker templates for "knit.include" (top-level of example files) and "test.template" (test template) are introduced with locations that are resolved from properties. * KNIT and TEST_OUT directives are not supported anymore. - Knitting is controlled by "knit.dir" and "knit.pattern" props. - "test.name" prop or TEST_NAME directive drives test gen. * All markdown files are now clean of top-level knit-related boilerplate (only TEST_NAME directive is remaining in some) * All example files are renumbered. It affects example-basic-xx, which had the legacy numbering with later insertions. * All auto-generated files now have the correct source-file name specified at their beginning, due to consistent use of template substitution. * No need to customize knit.pattern anymore (works out-of-the box) * "knit.name" is automatically generated based on example's file name "example-basic-01" -> "exampleBasic01" * Not match-pattern-group woodoo anymore, "knit.pattern" cannot have any user-defined match groups. * No need to look for "package xxx" in knitted sources, as the example's package is always ${knit.package}.${knit.name} * Simpler test names: testKotlinxCoroutinesGuideBasic01 -> testExampleBasic01 * Replaced END_TOC with END directive * Build-scripts are improved: - Consistent code to use mavenLocal when snapshots versions are used. - Proper substitution logic to use Android AAR files so that Dokka has correct links to Google APIs. - Google repository is added to all projects. --- README.md | 6 + build.gradle | 37 +- docs/basics.md | 35 +- docs/cancellation-and-timeouts.md | 19 +- docs/channels.md | 19 +- docs/compatibility.md | 8 +- docs/composing-suspending-functions.md | 20 +- docs/coroutine-context-and-dispatchers.md | 20 +- docs/debugging.md | 3 +- docs/exception-handling.md | 20 +- docs/flow.md | 20 +- docs/knit.code.include | 6 + docs/knit.properties | 22 + docs/knit.test.template | 27 + docs/select-expression.md | 23 +- docs/shared-mutable-state-and-concurrency.md | 21 +- gradle.properties | 3 +- .../build.gradle | 93 ++- .../test/TaskTest.kt | 4 +- knit/README.md | 13 - knit/build.gradle | 26 - knit/resources/knit.properties | 9 - knit/src/Knit.kt | 598 ------------------ kotlinx-coroutines-core/build.gradle | 3 +- .../jvm/test/guide/example-basic-01.kt | 6 +- .../jvm/test/guide/example-basic-02.kt | 6 +- .../jvm/test/guide/example-basic-02b.kt | 17 - .../jvm/test/guide/example-basic-03.kt | 14 +- .../jvm/test/guide/example-basic-03s.kt | 16 - .../jvm/test/guide/example-basic-04.kt | 28 +- .../jvm/test/guide/example-basic-05.kt | 19 +- .../jvm/test/guide/example-basic-05s.kt | 20 - .../jvm/test/guide/example-basic-06.kt | 24 +- .../jvm/test/guide/example-basic-07.kt | 21 +- .../jvm/test/guide/example-basic-08.kt | 17 + .../jvm/test/guide/example-basic-09.kt | 18 + .../jvm/test/guide/example-cancel-01.kt | 6 +- .../jvm/test/guide/example-cancel-02.kt | 6 +- .../jvm/test/guide/example-cancel-03.kt | 6 +- .../jvm/test/guide/example-cancel-04.kt | 6 +- .../jvm/test/guide/example-cancel-05.kt | 6 +- .../jvm/test/guide/example-cancel-06.kt | 6 +- .../jvm/test/guide/example-cancel-07.kt | 6 +- .../jvm/test/guide/example-channel-01.kt | 6 +- .../jvm/test/guide/example-channel-02.kt | 6 +- .../jvm/test/guide/example-channel-03.kt | 6 +- .../jvm/test/guide/example-channel-04.kt | 6 +- .../jvm/test/guide/example-channel-05.kt | 6 +- .../jvm/test/guide/example-channel-06.kt | 6 +- .../jvm/test/guide/example-channel-07.kt | 6 +- .../jvm/test/guide/example-channel-08.kt | 6 +- .../jvm/test/guide/example-channel-09.kt | 6 +- .../jvm/test/guide/example-channel-10.kt | 6 +- .../jvm/test/guide/example-compose-01.kt | 6 +- .../jvm/test/guide/example-compose-02.kt | 6 +- .../jvm/test/guide/example-compose-03.kt | 6 +- .../jvm/test/guide/example-compose-04.kt | 6 +- .../jvm/test/guide/example-compose-05.kt | 6 +- .../jvm/test/guide/example-compose-06.kt | 6 +- .../jvm/test/guide/example-context-01.kt | 6 +- .../jvm/test/guide/example-context-02.kt | 6 +- .../jvm/test/guide/example-context-03.kt | 6 +- .../jvm/test/guide/example-context-04.kt | 6 +- .../jvm/test/guide/example-context-05.kt | 6 +- .../jvm/test/guide/example-context-06.kt | 6 +- .../jvm/test/guide/example-context-07.kt | 6 +- .../jvm/test/guide/example-context-08.kt | 6 +- .../jvm/test/guide/example-context-09.kt | 6 +- .../jvm/test/guide/example-context-10.kt | 6 +- .../jvm/test/guide/example-context-11.kt | 6 +- .../jvm/test/guide/example-exceptions-01.kt | 6 +- .../jvm/test/guide/example-exceptions-02.kt | 6 +- .../jvm/test/guide/example-exceptions-03.kt | 6 +- .../jvm/test/guide/example-exceptions-04.kt | 6 +- .../jvm/test/guide/example-exceptions-05.kt | 6 +- .../jvm/test/guide/example-exceptions-06.kt | 6 +- .../jvm/test/guide/example-flow-01.kt | 6 +- .../jvm/test/guide/example-flow-02.kt | 6 +- .../jvm/test/guide/example-flow-03.kt | 6 +- .../jvm/test/guide/example-flow-04.kt | 6 +- .../jvm/test/guide/example-flow-05.kt | 6 +- .../jvm/test/guide/example-flow-06.kt | 6 +- .../jvm/test/guide/example-flow-07.kt | 6 +- .../jvm/test/guide/example-flow-08.kt | 6 +- .../jvm/test/guide/example-flow-09.kt | 6 +- .../jvm/test/guide/example-flow-10.kt | 6 +- .../jvm/test/guide/example-flow-11.kt | 6 +- .../jvm/test/guide/example-flow-12.kt | 6 +- .../jvm/test/guide/example-flow-13.kt | 6 +- .../jvm/test/guide/example-flow-14.kt | 6 +- .../jvm/test/guide/example-flow-15.kt | 6 +- .../jvm/test/guide/example-flow-16.kt | 6 +- .../jvm/test/guide/example-flow-17.kt | 6 +- .../jvm/test/guide/example-flow-18.kt | 6 +- .../jvm/test/guide/example-flow-19.kt | 6 +- .../jvm/test/guide/example-flow-20.kt | 6 +- .../jvm/test/guide/example-flow-21.kt | 6 +- .../jvm/test/guide/example-flow-22.kt | 6 +- .../jvm/test/guide/example-flow-23.kt | 6 +- .../jvm/test/guide/example-flow-24.kt | 6 +- .../jvm/test/guide/example-flow-25.kt | 6 +- .../jvm/test/guide/example-flow-26.kt | 6 +- .../jvm/test/guide/example-flow-27.kt | 6 +- .../jvm/test/guide/example-flow-28.kt | 6 +- .../jvm/test/guide/example-flow-29.kt | 6 +- .../jvm/test/guide/example-flow-30.kt | 6 +- .../jvm/test/guide/example-flow-31.kt | 6 +- .../jvm/test/guide/example-flow-32.kt | 6 +- .../jvm/test/guide/example-flow-33.kt | 6 +- .../jvm/test/guide/example-flow-34.kt | 6 +- .../jvm/test/guide/example-flow-35.kt | 6 +- .../jvm/test/guide/example-flow-36.kt | 6 +- .../jvm/test/guide/example-select-01.kt | 6 +- .../jvm/test/guide/example-select-02.kt | 6 +- .../jvm/test/guide/example-select-03.kt | 6 +- .../jvm/test/guide/example-select-04.kt | 6 +- .../jvm/test/guide/example-select-05.kt | 6 +- .../jvm/test/guide/example-supervision-01.kt | 6 +- .../jvm/test/guide/example-supervision-02.kt | 6 +- .../jvm/test/guide/example-supervision-03.kt | 6 +- .../jvm/test/guide/example-sync-01.kt | 6 +- .../jvm/test/guide/example-sync-02.kt | 6 +- .../jvm/test/guide/example-sync-03.kt | 6 +- .../jvm/test/guide/example-sync-04.kt | 6 +- .../jvm/test/guide/example-sync-05.kt | 6 +- .../jvm/test/guide/example-sync-06.kt | 6 +- .../jvm/test/guide/example-sync-07.kt | 6 +- .../jvm/test/guide/test/BasicsGuideTest.kt | 43 +- ...sGuideTest.kt => CancellationGuideTest.kt} | 37 +- .../jvm/test/guide/test/ChannelsGuideTest.kt | 47 +- .../jvm/test/guide/test/ComposingGuideTest.kt | 31 +- .../test/guide/test/DispatcherGuideTest.kt | 53 +- .../test/guide/test/ExceptionsGuideTest.kt | 43 +- .../jvm/test/guide/test/FlowGuideTest.kt | 159 ++--- .../jvm/test/guide/test/SelectGuideTest.kt | 27 +- .../test/guide/test/SharedStateGuideTest.kt | 35 +- .../jvm/test/guide/test/TestUtil.kt | 103 +-- reactive/knit.properties | 6 + reactive/knit.test.include | 11 + reactive/kotlinx-coroutines-reactor/README.md | 5 +- reactive/kotlinx-coroutines-rx2/README.md | 2 + settings.gradle | 1 - ui/coroutines-guide-ui.md | 58 +- ui/knit.code.include | 51 ++ ui/knit.properties | 7 + .../android-unit-tests/build.gradle | 6 +- .../test/guide/example-ui-actor-01.kt | 4 +- .../test/guide/example-ui-actor-02.kt | 4 +- .../test/guide/example-ui-actor-03.kt | 4 +- .../test/guide/example-ui-advanced-01.kt | 4 +- .../test/guide/example-ui-advanced-02.kt | 4 +- .../test/guide/example-ui-basic-01.kt | 4 +- .../test/guide/example-ui-basic-02.kt | 4 +- .../test/guide/example-ui-basic-03.kt | 4 +- .../test/guide/example-ui-blocking-01.kt | 4 +- .../test/guide/example-ui-blocking-02.kt | 4 +- .../test/guide/example-ui-blocking-03.kt | 4 +- 157 files changed, 914 insertions(+), 1662 deletions(-) create mode 100644 docs/knit.code.include create mode 100644 docs/knit.properties create mode 100644 docs/knit.test.template delete mode 100644 knit/README.md delete mode 100644 knit/build.gradle delete mode 100644 knit/resources/knit.properties delete mode 100644 knit/src/Knit.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/guide/example-basic-03s.kt delete mode 100644 kotlinx-coroutines-core/jvm/test/guide/example-basic-05s.kt create mode 100644 kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt create mode 100644 kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt rename kotlinx-coroutines-core/jvm/test/guide/test/{CancellationTimeOutsGuideTest.kt => CancellationGuideTest.kt} (60%) create mode 100644 reactive/knit.properties create mode 100644 reactive/knit.test.include create mode 100644 ui/knit.code.include create mode 100644 ui/knit.properties diff --git a/README.md b/README.md index bbd8726b42..274ca66961 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,12 @@ The `develop` branch is pushed to `master` during release. * Full release procedure checklist is [here](RELEASE.md). * Steps for contributing new integration modules are explained [here](integration/README.md#Contributing). +* Use [Knit](https://github.com/Kotlin/kotlinx-knit/blob/master/README.md) for updates to documentation: + * In project root directory run `./gradlew knit`. + * Commit updated documents and examples together with other changes. +* Use [Binary Compatibility Validator](https://github.com/Kotlin/binary-compatibility-validator/blob/master/README.md) for updates to public API: + * In project root directory run `./gradlew apiDump`. + * Commit updated API index together with other changes. diff --git a/build.gradle b/build.gradle index e03179dddb..e020937751 100644 --- a/build.gradle +++ b/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ import org.jetbrains.kotlin.konan.target.HostManager @@ -9,7 +9,7 @@ def rootModule = "kotlinx.coroutines" def coreModule = "kotlinx-coroutines-core" // Not applicable for Kotlin plugin def sourceless = ['kotlinx.coroutines', 'site', 'kotlinx-coroutines-bom'] -def internal = ['kotlinx.coroutines', 'site', 'benchmarks', 'knit', 'js-stub', 'stdlib-stubs'] +def internal = ['kotlinx.coroutines', 'site', 'benchmarks', 'js-stub', 'stdlib-stubs'] // Not published def unpublished = internal + ['example-frontend-js', 'android-unit-tests'] @@ -41,7 +41,16 @@ buildscript { } } - if (build_snapshot_train || atomicfu_version.endsWith("-SNAPSHOT")) { + // Determine if any project dependency is using a snapshot version + ext.using_snapshot_version = build_snapshot_train + rootProject.properties.each { key, value -> + if (key.endsWith("_version") && value instanceof String && value.endsWith("-SNAPSHOT")) { + println("NOTE: USING SNAPSHOT VERSION: $key=$value") + ext.using_snapshot_version=true + } + } + + if (using_snapshot_version) { repositories { mavenLocal() maven { url "https://oss.sonatype.org/content/repositories/snapshots" } @@ -67,6 +76,7 @@ buildscript { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version" classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version" + classpath "org.jetbrains.kotlinx:kotlinx-knit:$knit_version" classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version" classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version" @@ -102,7 +112,7 @@ allprojects { kotlin_version = rootProject.properties['kotlin_snapshot_version'] } - if (build_snapshot_train || atomicfu_version.endsWith("-SNAPSHOT") || lincheck_version.endsWith("-SNAPSHOT")) { + if (using_snapshot_version) { repositories { mavenLocal() maven { url "https://oss.sonatype.org/content/repositories/snapshots" } @@ -122,7 +132,7 @@ allprojects { apply plugin: "binary-compatibility-validator" apiValidation { - ignoredProjects += ["stdlib-stubs", "benchmarks", "knit", "site", + ignoredProjects += ["stdlib-stubs", "benchmarks", "site", "kotlinx-coroutines-bom", "android-unit-tests", "js-stub"] ignoredPackages += "kotlinx.coroutines.internal" } @@ -136,9 +146,7 @@ allprojects { * google should be first in the repository list because some of the play services * transitive dependencies was removed from jcenter, thus breaking gradle dependency resolution */ - if (projectName == "kotlinx-coroutines-play-services") { - google() - } + google() jcenter() maven { url "https://kotlin.bintray.com/kotlin-dev" @@ -251,7 +259,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { tasks.withType(dokka.getClass()) { externalDocumentationLink { url = new URL(core_docs_url) - packageListUrl = new URL("file://$core_docs_file") + packageListUrl = new File(core_docs_file).toURI().toURL() } } } @@ -267,3 +275,14 @@ task deploy(dependsOn: getTasksByName("publish", true) + getTasksByName("publish apply plugin: 'base' clean.dependsOn gradle.includedBuilds.collect { it.task(':clean') } + +// --------------- Knit configuration --------------- + +apply plugin: 'kotlinx-knit' + +knit { + siteRoot = "https://kotlin.github.io/kotlinx.coroutines" + moduleRoots = [".", "integration", "reactive", "ui"] +} + +knitPrepare.dependsOn getTasksByName("dokka", true) \ No newline at end of file diff --git a/docs/basics.md b/docs/basics.md index 6c3c0caa78..c5e931c58a 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -1,20 +1,4 @@ - - - + **Table of contents** @@ -30,8 +14,7 @@ class BasicsGuideTest { * [Coroutines ARE light-weight](#coroutines-are-light-weight) * [Global coroutines are like daemon threads](#global-coroutines-are-like-daemon-threads) - - + ## Coroutine Basics @@ -142,7 +125,7 @@ fun main() = runBlocking { // start main coroutine -> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt). +> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt). @@ -396,7 +379,7 @@ fun main() = runBlocking { -> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt). +> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt). You can run and see that it prints three lines and terminates: diff --git a/docs/cancellation-and-timeouts.md b/docs/cancellation-and-timeouts.md index ef4a9c9e09..b51c45c941 100644 --- a/docs/cancellation-and-timeouts.md +++ b/docs/cancellation-and-timeouts.md @@ -1,20 +1,5 @@ - -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.$$1$$2 ---> - - **Table of contents** @@ -27,7 +12,7 @@ class CancellationTimeOutsGuideTest { * [Run non-cancellable block](#run-non-cancellable-block) * [Timeout](#timeout) - + ## Cancellation and Timeouts diff --git a/docs/channels.md b/docs/channels.md index 5550759702..1d41774971 100644 --- a/docs/channels.md +++ b/docs/channels.md @@ -1,20 +1,5 @@ - -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.$$1$$2 ---> - - **Table of contents** @@ -31,7 +16,7 @@ class ChannelsGuideTest { * [Channels are fair](#channels-are-fair) * [Ticker channels](#ticker-channels) - + ## Channels diff --git a/docs/compatibility.md b/docs/compatibility.md index e56fc1be15..8dafae7293 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -1,9 +1,3 @@ - - * [Compatibility](#compatibility) @@ -19,7 +13,7 @@ * [Gradle](#gradle) * [Maven](#maven) - + ## Compatibility This document describes the compatibility policy of `kotlinx.coroutines` library since version 1.0.0 and semantics of compatibility-specific annotations. diff --git a/docs/composing-suspending-functions.md b/docs/composing-suspending-functions.md index 0cd02762ee..6a95d7585e 100644 --- a/docs/composing-suspending-functions.md +++ b/docs/composing-suspending-functions.md @@ -1,20 +1,4 @@ - - - + **Table of contents** @@ -27,7 +11,7 @@ class ComposingGuideTest { * [Async-style functions](#async-style-functions) * [Structured concurrency with async](#structured-concurrency-with-async) - + ## Composing Suspending Functions diff --git a/docs/coroutine-context-and-dispatchers.md b/docs/coroutine-context-and-dispatchers.md index 558b039744..e379842443 100644 --- a/docs/coroutine-context-and-dispatchers.md +++ b/docs/coroutine-context-and-dispatchers.md @@ -1,20 +1,4 @@ - - - + **Table of contents** @@ -33,7 +17,7 @@ class DispatchersGuideTest { * [Coroutine scope](#coroutine-scope) * [Thread-local data](#thread-local-data) - + ## Coroutine Context and Dispatchers diff --git a/docs/debugging.md b/docs/debugging.md index e2c7ec1e07..d3caa9aee6 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -9,8 +9,7 @@ * [Debug agent](#debug-agent) * [Debug agent and Android](#debug-agent-and-android) - - + ## Debugging coroutines Debugging asynchronous programs is challenging, because multiple concurrent coroutines are typically working at the same time. diff --git a/docs/exception-handling.md b/docs/exception-handling.md index 178f528ae2..08e63ea994 100644 --- a/docs/exception-handling.md +++ b/docs/exception-handling.md @@ -1,20 +1,5 @@ - -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.$$1$$2 ---> - - **Table of contents** @@ -29,7 +14,7 @@ class ExceptionsGuideTest { * [Supervision scope](#supervision-scope) * [Exceptions in supervised coroutines](#exceptions-in-supervised-coroutines) - + ## Exception Handling @@ -260,7 +245,6 @@ to leak to its exception handler. diff --git a/docs/flow.md b/docs/flow.md index ce4e80f1bb..705f338b20 100644 --- a/docs/flow.md +++ b/docs/flow.md @@ -1,20 +1,4 @@ - - - + **Table of contents** @@ -60,7 +44,7 @@ class FlowGuideTest { * [Launching flow](#launching-flow) * [Flow and Reactive Streams](#flow-and-reactive-streams) - + ## Asynchronous Flow diff --git a/docs/knit.code.include b/docs/knit.code.include new file mode 100644 index 0000000000..42f2b50e81 --- /dev/null +++ b/docs/knit.code.include @@ -0,0 +1,6 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from ${file.name} by Knit tool. Do not edit. +package ${knit.package}.${knit.name} \ No newline at end of file diff --git a/docs/knit.properties b/docs/knit.properties new file mode 100644 index 0000000000..ab2508a114 --- /dev/null +++ b/docs/knit.properties @@ -0,0 +1,22 @@ +# +# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# + +knit.package=kotlinx.coroutines.guide +knit.dir=../kotlinx-coroutines-core/jvm/test/guide/ +knit.pattern=example-[a-zA-Z0-9-]+-##\\.kt +knit.include=knit.code.include + +test.package=kotlinx.coroutines.guide.test +test.dir=../kotlinx-coroutines-core/jvm/test/guide/test/ +test.template=knit.test.template + +# Various test validation modes and their corresponding methods from TestUtil +test.mode.=verifyLines +test.mode.STARTS_WITH=verifyLinesStartWith +test.mode.ARBITRARY_TIME=verifyLinesArbitraryTime +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 diff --git a/docs/knit.test.template b/docs/knit.test.template new file mode 100644 index 0000000000..a912555a43 --- /dev/null +++ b/docs/knit.test.template @@ -0,0 +1,27 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from ${file.name} by Knit tool. Do not edit. +package ${test.package} + +import org.junit.Test + +class ${test.name} { +<#list cases as case><#assign method = test["mode.${case.param}"]!"custom"> + @Test + fun test${case.name}() { + test("${case.name}") { ${case.knit.package}.${case.knit.name}.main() }<#if method != "custom">.${method}( +<#list case.lines as line> + "${line?j_string}"<#sep>, + + ) +<#else>.also { lines -> + check(${case.param}) + } + + } +<#sep> + + +} \ No newline at end of file diff --git a/docs/select-expression.md b/docs/select-expression.md index f36fa09b6b..5809e7b93e 100644 --- a/docs/select-expression.md +++ b/docs/select-expression.md @@ -1,21 +1,4 @@ - - - - + **Table of contents** @@ -28,9 +11,7 @@ class SelectGuideTest { * [Selecting deferred values](#selecting-deferred-values) * [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values) - - - + ## Select Expression (experimental) diff --git a/docs/shared-mutable-state-and-concurrency.md b/docs/shared-mutable-state-and-concurrency.md index 30d7334e6c..1a3c406472 100644 --- a/docs/shared-mutable-state-and-concurrency.md +++ b/docs/shared-mutable-state-and-concurrency.md @@ -1,20 +1,5 @@ - - - + + **Table of contents** @@ -28,7 +13,7 @@ class SharedStateGuideTest { * [Mutual exclusion](#mutual-exclusion) * [Actors](#actors) - + ## Shared mutable state and concurrency diff --git a/gradle.properties b/gradle.properties index b693ededcd..38fdeb03d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # # Kotlin @@ -10,6 +10,7 @@ kotlin_version=1.3.61 # Dependencies junit_version=4.12 atomicfu_version=0.14.1 +knit_version=0.1.2 html_version=0.6.8 lincheck_version=2.5.3 dokka_version=0.9.16-rdev-2-mpp-hacks diff --git a/integration/kotlinx-coroutines-play-services/build.gradle b/integration/kotlinx-coroutines-play-services/build.gradle index 61201faeb7..eb554866ed 100644 --- a/integration/kotlinx-coroutines-play-services/build.gradle +++ b/integration/kotlinx-coroutines-play-services/build.gradle @@ -1,32 +1,43 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +import org.gradle.api.artifacts.transform.* + import java.nio.file.Files -import java.nio.file.NoSuchFileException import java.util.zip.ZipEntry import java.util.zip.ZipFile -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - ext.tasks_version = '16.0.1' -def attr = Attribute.of("artifactType", String.class) -configurations { - aar { - attributes { attribute(attr, ArtifactTypeDefinition.JAR_TYPE) } - sourceSets.main.compileClasspath += it - sourceSets.test.compileClasspath += it - sourceSets.test.runtimeClasspath += it +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 { - registerTransform { - from.attribute(attr, "aar") - to.attribute(attr, "jar") - artifactTransform(ExtractJars.class) + attributesSchema { + attribute(unpackedAar) + } + + artifactTypes { + aar { + attributes.attribute(unpackedAar, false) + } } - aar("com.google.android.gms:play-services-tasks:$tasks_version") { + 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' } } @@ -37,48 +48,32 @@ tasks.withType(dokka.getClass()) { // This is workaround for missing package list in Google API packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL() } - - afterEvaluate { - classpath += project.configurations.aar.files - } } -class ExtractJars extends ArtifactTransform { - @Override - List transform(File input) { - unzip(input) - - List jars = new ArrayList<>() - outputDirectory.traverse(nameFilter: ~/.*\.jar/) { jars += it } +abstract class UnpackAar implements TransformAction { + @InputArtifact + abstract Provider getInputArtifact() - return jars - } - - private void unzip(File zipFile) { - ZipFile zip + @Override + void transform(TransformOutputs outputs) { + ZipFile zip = new ZipFile(inputArtifact.get().asFile) try { - zip = new ZipFile(zipFile) for (entry in zip.entries()) { - unzipEntryTo(zip, entry) + if (!entry.isDirectory() && entry.name.endsWith(".jar")) { + unzipEntryTo(zip, entry, outputs.file(entry.name)) + } } } finally { - if (zip != null) zip.close() + zip.close() } } - private void unzipEntryTo(ZipFile zip, ZipEntry entry) { - File output = new File(outputDirectory, entry.name) - if (entry.isDirectory()) { - output.mkdirs() - } else { - InputStream stream - try { - stream = zip.getInputStream(entry) - Files.copy(stream, output.toPath()) - } catch (NoSuchFileException ignored) { - } finally { - if (stream != null) stream.close() - } + private static void unzipEntryTo(ZipFile zip, ZipEntry entry, File output) { + InputStream stream = zip.getInputStream(entry) + try { + Files.copy(stream, output.toPath()) + } finally { + stream.close() } } } diff --git a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt index b87a295449..0f125ac98c 100644 --- a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt +++ b/integration/kotlinx-coroutines-play-services/test/TaskTest.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.tasks @@ -61,7 +61,7 @@ class TaskTest : TestBase() { @Test fun testThrowingAsTask() { - val deferred = GlobalScope.async { + val deferred = GlobalScope.async { throw TestException("Fail") } diff --git a/knit/README.md b/knit/README.md deleted file mode 100644 index ca0560fa6c..0000000000 --- a/knit/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Knit - -This is a very simple tool that produces Kotlin source example files from a markdown document that includes -snippets of Kotlin code in its body. It is used to produce examples for -[coroutines guide](../docs/coroutines-guide.md) and other markdown documents. -It also includes links to the documentation web site into the documents. - -## Usage - -* In project root directory do: - * Run `./gradlew knit` -* Commit updated documents and examples - diff --git a/knit/build.gradle b/knit/build.gradle deleted file mode 100644 index 0410d5d268..0000000000 --- a/knit/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -apply plugin: "application" - -sourceSets { - main.kotlin.srcDirs = ['src'] - main.java.srcDirs = ['src'] - main.resources.srcDirs = ['resources'] -} - -FileTree mdFiles = fileTree(project.rootDir) { - include '**/*.md' - exclude '**/build/**' - exclude '**/.gradle/**' - exclude '**/node_modules/**' -} - -mainClassName = "KnitKt" - -run.dependsOn rootProject.getTasksByName("dokka", true) -run.args = mdFiles -run.workingDir = project.rootDir - -task knit(dependsOn: run) diff --git a/knit/resources/knit.properties b/knit/resources/knit.properties deleted file mode 100644 index 146c182339..0000000000 --- a/knit/resources/knit.properties +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -site.root=https://kotlin.github.io/kotlinx.coroutines - -module.roots=. integration reactive ui -module.marker=build.gradle -module.docs=build/dokka \ No newline at end of file diff --git a/knit/src/Knit.kt b/knit/src/Knit.kt deleted file mode 100644 index 30dd678fd1..0000000000 --- a/knit/src/Knit.kt +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -import java.io.* -import java.util.* -import kotlin.properties.* - -// --- props in knit.properties - -val knitProperties = ClassLoader.getSystemClassLoader() - .getResource("knit.properties").openStream().use { Properties().apply { load(it) } } - -val siteRoot = knitProperties.getProperty("site.root")!! -val moduleRoots = knitProperties.getProperty("module.roots").split(" ") -val moduleMarker = knitProperties.getProperty("module.marker")!! -val moduleDocs = knitProperties.getProperty("module.docs")!! - -// --- markdown syntax - -const val DIRECTIVE_START = "" - -const val TOC_DIRECTIVE = "TOC" -const val TOC_REF_DIRECTIVE = "TOC_REF" -const val KNIT_DIRECTIVE = "KNIT" -const val INCLUDE_DIRECTIVE = "INCLUDE" -const val CLEAR_DIRECTIVE = "CLEAR" -const val TEST_DIRECTIVE = "TEST" - -const val KNIT_AUTONUMBER_PLACEHOLDER = '#' -const val KNIT_AUTONUMBER_REGEX = "([0-9a-z]+)" - -const val TEST_OUT_DIRECTIVE = "TEST_OUT" - -const val MODULE_DIRECTIVE = "MODULE" -const val INDEX_DIRECTIVE = "INDEX" - -const val CODE_START = "```kotlin" -const val CODE_END = "```" - -const val SAMPLE_START = "//sampleStart" -const val SAMPLE_END = "//sampleEnd" - -const val TEST_START = "```text" -const val TEST_END = "```" - -const val SECTION_START = "##" - -const val PACKAGE_PREFIX = "package " -const val STARTS_WITH_PREDICATE = "STARTS_WITH" -const val ARBITRARY_TIME_PREDICATE = "ARBITRARY_TIME" -const val FLEXIBLE_TIME_PREDICATE = "FLEXIBLE_TIME" -const val FLEXIBLE_THREAD_PREDICATE = "FLEXIBLE_THREAD" -const val LINES_START_UNORDERED_PREDICATE = "LINES_START_UNORDERED" -const val EXCEPTION_MODE = "EXCEPTION" -const val LINES_START_PREDICATE = "LINES_START" - -val API_REF_REGEX = Regex("(^|[ \\](])\\[([A-Za-z0-9_().]+)]($|[^\\[(])") -val LINK_DEF_REGEX = Regex("^\\[([A-Za-z0-9_().]+)]: .*") - -val tocRefMap = HashMap>() -val fileSet = HashSet() -val fileQueue = ArrayDeque() - -fun main(args: Array) { - if (args.isEmpty()) { - println("Usage: Knit ") - return - } - args.map { File(it) }.toCollection(fileQueue) - fileQueue.toCollection(fileSet) - while (!fileQueue.isEmpty()) { - if (!knit(fileQueue.removeFirst())) System.exit(1) // abort on first error with error exit code - } -} - -fun knit(markdownFile: File): Boolean { - println("*** Reading $markdownFile") - val tocLines = arrayListOf() - var knitRegex: Regex? = null - var knitAutonumberGroup = 0 - var knitAutonumberDigits = 0 - var knitAutonumberIndex = 1 - val includes = arrayListOf() - val codeLines = arrayListOf() - val testLines = arrayListOf() - var testOut: String? = null - val testOutLines = arrayListOf() - var lastPgk: String? = null - val files = mutableSetOf() - val allApiRefs = arrayListOf() - val remainingApiRefNames = mutableSetOf() - var moduleName: String by Delegates.notNull() - var docsRoot: String by Delegates.notNull() - var retryKnitLater = false - val tocRefs = ArrayList().also { tocRefMap[markdownFile] = it } - // read markdown file - val markdown = markdownFile.withMarkdownTextReader { - mainLoop@ while (true) { - val inLine = readLine() ?: break - val directive = directive(inLine) - if (directive != null && markdownPart == MarkdownPart.TOC) { - markdownPart = MarkdownPart.POST_TOC - postTocText += inLine - } - when (directive?.name) { - TOC_DIRECTIVE -> { - requireSingleLine(directive) - require(directive.param.isEmpty()) { "$TOC_DIRECTIVE directive must not have parameters" } - require(markdownPart == MarkdownPart.PRE_TOC) { "Only one TOC directive is supported" } - markdownPart = MarkdownPart.TOC - } - TOC_REF_DIRECTIVE -> { - requireSingleLine(directive) - require(!directive.param.isEmpty()) { "$TOC_REF_DIRECTIVE directive must include reference file path" } - val refPath = directive.param - val refFile = File(markdownFile.parent, refPath.replace('/', File.separatorChar)) - require(fileSet.contains(refFile)) { "Referenced file $refFile is missing from the processed file set" } - val toc = tocRefMap[refFile] - if (toc == null) { - retryKnitLater = true // put this file at the end of the queue and retry later - } else { - val lines = toc.map { (levelPrefix, name, ref) -> - "$levelPrefix [$name]($refPath#$ref)" - } - if (!replaceUntilNextDirective(lines)) error("Unexpected end of file after $TOC_REF_DIRECTIVE") - } - } - KNIT_DIRECTIVE -> { - requireSingleLine(directive) - require(!directive.param.isEmpty()) { "$KNIT_DIRECTIVE directive must include regex parameter" } - require(knitRegex == null) { "Only one KNIT directive is supported"} - var str = directive.param - val i = str.indexOf(KNIT_AUTONUMBER_PLACEHOLDER) - if (i >= 0) { - val j = str.lastIndexOf(KNIT_AUTONUMBER_PLACEHOLDER) - knitAutonumberDigits = j - i + 1 - require(str.substring(i, j + 1) == KNIT_AUTONUMBER_PLACEHOLDER.toString().repeat(knitAutonumberDigits)) { - "$KNIT_DIRECTIVE can only use a contiguous range of '$KNIT_AUTONUMBER_PLACEHOLDER' for auto-numbering" - } - knitAutonumberGroup = str.substring(0, i).count { it == '(' } + 2 // note: it does not understand escaped open braces - str = str.substring(0, i) + KNIT_AUTONUMBER_REGEX + str.substring(j + 1) - } - knitRegex = Regex("\\((" + str + ")\\)") - continue@mainLoop - } - INCLUDE_DIRECTIVE -> { - if (directive.param.isEmpty()) { - require(!directive.singleLine) { "$INCLUDE_DIRECTIVE directive without parameters must not be single line" } - readUntilTo(DIRECTIVE_END, codeLines) - } else { - val include = Include(Regex(directive.param)) - if (directive.singleLine) { - include.lines += codeLines - codeLines.clear() - } else { - readUntilTo(DIRECTIVE_END, include.lines) - } - includes += include - } - continue@mainLoop - } - CLEAR_DIRECTIVE -> { - requireSingleLine(directive) - require(directive.param.isEmpty()) { "$CLEAR_DIRECTIVE directive must not have parameters" } - codeLines.clear() - continue@mainLoop - } - TEST_OUT_DIRECTIVE -> { - require(!directive.param.isEmpty()) { "$TEST_OUT_DIRECTIVE directive must include file name parameter" } - flushTestOut(markdownFile.parentFile, testOut, testOutLines) - testOut = directive.param - readUntil(DIRECTIVE_END).forEach { testOutLines += it } - } - TEST_DIRECTIVE -> { - require(lastPgk != null) { "'$PACKAGE_PREFIX' prefix was not found in emitted code"} - require(testOut != null) { "$TEST_OUT_DIRECTIVE directive was not specified" } - val predicate = directive.param - if (testLines.isEmpty()) { - if (directive.singleLine) { - require(!predicate.isEmpty()) { "$TEST_OUT_DIRECTIVE must be preceded by $TEST_START block or contain test predicate"} - } else - testLines += readUntil(DIRECTIVE_END) - } else { - requireSingleLine(directive) - } - makeTest(testOutLines, lastPgk!!, testLines, predicate) - testLines.clear() - } - MODULE_DIRECTIVE -> { - requireSingleLine(directive) - moduleName = directive.param - docsRoot = findModuleRootDir(moduleName) + "/" + moduleDocs + "/" + moduleName - } - INDEX_DIRECTIVE -> { - requireSingleLine(directive) - val indexLines = processApiIndex("$siteRoot/$moduleName", docsRoot, directive.param, remainingApiRefNames) - ?: throw IllegalArgumentException("Failed to load index for ${directive.param}") - if (!replaceUntilNextDirective(indexLines)) error("Unexpected end of file after $INDEX_DIRECTIVE") - } - } - if (inLine.startsWith(CODE_START)) { - require(testOut == null || testLines.isEmpty()) { "Previous test was not emitted with $TEST_DIRECTIVE" } - codeLines += "" - readUntilTo(CODE_END, codeLines) { line -> - !line.startsWith(SAMPLE_START) && !line.startsWith(SAMPLE_END) - } - continue@mainLoop - } - if (inLine.startsWith(TEST_START)) { - require(testOut == null || testLines.isEmpty()) { "Previous test was not emitted with $TEST_DIRECTIVE" } - readUntilTo(TEST_END, testLines) - continue@mainLoop - } - if (inLine.startsWith(SECTION_START) && markdownPart == MarkdownPart.POST_TOC) { - val i = inLine.indexOf(' ') - require(i >= 2) { "Invalid section start" } - val name = inLine.substring(i + 1).trim() - val levelPrefix = " ".repeat(i - 2) + "*" - val sectionRef = makeSectionRef(name) - tocLines += "$levelPrefix [$name](#$sectionRef)" - tocRefs += TocRef(levelPrefix, name, sectionRef) - continue@mainLoop - } - val linkDefMatch = LINK_DEF_REGEX.matchEntire(inLine) - if (linkDefMatch != null) { - val name = linkDefMatch.groups[1]!!.value - remainingApiRefNames -= name - } else { - for (match in API_REF_REGEX.findAll(inLine)) { - val apiRef = ApiRef(lineNumber, match.groups[2]!!.value) - allApiRefs += apiRef - remainingApiRefNames += apiRef.name - } - } - knitRegex?.find(inLine)?.let knitRegexMatch@{ knitMatch -> - val fileName = knitMatch.groups[1]!!.value - if (knitAutonumberDigits != 0) { - val numGroup = knitMatch.groups[knitAutonumberGroup]!! - val num = knitAutonumberIndex.toString().padStart(knitAutonumberDigits, '0') - if (numGroup.value != num) { // update and retry with this line if a different number - val r = numGroup.range - val newLine = inLine.substring(0, r.first) + num + inLine.substring(r.last + 1) - updateLineAndRetry(newLine) - return@knitRegexMatch - } - } - knitAutonumberIndex++ - val file = File(markdownFile.parentFile, fileName) - require(files.add(file)) { "Duplicate file: $file"} - println("Knitting $file ...") - val outLines = arrayListOf() - for (include in includes) { - val includeMatch = include.regex.matchEntire(fileName) ?: continue - include.lines.forEach { includeLine -> - val line = makeReplacements(includeLine, includeMatch) - if (line.startsWith(PACKAGE_PREFIX)) - lastPgk = line.substring(PACKAGE_PREFIX.length).trim() - outLines += line - } - } - for (code in codeLines) { - outLines += code.replace("System.currentTimeMillis()", "currentTimeMillis()") - } - codeLines.clear() - writeLinesIfNeeded(file, outLines) - } - } - } ?: return false // false when failed - // bailout if retry was requested - if (retryKnitLater) { - fileQueue.add(markdownFile) - return true - } - // update markdown file with toc - val newLines = buildList { - addAll(markdown.preTocText) - if (!tocLines.isEmpty()) { - add("") - addAll(tocLines) - add("") - } - addAll(markdown.postTocText) - } - if (newLines != markdown.inText) writeLines(markdownFile, newLines) - // check apiRefs - for (apiRef in allApiRefs) { - if (apiRef.name in remainingApiRefNames) { - println("WARNING: $markdownFile: ${apiRef.line}: Broken reference to [${apiRef.name}]") - } - } - // write test output - flushTestOut(markdownFile.parentFile, testOut, testOutLines) - return true -} - -data class TocRef(val levelPrefix: String, val name: String, val ref: String) - -fun makeTest(testOutLines: MutableList, pgk: String, test: List, predicate: String) { - val funName = buildString { - var cap = true - for (c in pgk) { - if (c == '.') { - cap = true - } else { - append(if (cap) c.toUpperCase() else c) - cap = false - } - } - } - testOutLines += "" - testOutLines += " @Test" - testOutLines += " fun test$funName() {" - val prefix = " test(\"$funName\") { $pgk.main() }" - when (predicate) { - "" -> makeTestLines(testOutLines, prefix, "verifyLines", test) - STARTS_WITH_PREDICATE -> makeTestLines(testOutLines, prefix, "verifyLinesStartWith", test) - ARBITRARY_TIME_PREDICATE -> makeTestLines(testOutLines, prefix, "verifyLinesArbitraryTime", test) - FLEXIBLE_TIME_PREDICATE -> makeTestLines(testOutLines, prefix, "verifyLinesFlexibleTime", test) - FLEXIBLE_THREAD_PREDICATE -> makeTestLines(testOutLines, prefix, "verifyLinesFlexibleThread", test) - LINES_START_UNORDERED_PREDICATE -> makeTestLines(testOutLines, prefix, "verifyLinesStartUnordered", test) - EXCEPTION_MODE -> makeTestLines(testOutLines, prefix, "verifyExceptions", test) - LINES_START_PREDICATE -> makeTestLines(testOutLines, prefix, "verifyLinesStart", test) - else -> { - testOutLines += "$prefix.also { lines ->" - testOutLines += " check($predicate)" - testOutLines += " }" - } - } - testOutLines += " }" -} - -private fun makeTestLines(testOutLines: MutableList, prefix: String, method: String, test: List) { - testOutLines += "$prefix.$method(" - for ((index, testLine) in test.withIndex()) { - val commaOpt = if (index < test.size - 1) "," else "" - val escapedLine = testLine.replace("\"", "\\\"") - testOutLines += " \"$escapedLine\"$commaOpt" - } - testOutLines += " )" -} - -private fun makeReplacements(line: String, match: MatchResult): String { - var result = line - for ((id, group) in match.groups.withIndex()) { - if (group != null) - result = result.replace("\$\$$id", group.value) - } - return result -} - -private fun flushTestOut(parentDir: File?, testOut: String?, testOutLines: MutableList) { - if (testOut == null) return - val file = File(parentDir, testOut) - testOutLines += "}" - writeLinesIfNeeded(file, testOutLines) - testOutLines.clear() -} - -private fun MarkdownTextReader.readUntil(marker: String): List = - arrayListOf().also { readUntilTo(marker, it) } - -private fun MarkdownTextReader.readUntilTo(marker: String, list: MutableList, linePredicate: (String) -> Boolean = { true }) { - while (true) { - val line = readLine() ?: break - if (line.startsWith(marker)) break - if (linePredicate(line)) list += line - } -} - -private inline fun buildList(block: ArrayList.() -> Unit): List { - val result = arrayListOf() - result.block() - return result -} - -private fun requireSingleLine(directive: Directive) { - require(directive.singleLine) { "${directive.name} directive must end on the same line with '$DIRECTIVE_END'" } -} - -fun makeSectionRef(name: String): String = name - .replace(' ', '-') - .replace(".", "") - .replace(",", "") - .replace("(", "") - .replace(")", "") - .replace("`", "") - .toLowerCase() - -class Include(val regex: Regex, val lines: MutableList = arrayListOf()) - -class Directive( - val name: String, - val param: String, - val singleLine: Boolean -) - -fun directive(line: String): Directive? { - if (!line.startsWith(DIRECTIVE_START)) return null - var s = line.substring(DIRECTIVE_START.length).trim() - val singleLine = s.endsWith(DIRECTIVE_END) - if (singleLine) s = s.substring(0, s.length - DIRECTIVE_END.length) - val i = s.indexOf(' ') - val name = if (i < 0) s else s.substring(0, i) - val param = if (i < 0) "" else s.substring(i).trim() - return Directive(name, param, singleLine) -} - -class ApiRef(val line: Int, val name: String) - -enum class MarkdownPart { PRE_TOC, TOC, POST_TOC } - -class MarkdownTextReader(r: Reader) : LineNumberReader(r) { - val inText = arrayListOf() - val preTocText = arrayListOf() - val postTocText = arrayListOf() - var markdownPart: MarkdownPart = MarkdownPart.PRE_TOC - var skip = false - var putBackLine: String? = null - - val outText: MutableList get() = when (markdownPart) { - MarkdownPart.PRE_TOC -> preTocText - MarkdownPart.POST_TOC -> postTocText - else -> throw IllegalStateException("Wrong state: $markdownPart") - } - - override fun readLine(): String? { - putBackLine?.let { - putBackLine = null - return it - } - val line = super.readLine() ?: return null - inText += line - if (!skip && markdownPart != MarkdownPart.TOC) - outText += line - return line - } - - fun updateLineAndRetry(line: String) { - outText.removeAt(outText.lastIndex) - outText += line - putBackLine = line - } - - fun replaceUntilNextDirective(lines: List): Boolean { - skip = true - while (true) { - val skipLine = readLine() ?: return false - if (directive(skipLine) != null) { - putBackLine = skipLine - break - } - } - skip = false - outText += lines - outText += putBackLine!! - return true - } -} - -fun File.withLineNumberReader(factory: (Reader) -> T, block: T.() -> Unit): T? { - val reader = factory(reader()) - reader.use { - try { - it.block() - } catch (e: Exception) { - println("ERROR: ${this@withLineNumberReader}: ${it.lineNumber}: ${e.message}") - return null - } - } - return reader -} - -fun File.withMarkdownTextReader(block: MarkdownTextReader.() -> Unit): MarkdownTextReader? = - withLineNumberReader(::MarkdownTextReader, block) - -fun writeLinesIfNeeded(file: File, outLines: List) { - val oldLines = try { - file.readLines() - } catch (e: IOException) { - emptyList() - } - if (outLines != oldLines) writeLines(file, outLines) -} - -fun writeLines(file: File, lines: List) { - println(" Writing $file ...") - file.parentFile?.mkdirs() - file.printWriter().use { out -> - lines.forEach { out.println(it) } - } -} - -fun findModuleRootDir(name: String): String = - moduleRoots - .map { "$it/$name" } - .firstOrNull { File("$it/$moduleMarker").exists() } - ?: throw IllegalArgumentException("Module $name is not found in any of the module root dirs") - -data class ApiIndexKey( - val docsRoot: String, - val pkg: String -) - -val apiIndexCache: MutableMap>> = HashMap() - -val REF_LINE_REGEX = Regex("([a-zA-z0-9.]+)") -val INDEX_HTML = "/index.html" -val INDEX_MD = "/index.md" -val FUNCTIONS_SECTION_HEADER = "### Functions" - -fun HashMap>.putUnambiguous(key: String, value: String) { - val oldValue = this[key] - if (oldValue != null) { - oldValue.add(value) - put(key, oldValue) - } else { - put(key, mutableListOf(value)) - } -} - -fun loadApiIndex( - docsRoot: String, - path: String, - pkg: String, - namePrefix: String = "" -): Map>? { - val fileName = "$docsRoot/$path$INDEX_MD" - val visited = mutableSetOf() - val map = HashMap>() - var inFunctionsSection = false - File(fileName).withLineNumberReader(::LineNumberReader) { - while (true) { - val line = readLine() ?: break - if (line == FUNCTIONS_SECTION_HEADER) inFunctionsSection = true - val result = REF_LINE_REGEX.matchEntire(line) ?: continue - val link = result.groups[1]!!.value - if (link.startsWith("..")) continue // ignore cross-references - val absLink = "$path/$link" - var name = result.groups[2]!!.value - // a special disambiguation fix for pseudo-constructor functions - if (inFunctionsSection && name[0] in 'A'..'Z') name += "()" - val refName = namePrefix + name - val fqName = "$pkg.$refName" - // Put shorter names for extensions on 3rd party classes (prefix is FQname of those classes) - if (namePrefix != "" && namePrefix[0] in 'a'..'z') { - val i = namePrefix.dropLast(1).lastIndexOf('.') - if (i >= 0) map.putUnambiguous(namePrefix.substring(i + 1) + name, absLink) - map.putUnambiguous(name, absLink) - } - // Disambiguate lower-case names with leading underscore (e.g. Flow class vs flow builder ambiguity) - if (namePrefix == "" && name[0] in 'a'..'z') { - map.putUnambiguous("_$name", absLink) - } - // Always put fully qualified names - map.putUnambiguous(refName, absLink) - map.putUnambiguous(fqName, absLink) - if (link.endsWith(INDEX_HTML)) { - if (visited.add(link)) { - val path2 = path + "/" + link.substring(0, link.length - INDEX_HTML.length) - map += loadApiIndex(docsRoot, path2, pkg, "$refName.") - ?: throw IllegalArgumentException("Failed to parse $docsRoot/$path2") - } - } - } - } ?: return null // return null on failure - return map -} - -fun processApiIndex( - siteRoot: String, - docsRoot: String, - pkg: String, - remainingApiRefNames: MutableSet -): List? { - val key = ApiIndexKey(docsRoot, pkg) - val map = apiIndexCache.getOrPut(key, { - print("Parsing API docs at $docsRoot/$pkg: ") - val result = loadApiIndex(docsRoot, pkg, pkg) ?: return null // null on failure - println("${result.size} definitions") - result - }) - val indexList = arrayListOf() - val it = remainingApiRefNames.iterator() - while (it.hasNext()) { - val refName = it.next() - val refLink = map[refName] ?: continue - if (refLink.size > 1) { - println("INFO: Ambiguous reference to [$refName]: $refLink, taking the shortest one") - } - - val link = refLink.minBy { it.length } - indexList += "[$refName]: $siteRoot/$link" - it.remove() - } - return indexList -} diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index 832321493a..547a12b4c6 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: 'kotlin-multiplatform' @@ -57,6 +57,7 @@ compileKotlinMetadata { kotlin.sourceSets { jvmTest.dependencies { api "org.jetbrains.kotlinx:lincheck:$lincheck_version" + api "org.jetbrains.kotlinx:kotlinx-knit-test:$knit_version" api "com.esotericsoftware:kryo:4.0.0" implementation project (":android-unit-tests") } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt index dcb36af536..15e126149b 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic01 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic01 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt index 4f1277d4a4..4f178ca6b3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic02 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic02 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt deleted file mode 100644 index a78840d5e1..0000000000 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic02b - -import kotlinx.coroutines.* - -fun main() = runBlocking { // start main coroutine - GlobalScope.launch { // launch a new coroutine in background and continue - delay(1000L) - println("World!") - } - println("Hello,") // main coroutine continues here immediately - delay(2000L) // delaying for 2 seconds to keep JVM alive -} diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt index a35e848196..f80113c57f 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt @@ -1,17 +1,17 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic03 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic03 import kotlinx.coroutines.* -fun main() = runBlocking { - val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job +fun main() = runBlocking { // start main coroutine + GlobalScope.launch { // launch a new coroutine in background and continue delay(1000L) println("World!") } - println("Hello,") - job.join() // wait until child coroutine completes + println("Hello,") // main coroutine continues here immediately + delay(2000L) // delaying for 2 seconds to keep JVM alive } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-03s.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03s.kt deleted file mode 100644 index 13cf679ab9..0000000000 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-03s.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic03s - -import kotlinx.coroutines.* - -fun main() = runBlocking { // this: CoroutineScope - launch { // launch a new coroutine in the scope of runBlocking - delay(1000L) - println("World!") - } - println("Hello,") -} diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt index 3afa0fe5c7..33c928a008 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt @@ -1,27 +1,17 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic04 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic04 import kotlinx.coroutines.* -fun main() = runBlocking { // this: CoroutineScope - launch { - delay(200L) - println("Task from runBlocking") +fun main() = runBlocking { + val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job + delay(1000L) + println("World!") } - - coroutineScope { // Creates a coroutine scope - launch { - delay(500L) - println("Task from nested launch") - } - - delay(100L) - println("Task from coroutine scope") // This line will be printed before the nested launch - } - - println("Coroutine scope is over") // This line is not printed until the nested launch completes + println("Hello,") + job.join() // wait until child coroutine completes } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt index e6a911291d..52b490d2b7 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt @@ -1,19 +1,16 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic05 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic05 import kotlinx.coroutines.* -fun main() = runBlocking { - launch { doWorld() } +fun main() = runBlocking { // this: CoroutineScope + launch { // launch a new coroutine in the scope of runBlocking + delay(1000L) + println("World!") + } println("Hello,") } - -// this is your first suspending function -suspend fun doWorld() { - delay(1000L) - println("World!") -} diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-05s.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05s.kt deleted file mode 100644 index 876f9a1aeb..0000000000 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-05s.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic05s - -import kotlinx.coroutines.* - -fun main(args: Array) = runBlocking { - launchDoWorld() - println("Hello,") -} - -// this is your first suspending function -suspend fun launchDoWorld() = coroutineScope { - launch { - println("World!") - } -} diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt index 60de941d49..a1b5bc5f23 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt @@ -1,17 +1,27 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic06 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic06 import kotlinx.coroutines.* -fun main() = runBlocking { - repeat(100_000) { // launch a lot of coroutines +fun main() = runBlocking { // this: CoroutineScope + launch { + delay(200L) + println("Task from runBlocking") + } + + coroutineScope { // Creates a coroutine scope launch { - delay(1000L) - print(".") + delay(500L) + println("Task from nested launch") } + + delay(100L) + println("Task from coroutine scope") // This line will be printed before the nested launch } + + println("Coroutine scope is over") // This line is not printed until the nested launch completes } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt index 56e785fb7f..32c02b86e5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt @@ -1,18 +1,19 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.basic07 +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic07 import kotlinx.coroutines.* fun main() = runBlocking { - GlobalScope.launch { - repeat(1000) { i -> - println("I'm sleeping $i ...") - delay(500L) - } - } - delay(1300L) // just quit after delay + launch { doWorld() } + println("Hello,") +} + +// this is your first suspending function +suspend fun doWorld() { + delay(1000L) + println("World!") } diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt new file mode 100644 index 0000000000..ff11eb70d7 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-08.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic08 + +import kotlinx.coroutines.* + +fun main() = runBlocking { + repeat(100_000) { // launch a lot of coroutines + launch { + delay(1000L) + print(".") + } + } +} diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt new file mode 100644 index 0000000000..9f998b5244 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/guide/example-basic-09.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from basics.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleBasic09 + +import kotlinx.coroutines.* + +fun main() = runBlocking { + GlobalScope.launch { + repeat(1000) { i -> + println("I'm sleeping $i ...") + delay(500L) + } + } + delay(1300L) // just quit after delay +} diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt index ebf5171e2e..a1b036d91f 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel01 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel01 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt index e3127b41ba..f6dec6e8f4 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel02 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel02 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt index d47ecd9dda..3daaf49b36 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel03 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel03 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt index 45c97851aa..b1b9a9bfd5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel04 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel04 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt index 9f2cac1c23..9772ae5739 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel05 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel05 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt index f06d1187e4..e1afd057c4 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel06 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel06 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt index e2880c9129..8c57b42903 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.cancel07 +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCancel07 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt index 36c6db316b..0af1ebd311 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel01 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel01 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt index 59f5a76807..33eb7b33dd 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel02 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel02 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt index 5c9cfb181f..4a2613be6a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel03 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel03 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt index 4eb6c37d2c..fe39814640 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel04 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel04 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt index 8b80764af5..1f129f3739 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel05 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel05 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt index 452e056d34..b78fcc90ef 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel06 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel06 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt index 9fc852e5c0..84de403dc9 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel07 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel07 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt index c9916d4184..eedf1c7a89 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel08 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel08 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt index fb293257e8..259f52eb8a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel09 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel09 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt index 43ceea50b3..ce0424471a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.channel10 +// This file was automatically generated from channels.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleChannel10 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt index ab9ef608f4..ec20f1e40d 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.compose01 +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCompose01 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt index 9e46c6c48f..9531b5c893 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.compose02 +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCompose02 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt index 1dc2fd9bb2..a61afeab55 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.compose03 +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCompose03 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt index ad0b021488..312dc72b55 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.compose04 +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCompose04 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt index e02f33e0bd..37c4f99e6e 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.compose05 +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCompose05 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt index 1df506e4e8..5ee9e451fb 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.compose06 +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleCompose06 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt index c3a9f5afeb..0a9546057a 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context01 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext01 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt index d1ec85fa9b..49bfe7efa3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context02 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext02 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt index e52976d095..3aaf0b30ad 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context03 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext03 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt index b4a8a3f821..c5ce5eba7b 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context04 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext04 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt index 338e3c9d88..3017b04996 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context05 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext05 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt index b37b06b85c..e23eaf2542 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context06 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext06 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt index 825f572a34..8037a559c5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context07 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext07 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt index 1083d77da4..a34e1aea5c 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context08 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext08 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt index 386e52544f..6c1121b2a3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context09 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext09 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt index 3dde44670e..0256004405 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context10 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext10 import kotlin.coroutines.* import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt index 4a50d86c0f..e3563171f5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.context11 +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleContext11 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt index 4bec14fca3..34d7b68c82 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.exceptions01 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleExceptions01 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt index 818ab285c8..359eff60e4 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.exceptions02 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleExceptions02 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt index 2b1e8e62b1..1ad5aef719 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.exceptions03 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleExceptions03 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt index 02024ce206..e1fc22d725 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.exceptions04 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleExceptions04 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt index e90606ff2a..e97572aba8 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.exceptions05 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleExceptions05 import kotlinx.coroutines.exceptions.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt index 636c4a1f5d..eec27840e5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.exceptions06 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleExceptions06 import kotlinx.coroutines.* import java.io.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt index 020f458b44..df14603db0 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow01 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow01 fun foo(): List = listOf(1, 2, 3) diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt index 66fc1639b5..fcb61b9d1d 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow02 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow02 fun foo(): Sequence = sequence { // sequence builder for (i in 1..3) { diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt index 393a0fa3a0..ba94b2f8f6 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow03 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow03 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt index 7bde16cf29..3e3aea0f55 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow04 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow04 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt index c1e05e2e3c..6d0e451923 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow05 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow05 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt index 1926983d67..9d9348ea5c 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow06 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow06 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt index 47ecf20bae..73b1734208 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-07.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow07 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow07 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt index 96aa19c1d5..1e8580c81f 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-08.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow08 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow08 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt index 4af29d93d3..7e2113c401 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-09.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow09 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow09 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt index 47602dab09..61e74a1aa1 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-10.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow10 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow10 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt index a97400626c..513057d10b 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-11.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow11 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow11 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt index 24dc4267ad..54ddf659f3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-12.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow12 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow12 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt index 5d45946cb9..4feacc6d25 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-13.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow13 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow13 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt index 6628d12601..c0f2320490 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-14.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow14 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow14 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt index 3c1b10a94b..8f0e395ce4 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-15.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow15 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow15 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt index 0698e1bf84..d2f41ff6cc 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-16.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow16 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow16 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt index 86de59a2d0..5db79df185 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-17.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow17 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow17 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt index 597ff78326..3c1a8a1b7c 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-18.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow18 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow18 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt index eff3d8c054..1725276bf8 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-19.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow19 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow19 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt index 0cc3df45ab..bb829d11a0 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-20.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow20 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow20 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt index 5bf0e87074..e0adea60b5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-21.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow21 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow21 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt index cd8f8b0c5c..9450ce59a9 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-22.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow22 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow22 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt index 742452e414..513fa30450 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-23.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow23 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow23 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt index 32047a93c4..7da20e01a6 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-24.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow24 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow24 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt index 094553095a..e3c2b812cd 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-25.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow25 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow25 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt index 037e253094..e489c3f2ed 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-26.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow26 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow26 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt index 6117cf5c62..f9ef9793cf 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-27.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow27 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow27 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt index 15acb79614..84fc69fd7b 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-28.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow28 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow28 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt index c0497df73c..6c60c5d9d2 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-29.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow29 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow29 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt index 5035efe23c..e21c77fcf3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-30.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow30 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow30 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt index dfa43db53e..9b2855ef09 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-31.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow31 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow31 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt index f541ab57d9..3ad74ae5f1 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-32.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow32 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow32 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt index 1e291412c3..c0e0ab3d5b 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-33.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow33 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow33 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt index df2cad2025..4b79a73683 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-34.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow34 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow34 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt index a7c6bd2100..928c8bf2e6 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-35.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow35 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow35 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt b/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt index 9c5a57bf8f..3138464ced 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-flow-36.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.flow36 +// This file was automatically generated from flow.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleFlow36 import kotlinx.coroutines.* import kotlinx.coroutines.flow.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt index 1939e72089..c1a962e60d 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.select01 +// This file was automatically generated from select-expression.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSelect01 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt index 0e51015105..57fe638297 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.select02 +// This file was automatically generated from select-expression.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSelect02 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt index 42422378f8..36597dd637 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.select03 +// This file was automatically generated from select-expression.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSelect03 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt index 2db5170206..4cd9f6d93f 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.select04 +// This file was automatically generated from select-expression.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSelect04 import kotlinx.coroutines.* import kotlinx.coroutines.selects.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt index e03be9da75..464e9b20f3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.select05 +// This file was automatically generated from select-expression.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSelect05 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt index d70b6c9f69..ffd56a8f85 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.supervision01 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSupervision01 import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt index facc2e0881..dc3a0f2844 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.supervision02 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSupervision02 import kotlin.coroutines.* import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt index 47c31b9e75..b32a004639 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.supervision03 +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSupervision03 import kotlin.coroutines.* import kotlinx.coroutines.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt index bd710a49cd..32d4ac4fe9 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync01 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync01 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt index 813123723a..fb551f8953 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync02 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync02 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt index 1baf849acd..6c34149c93 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync03 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync03 import kotlinx.coroutines.* import java.util.concurrent.atomic.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt index e16a8113f0..f94c4a05da 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync04 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync04 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt index d022961b31..a6a1cdd2a6 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync05 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync05 import kotlinx.coroutines.* import kotlin.system.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt index fe08f049fd..e6c5f1bad3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync06 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync06 import kotlinx.coroutines.* import kotlinx.coroutines.sync.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt index 65e2050021..a84e02c849 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. -package kotlinx.coroutines.guide.sync07 +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. +package kotlinx.coroutines.guide.exampleSync07 import kotlinx.coroutines.* import kotlinx.coroutines.channels.* diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt index 93b49a6013..7fc57c2ee3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt @@ -1,53 +1,56 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from basics.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class BasicsGuideTest { - @Test - fun testKotlinxCoroutinesGuideBasic01() { - test("KotlinxCoroutinesGuideBasic01") { kotlinx.coroutines.guide.basic01.main() }.verifyLines( + fun testExampleBasic01() { + test("ExampleBasic01") { kotlinx.coroutines.guide.exampleBasic01.main() }.verifyLines( "Hello,", "World!" ) } @Test - fun testKotlinxCoroutinesGuideBasic02() { - test("KotlinxCoroutinesGuideBasic02") { kotlinx.coroutines.guide.basic02.main() }.verifyLines( + fun testExampleBasic02() { + test("ExampleBasic02") { kotlinx.coroutines.guide.exampleBasic02.main() }.verifyLines( "Hello,", "World!" ) } @Test - fun testKotlinxCoroutinesGuideBasic02b() { - test("KotlinxCoroutinesGuideBasic02b") { kotlinx.coroutines.guide.basic02b.main() }.verifyLines( + fun testExampleBasic03() { + test("ExampleBasic03") { kotlinx.coroutines.guide.exampleBasic03.main() }.verifyLines( "Hello,", "World!" ) } @Test - fun testKotlinxCoroutinesGuideBasic03() { - test("KotlinxCoroutinesGuideBasic03") { kotlinx.coroutines.guide.basic03.main() }.verifyLines( + fun testExampleBasic04() { + test("ExampleBasic04") { kotlinx.coroutines.guide.exampleBasic04.main() }.verifyLines( "Hello,", "World!" ) } @Test - fun testKotlinxCoroutinesGuideBasic03s() { - test("KotlinxCoroutinesGuideBasic03s") { kotlinx.coroutines.guide.basic03s.main() }.verifyLines( + fun testExampleBasic05() { + test("ExampleBasic05") { kotlinx.coroutines.guide.exampleBasic05.main() }.verifyLines( "Hello,", "World!" ) } @Test - fun testKotlinxCoroutinesGuideBasic04() { - test("KotlinxCoroutinesGuideBasic04") { kotlinx.coroutines.guide.basic04.main() }.verifyLines( + fun testExampleBasic06() { + test("ExampleBasic06") { kotlinx.coroutines.guide.exampleBasic06.main() }.verifyLines( "Task from coroutine scope", "Task from runBlocking", "Task from nested launch", @@ -56,23 +59,23 @@ class BasicsGuideTest { } @Test - fun testKotlinxCoroutinesGuideBasic05() { - test("KotlinxCoroutinesGuideBasic05") { kotlinx.coroutines.guide.basic05.main() }.verifyLines( + fun testExampleBasic07() { + test("ExampleBasic07") { kotlinx.coroutines.guide.exampleBasic07.main() }.verifyLines( "Hello,", "World!" ) } @Test - fun testKotlinxCoroutinesGuideBasic06() { - test("KotlinxCoroutinesGuideBasic06") { kotlinx.coroutines.guide.basic06.main() }.also { lines -> + fun testExampleBasic08() { + test("ExampleBasic08") { kotlinx.coroutines.guide.exampleBasic08.main() }.also { lines -> check(lines.size == 1 && lines[0] == ".".repeat(100_000)) } } @Test - fun testKotlinxCoroutinesGuideBasic07() { - test("KotlinxCoroutinesGuideBasic07") { kotlinx.coroutines.guide.basic07.main() }.verifyLines( + fun testExampleBasic09() { + test("ExampleBasic09") { kotlinx.coroutines.guide.exampleBasic09.main() }.verifyLines( "I'm sleeping 0 ...", "I'm sleeping 1 ...", "I'm sleeping 2 ..." diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/CancellationTimeOutsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt similarity index 60% rename from kotlinx-coroutines-core/jvm/test/guide/test/CancellationTimeOutsGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt index 83bca486cd..a2e91de82d 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/CancellationTimeOutsGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/CancellationGuideTest.kt @@ -1,13 +1,16 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from cancellation-and-timeouts.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test -class CancellationTimeOutsGuideTest { - +class CancellationGuideTest { @Test - fun testKotlinxCoroutinesGuideCancel01() { - test("KotlinxCoroutinesGuideCancel01") { kotlinx.coroutines.guide.cancel01.main() }.verifyLines( + fun testExampleCancel01() { + test("ExampleCancel01") { kotlinx.coroutines.guide.exampleCancel01.main() }.verifyLines( "job: I'm sleeping 0 ...", "job: I'm sleeping 1 ...", "job: I'm sleeping 2 ...", @@ -17,8 +20,8 @@ class CancellationTimeOutsGuideTest { } @Test - fun testKotlinxCoroutinesGuideCancel02() { - test("KotlinxCoroutinesGuideCancel02") { kotlinx.coroutines.guide.cancel02.main() }.verifyLines( + fun testExampleCancel02() { + test("ExampleCancel02") { kotlinx.coroutines.guide.exampleCancel02.main() }.verifyLines( "job: I'm sleeping 0 ...", "job: I'm sleeping 1 ...", "job: I'm sleeping 2 ...", @@ -30,8 +33,8 @@ class CancellationTimeOutsGuideTest { } @Test - fun testKotlinxCoroutinesGuideCancel03() { - test("KotlinxCoroutinesGuideCancel03") { kotlinx.coroutines.guide.cancel03.main() }.verifyLines( + fun testExampleCancel03() { + test("ExampleCancel03") { kotlinx.coroutines.guide.exampleCancel03.main() }.verifyLines( "job: I'm sleeping 0 ...", "job: I'm sleeping 1 ...", "job: I'm sleeping 2 ...", @@ -41,8 +44,8 @@ class CancellationTimeOutsGuideTest { } @Test - fun testKotlinxCoroutinesGuideCancel04() { - test("KotlinxCoroutinesGuideCancel04") { kotlinx.coroutines.guide.cancel04.main() }.verifyLines( + fun testExampleCancel04() { + test("ExampleCancel04") { kotlinx.coroutines.guide.exampleCancel04.main() }.verifyLines( "job: I'm sleeping 0 ...", "job: I'm sleeping 1 ...", "job: I'm sleeping 2 ...", @@ -53,8 +56,8 @@ class CancellationTimeOutsGuideTest { } @Test - fun testKotlinxCoroutinesGuideCancel05() { - test("KotlinxCoroutinesGuideCancel05") { kotlinx.coroutines.guide.cancel05.main() }.verifyLines( + fun testExampleCancel05() { + test("ExampleCancel05") { kotlinx.coroutines.guide.exampleCancel05.main() }.verifyLines( "job: I'm sleeping 0 ...", "job: I'm sleeping 1 ...", "job: I'm sleeping 2 ...", @@ -66,8 +69,8 @@ class CancellationTimeOutsGuideTest { } @Test - fun testKotlinxCoroutinesGuideCancel06() { - test("KotlinxCoroutinesGuideCancel06") { kotlinx.coroutines.guide.cancel06.main() }.verifyLinesStartWith( + fun testExampleCancel06() { + test("ExampleCancel06") { kotlinx.coroutines.guide.exampleCancel06.main() }.verifyLinesStartWith( "I'm sleeping 0 ...", "I'm sleeping 1 ...", "I'm sleeping 2 ...", @@ -76,8 +79,8 @@ class CancellationTimeOutsGuideTest { } @Test - fun testKotlinxCoroutinesGuideCancel07() { - test("KotlinxCoroutinesGuideCancel07") { kotlinx.coroutines.guide.cancel07.main() }.verifyLines( + fun testExampleCancel07() { + test("ExampleCancel07") { kotlinx.coroutines.guide.exampleCancel07.main() }.verifyLines( "I'm sleeping 0 ...", "I'm sleeping 1 ...", "I'm sleeping 2 ...", diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt index a747c98487..209d439663 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt @@ -1,13 +1,16 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from channels.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class ChannelsGuideTest { - @Test - fun testKotlinxCoroutinesGuideChannel01() { - test("KotlinxCoroutinesGuideChannel01") { kotlinx.coroutines.guide.channel01.main() }.verifyLines( + fun testExampleChannel01() { + test("ExampleChannel01") { kotlinx.coroutines.guide.exampleChannel01.main() }.verifyLines( "1", "4", "9", @@ -18,8 +21,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel02() { - test("KotlinxCoroutinesGuideChannel02") { kotlinx.coroutines.guide.channel02.main() }.verifyLines( + fun testExampleChannel02() { + test("ExampleChannel02") { kotlinx.coroutines.guide.exampleChannel02.main() }.verifyLines( "1", "4", "9", @@ -30,8 +33,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel03() { - test("KotlinxCoroutinesGuideChannel03") { kotlinx.coroutines.guide.channel03.main() }.verifyLines( + fun testExampleChannel03() { + test("ExampleChannel03") { kotlinx.coroutines.guide.exampleChannel03.main() }.verifyLines( "1", "4", "9", @@ -42,8 +45,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel04() { - test("KotlinxCoroutinesGuideChannel04") { kotlinx.coroutines.guide.channel04.main() }.verifyLines( + fun testExampleChannel04() { + test("ExampleChannel04") { kotlinx.coroutines.guide.exampleChannel04.main() }.verifyLines( "1", "4", "9", @@ -54,8 +57,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel05() { - test("KotlinxCoroutinesGuideChannel05") { kotlinx.coroutines.guide.channel05.main() }.verifyLines( + fun testExampleChannel05() { + test("ExampleChannel05") { kotlinx.coroutines.guide.exampleChannel05.main() }.verifyLines( "2", "3", "5", @@ -70,15 +73,15 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel06() { - test("KotlinxCoroutinesGuideChannel06") { kotlinx.coroutines.guide.channel06.main() }.also { lines -> + fun testExampleChannel06() { + test("ExampleChannel06") { kotlinx.coroutines.guide.exampleChannel06.main() }.also { lines -> check(lines.size == 10 && lines.withIndex().all { (i, line) -> line.startsWith("Processor #") && line.endsWith(" received ${i + 1}") }) } } @Test - fun testKotlinxCoroutinesGuideChannel07() { - test("KotlinxCoroutinesGuideChannel07") { kotlinx.coroutines.guide.channel07.main() }.verifyLines( + fun testExampleChannel07() { + test("ExampleChannel07") { kotlinx.coroutines.guide.exampleChannel07.main() }.verifyLines( "foo", "foo", "BAR!", @@ -89,8 +92,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel08() { - test("KotlinxCoroutinesGuideChannel08") { kotlinx.coroutines.guide.channel08.main() }.verifyLines( + fun testExampleChannel08() { + test("ExampleChannel08") { kotlinx.coroutines.guide.exampleChannel08.main() }.verifyLines( "Sending 0", "Sending 1", "Sending 2", @@ -100,8 +103,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel09() { - test("KotlinxCoroutinesGuideChannel09") { kotlinx.coroutines.guide.channel09.main() }.verifyLines( + fun testExampleChannel09() { + test("ExampleChannel09") { kotlinx.coroutines.guide.exampleChannel09.main() }.verifyLines( "ping Ball(hits=1)", "pong Ball(hits=2)", "ping Ball(hits=3)", @@ -110,8 +113,8 @@ class ChannelsGuideTest { } @Test - fun testKotlinxCoroutinesGuideChannel10() { - test("KotlinxCoroutinesGuideChannel10") { kotlinx.coroutines.guide.channel10.main() }.verifyLines( + fun testExampleChannel10() { + test("ExampleChannel10") { kotlinx.coroutines.guide.exampleChannel10.main() }.verifyLines( "Initial element is available immediately: kotlin.Unit", "Next element is not ready in 50 ms: null", "Next element is ready in 100 ms: kotlin.Unit", diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt index de4cba44c6..50c3fd7e62 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt @@ -1,53 +1,56 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from composing-suspending-functions.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class ComposingGuideTest { - @Test - fun testKotlinxCoroutinesGuideCompose01() { - test("KotlinxCoroutinesGuideCompose01") { kotlinx.coroutines.guide.compose01.main() }.verifyLinesArbitraryTime( + fun testExampleCompose01() { + test("ExampleCompose01") { kotlinx.coroutines.guide.exampleCompose01.main() }.verifyLinesArbitraryTime( "The answer is 42", "Completed in 2017 ms" ) } @Test - fun testKotlinxCoroutinesGuideCompose02() { - test("KotlinxCoroutinesGuideCompose02") { kotlinx.coroutines.guide.compose02.main() }.verifyLinesArbitraryTime( + fun testExampleCompose02() { + test("ExampleCompose02") { kotlinx.coroutines.guide.exampleCompose02.main() }.verifyLinesArbitraryTime( "The answer is 42", "Completed in 1017 ms" ) } @Test - fun testKotlinxCoroutinesGuideCompose03() { - test("KotlinxCoroutinesGuideCompose03") { kotlinx.coroutines.guide.compose03.main() }.verifyLinesArbitraryTime( + fun testExampleCompose03() { + test("ExampleCompose03") { kotlinx.coroutines.guide.exampleCompose03.main() }.verifyLinesArbitraryTime( "The answer is 42", "Completed in 1017 ms" ) } @Test - fun testKotlinxCoroutinesGuideCompose04() { - test("KotlinxCoroutinesGuideCompose04") { kotlinx.coroutines.guide.compose04.main() }.verifyLinesArbitraryTime( + fun testExampleCompose04() { + test("ExampleCompose04") { kotlinx.coroutines.guide.exampleCompose04.main() }.verifyLinesArbitraryTime( "The answer is 42", "Completed in 1085 ms" ) } @Test - fun testKotlinxCoroutinesGuideCompose05() { - test("KotlinxCoroutinesGuideCompose05") { kotlinx.coroutines.guide.compose05.main() }.verifyLinesArbitraryTime( + fun testExampleCompose05() { + test("ExampleCompose05") { kotlinx.coroutines.guide.exampleCompose05.main() }.verifyLinesArbitraryTime( "The answer is 42", "Completed in 1017 ms" ) } @Test - fun testKotlinxCoroutinesGuideCompose06() { - test("KotlinxCoroutinesGuideCompose06") { kotlinx.coroutines.guide.compose06.main() }.verifyLines( + fun testExampleCompose06() { + test("ExampleCompose06") { kotlinx.coroutines.guide.exampleCompose06.main() }.verifyLines( "Second child throws an exception", "First child was cancelled", "Computation failed with ArithmeticException" diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt index 180738f8b3..c0c32410d5 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt @@ -1,13 +1,16 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from coroutine-context-and-dispatchers.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test -class DispatchersGuideTest { - +class DispatcherGuideTest { @Test - fun testKotlinxCoroutinesGuideContext01() { - test("KotlinxCoroutinesGuideContext01") { kotlinx.coroutines.guide.context01.main() }.verifyLinesStartUnordered( + fun testExampleContext01() { + test("ExampleContext01") { kotlinx.coroutines.guide.exampleContext01.main() }.verifyLinesStartUnordered( "Unconfined : I'm working in thread main", "Default : I'm working in thread DefaultDispatcher-worker-1", "newSingleThreadContext: I'm working in thread MyOwnThread", @@ -16,8 +19,8 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext02() { - test("KotlinxCoroutinesGuideContext02") { kotlinx.coroutines.guide.context02.main() }.verifyLinesStart( + fun testExampleContext02() { + test("ExampleContext02") { kotlinx.coroutines.guide.exampleContext02.main() }.verifyLinesStart( "Unconfined : I'm working in thread main", "main runBlocking: I'm working in thread main", "Unconfined : After delay in thread kotlinx.coroutines.DefaultExecutor", @@ -26,8 +29,8 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext03() { - test("KotlinxCoroutinesGuideContext03") { kotlinx.coroutines.guide.context03.main() }.verifyLinesFlexibleThread( + fun testExampleContext03() { + test("ExampleContext03") { kotlinx.coroutines.guide.exampleContext03.main() }.verifyLinesFlexibleThread( "[main @coroutine#2] I'm computing a piece of the answer", "[main @coroutine#3] I'm computing another piece of the answer", "[main @coroutine#1] The answer is 42" @@ -35,8 +38,8 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext04() { - test("KotlinxCoroutinesGuideContext04") { kotlinx.coroutines.guide.context04.main() }.verifyLines( + fun testExampleContext04() { + test("ExampleContext04") { kotlinx.coroutines.guide.exampleContext04.main() }.verifyLines( "[Ctx1 @coroutine#1] Started in ctx1", "[Ctx2 @coroutine#1] Working in ctx2", "[Ctx1 @coroutine#1] Back to ctx1" @@ -44,15 +47,15 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext05() { - test("KotlinxCoroutinesGuideContext05") { kotlinx.coroutines.guide.context05.main() }.also { lines -> + fun testExampleContext05() { + test("ExampleContext05") { kotlinx.coroutines.guide.exampleContext05.main() }.also { lines -> check(lines.size == 1 && lines[0].startsWith("My job is \"coroutine#1\":BlockingCoroutine{Active}@")) } } @Test - fun testKotlinxCoroutinesGuideContext06() { - test("KotlinxCoroutinesGuideContext06") { kotlinx.coroutines.guide.context06.main() }.verifyLines( + fun testExampleContext06() { + test("ExampleContext06") { kotlinx.coroutines.guide.exampleContext06.main() }.verifyLines( "job1: I run in GlobalScope and execute independently!", "job2: I am a child of the request coroutine", "job1: I am not affected by cancellation of the request", @@ -61,8 +64,8 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext07() { - test("KotlinxCoroutinesGuideContext07") { kotlinx.coroutines.guide.context07.main() }.verifyLines( + fun testExampleContext07() { + test("ExampleContext07") { kotlinx.coroutines.guide.exampleContext07.main() }.verifyLines( "request: I'm done and I don't explicitly join my children that are still active", "Coroutine 0 is done", "Coroutine 1 is done", @@ -72,8 +75,8 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext08() { - test("KotlinxCoroutinesGuideContext08") { kotlinx.coroutines.guide.context08.main() }.verifyLinesFlexibleThread( + fun testExampleContext08() { + test("ExampleContext08") { kotlinx.coroutines.guide.exampleContext08.main() }.verifyLinesFlexibleThread( "[main @main#1] Started main coroutine", "[main @v1coroutine#2] Computing v1", "[main @v2coroutine#3] Computing v2", @@ -82,15 +85,15 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext09() { - test("KotlinxCoroutinesGuideContext09") { kotlinx.coroutines.guide.context09.main() }.verifyLinesFlexibleThread( + fun testExampleContext09() { + test("ExampleContext09") { kotlinx.coroutines.guide.exampleContext09.main() }.verifyLinesFlexibleThread( "I'm working in thread DefaultDispatcher-worker-1 @test#2" ) } @Test - fun testKotlinxCoroutinesGuideContext10() { - test("KotlinxCoroutinesGuideContext10") { kotlinx.coroutines.guide.context10.main() }.verifyLines( + fun testExampleContext10() { + test("ExampleContext10") { kotlinx.coroutines.guide.exampleContext10.main() }.verifyLines( "Launched coroutines", "Coroutine 0 is done", "Coroutine 1 is done", @@ -99,8 +102,8 @@ class DispatchersGuideTest { } @Test - fun testKotlinxCoroutinesGuideContext11() { - test("KotlinxCoroutinesGuideContext11") { kotlinx.coroutines.guide.context11.main() }.verifyLinesFlexibleThread( + fun testExampleContext11() { + test("ExampleContext11") { kotlinx.coroutines.guide.exampleContext11.main() }.verifyLinesFlexibleThread( "Pre-main, current thread: Thread[main @coroutine#1,5,main], thread local value: 'main'", "Launch start, current thread: Thread[DefaultDispatcher-worker-1 @coroutine#2,5,main], thread local value: 'launch'", "After yield, current thread: Thread[DefaultDispatcher-worker-2 @coroutine#2,5,main], thread local value: 'launch'", diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt index 7fa692b2a0..4a140208f9 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt @@ -1,13 +1,16 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from exception-handling.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class ExceptionsGuideTest { - @Test - fun testKotlinxCoroutinesGuideExceptions01() { - test("KotlinxCoroutinesGuideExceptions01") { kotlinx.coroutines.guide.exceptions01.main() }.verifyExceptions( + fun testExampleExceptions01() { + test("ExampleExceptions01") { kotlinx.coroutines.guide.exampleExceptions01.main() }.verifyExceptions( "Throwing exception from launch", "Exception in thread \"DefaultDispatcher-worker-2 @coroutine#2\" java.lang.IndexOutOfBoundsException", "Joined failed job", @@ -17,15 +20,15 @@ class ExceptionsGuideTest { } @Test - fun testKotlinxCoroutinesGuideExceptions02() { - test("KotlinxCoroutinesGuideExceptions02") { kotlinx.coroutines.guide.exceptions02.main() }.verifyLines( + fun testExampleExceptions02() { + test("ExampleExceptions02") { kotlinx.coroutines.guide.exampleExceptions02.main() }.verifyLines( "Caught java.lang.AssertionError" ) } @Test - fun testKotlinxCoroutinesGuideExceptions03() { - test("KotlinxCoroutinesGuideExceptions03") { kotlinx.coroutines.guide.exceptions03.main() }.verifyLines( + fun testExampleExceptions03() { + test("ExampleExceptions03") { kotlinx.coroutines.guide.exampleExceptions03.main() }.verifyLines( "Cancelling child", "Child is cancelled", "Parent is not cancelled" @@ -33,8 +36,8 @@ class ExceptionsGuideTest { } @Test - fun testKotlinxCoroutinesGuideExceptions04() { - test("KotlinxCoroutinesGuideExceptions04") { kotlinx.coroutines.guide.exceptions04.main() }.verifyLines( + fun testExampleExceptions04() { + test("ExampleExceptions04") { kotlinx.coroutines.guide.exampleExceptions04.main() }.verifyLines( "Second child throws an exception", "Children are cancelled, but exception is not handled until all children terminate", "The first child finished its non cancellable block", @@ -43,23 +46,23 @@ class ExceptionsGuideTest { } @Test - fun testKotlinxCoroutinesGuideExceptions05() { - test("KotlinxCoroutinesGuideExceptions05") { kotlinx.coroutines.guide.exceptions05.main() }.verifyLines( + fun testExampleExceptions05() { + test("ExampleExceptions05") { kotlinx.coroutines.guide.exampleExceptions05.main() }.verifyLines( "Caught java.io.IOException with suppressed [java.lang.ArithmeticException]" ) } @Test - fun testKotlinxCoroutinesGuideExceptions06() { - test("KotlinxCoroutinesGuideExceptions06") { kotlinx.coroutines.guide.exceptions06.main() }.verifyLines( + fun testExampleExceptions06() { + test("ExampleExceptions06") { kotlinx.coroutines.guide.exampleExceptions06.main() }.verifyLines( "Rethrowing CancellationException with original cause", "Caught original java.io.IOException" ) } @Test - fun testKotlinxCoroutinesGuideSupervision01() { - test("KotlinxCoroutinesGuideSupervision01") { kotlinx.coroutines.guide.supervision01.main() }.verifyLines( + fun testExampleSupervision01() { + test("ExampleSupervision01") { kotlinx.coroutines.guide.exampleSupervision01.main() }.verifyLines( "First child is failing", "First child is cancelled: true, but second one is still active", "Cancelling supervisor", @@ -68,8 +71,8 @@ class ExceptionsGuideTest { } @Test - fun testKotlinxCoroutinesGuideSupervision02() { - test("KotlinxCoroutinesGuideSupervision02") { kotlinx.coroutines.guide.supervision02.main() }.verifyLines( + fun testExampleSupervision02() { + test("ExampleSupervision02") { kotlinx.coroutines.guide.exampleSupervision02.main() }.verifyLines( "Child is sleeping", "Throwing exception from scope", "Child is cancelled", @@ -78,8 +81,8 @@ class ExceptionsGuideTest { } @Test - fun testKotlinxCoroutinesGuideSupervision03() { - test("KotlinxCoroutinesGuideSupervision03") { kotlinx.coroutines.guide.supervision03.main() }.verifyLines( + fun testExampleSupervision03() { + test("ExampleSupervision03") { kotlinx.coroutines.guide.exampleSupervision03.main() }.verifyLines( "Scope is completing", "Child throws an exception", "Caught java.lang.AssertionError", diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt index 0353c54e7c..5d320f2124 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt @@ -1,13 +1,16 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + // This file was automatically generated from flow.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class FlowGuideTest { - @Test - fun testKotlinxCoroutinesGuideFlow01() { - test("KotlinxCoroutinesGuideFlow01") { kotlinx.coroutines.guide.flow01.main() }.verifyLines( + fun testExampleFlow01() { + test("ExampleFlow01") { kotlinx.coroutines.guide.exampleFlow01.main() }.verifyLines( "1", "2", "3" @@ -15,8 +18,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow02() { - test("KotlinxCoroutinesGuideFlow02") { kotlinx.coroutines.guide.flow02.main() }.verifyLines( + fun testExampleFlow02() { + test("ExampleFlow02") { kotlinx.coroutines.guide.exampleFlow02.main() }.verifyLines( "1", "2", "3" @@ -24,8 +27,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow03() { - test("KotlinxCoroutinesGuideFlow03") { kotlinx.coroutines.guide.flow03.main() }.verifyLines( + fun testExampleFlow03() { + test("ExampleFlow03") { kotlinx.coroutines.guide.exampleFlow03.main() }.verifyLines( "1", "2", "3" @@ -33,8 +36,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow04() { - test("KotlinxCoroutinesGuideFlow04") { kotlinx.coroutines.guide.flow04.main() }.verifyLines( + fun testExampleFlow04() { + test("ExampleFlow04") { kotlinx.coroutines.guide.exampleFlow04.main() }.verifyLines( "I'm not blocked 1", "1", "I'm not blocked 2", @@ -45,8 +48,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow05() { - test("KotlinxCoroutinesGuideFlow05") { kotlinx.coroutines.guide.flow05.main() }.verifyLines( + fun testExampleFlow05() { + test("ExampleFlow05") { kotlinx.coroutines.guide.exampleFlow05.main() }.verifyLines( "Calling foo...", "Calling collect...", "Flow started", @@ -62,8 +65,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow06() { - test("KotlinxCoroutinesGuideFlow06") { kotlinx.coroutines.guide.flow06.main() }.verifyLines( + fun testExampleFlow06() { + test("ExampleFlow06") { kotlinx.coroutines.guide.exampleFlow06.main() }.verifyLines( "Emitting 1", "1", "Emitting 2", @@ -73,8 +76,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow07() { - test("KotlinxCoroutinesGuideFlow07") { kotlinx.coroutines.guide.flow07.main() }.verifyLines( + fun testExampleFlow07() { + test("ExampleFlow07") { kotlinx.coroutines.guide.exampleFlow07.main() }.verifyLines( "1", "2", "3" @@ -82,8 +85,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow08() { - test("KotlinxCoroutinesGuideFlow08") { kotlinx.coroutines.guide.flow08.main() }.verifyLines( + fun testExampleFlow08() { + test("ExampleFlow08") { kotlinx.coroutines.guide.exampleFlow08.main() }.verifyLines( "response 1", "response 2", "response 3" @@ -91,8 +94,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow09() { - test("KotlinxCoroutinesGuideFlow09") { kotlinx.coroutines.guide.flow09.main() }.verifyLines( + fun testExampleFlow09() { + test("ExampleFlow09") { kotlinx.coroutines.guide.exampleFlow09.main() }.verifyLines( "Making request 1", "response 1", "Making request 2", @@ -103,8 +106,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow10() { - test("KotlinxCoroutinesGuideFlow10") { kotlinx.coroutines.guide.flow10.main() }.verifyLines( + fun testExampleFlow10() { + test("ExampleFlow10") { kotlinx.coroutines.guide.exampleFlow10.main() }.verifyLines( "1", "2", "Finally in numbers" @@ -112,15 +115,15 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow11() { - test("KotlinxCoroutinesGuideFlow11") { kotlinx.coroutines.guide.flow11.main() }.verifyLines( + fun testExampleFlow11() { + test("ExampleFlow11") { kotlinx.coroutines.guide.exampleFlow11.main() }.verifyLines( "55" ) } @Test - fun testKotlinxCoroutinesGuideFlow12() { - test("KotlinxCoroutinesGuideFlow12") { kotlinx.coroutines.guide.flow12.main() }.verifyLines( + fun testExampleFlow12() { + test("ExampleFlow12") { kotlinx.coroutines.guide.exampleFlow12.main() }.verifyLines( "Filter 1", "Filter 2", "Map 2", @@ -134,8 +137,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow13() { - test("KotlinxCoroutinesGuideFlow13") { kotlinx.coroutines.guide.flow13.main() }.verifyLinesFlexibleThread( + fun testExampleFlow13() { + test("ExampleFlow13") { kotlinx.coroutines.guide.exampleFlow13.main() }.verifyLinesFlexibleThread( "[main @coroutine#1] Started foo flow", "[main @coroutine#1] Collected 1", "[main @coroutine#1] Collected 2", @@ -144,19 +147,19 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow14() { - test("KotlinxCoroutinesGuideFlow14") { kotlinx.coroutines.guide.flow14.main() }.verifyExceptions( + fun testExampleFlow14() { + test("ExampleFlow14") { kotlinx.coroutines.guide.exampleFlow14.main() }.verifyExceptions( "Exception in thread \"main\" java.lang.IllegalStateException: Flow invariant is violated:", - " Flow was collected in [CoroutineId(1), \"coroutine#1\":BlockingCoroutine{Active}@5511c7f8, BlockingEventLoop@2eac3323],", - " but emission happened in [CoroutineId(1), \"coroutine#1\":DispatchedCoroutine{Active}@2dae0000, DefaultDispatcher].", - " Please refer to 'flow' documentation or use 'flowOn' instead", - " at ..." + "\t\tFlow was collected in [CoroutineId(1), \"coroutine#1\":BlockingCoroutine{Active}@5511c7f8, BlockingEventLoop@2eac3323],", + "\t\tbut emission happened in [CoroutineId(1), \"coroutine#1\":DispatchedCoroutine{Active}@2dae0000, DefaultDispatcher].", + "\t\tPlease refer to 'flow' documentation or use 'flowOn' instead", + "\tat ..." ) } @Test - fun testKotlinxCoroutinesGuideFlow15() { - test("KotlinxCoroutinesGuideFlow15") { kotlinx.coroutines.guide.flow15.main() }.verifyLinesFlexibleThread( + fun testExampleFlow15() { + test("ExampleFlow15") { kotlinx.coroutines.guide.exampleFlow15.main() }.verifyLinesFlexibleThread( "[DefaultDispatcher-worker-1 @coroutine#2] Emitting 1", "[main @coroutine#1] Collected 1", "[DefaultDispatcher-worker-1 @coroutine#2] Emitting 2", @@ -167,8 +170,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow16() { - test("KotlinxCoroutinesGuideFlow16") { kotlinx.coroutines.guide.flow16.main() }.verifyLinesArbitraryTime( + fun testExampleFlow16() { + test("ExampleFlow16") { kotlinx.coroutines.guide.exampleFlow16.main() }.verifyLinesArbitraryTime( "1", "2", "3", @@ -177,8 +180,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow17() { - test("KotlinxCoroutinesGuideFlow17") { kotlinx.coroutines.guide.flow17.main() }.verifyLinesArbitraryTime( + fun testExampleFlow17() { + test("ExampleFlow17") { kotlinx.coroutines.guide.exampleFlow17.main() }.verifyLinesArbitraryTime( "1", "2", "3", @@ -187,8 +190,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow18() { - test("KotlinxCoroutinesGuideFlow18") { kotlinx.coroutines.guide.flow18.main() }.verifyLinesArbitraryTime( + fun testExampleFlow18() { + test("ExampleFlow18") { kotlinx.coroutines.guide.exampleFlow18.main() }.verifyLinesArbitraryTime( "1", "3", "Collected in 758 ms" @@ -196,8 +199,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow19() { - test("KotlinxCoroutinesGuideFlow19") { kotlinx.coroutines.guide.flow19.main() }.verifyLinesArbitraryTime( + fun testExampleFlow19() { + test("ExampleFlow19") { kotlinx.coroutines.guide.exampleFlow19.main() }.verifyLinesArbitraryTime( "Collecting 1", "Collecting 2", "Collecting 3", @@ -207,8 +210,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow20() { - test("KotlinxCoroutinesGuideFlow20") { kotlinx.coroutines.guide.flow20.main() }.verifyLines( + fun testExampleFlow20() { + test("ExampleFlow20") { kotlinx.coroutines.guide.exampleFlow20.main() }.verifyLines( "1 -> one", "2 -> two", "3 -> three" @@ -216,8 +219,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow21() { - test("KotlinxCoroutinesGuideFlow21") { kotlinx.coroutines.guide.flow21.main() }.verifyLinesArbitraryTime( + fun testExampleFlow21() { + test("ExampleFlow21") { kotlinx.coroutines.guide.exampleFlow21.main() }.verifyLinesArbitraryTime( "1 -> one at 437 ms from start", "2 -> two at 837 ms from start", "3 -> three at 1243 ms from start" @@ -225,8 +228,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow22() { - test("KotlinxCoroutinesGuideFlow22") { kotlinx.coroutines.guide.flow22.main() }.verifyLinesArbitraryTime( + fun testExampleFlow22() { + test("ExampleFlow22") { kotlinx.coroutines.guide.exampleFlow22.main() }.verifyLinesArbitraryTime( "1 -> one at 452 ms from start", "2 -> one at 651 ms from start", "2 -> two at 854 ms from start", @@ -236,8 +239,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow23() { - test("KotlinxCoroutinesGuideFlow23") { kotlinx.coroutines.guide.flow23.main() }.verifyLinesArbitraryTime( + fun testExampleFlow23() { + test("ExampleFlow23") { kotlinx.coroutines.guide.exampleFlow23.main() }.verifyLinesArbitraryTime( "1: First at 121 ms from start", "1: Second at 622 ms from start", "2: First at 727 ms from start", @@ -248,8 +251,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow24() { - test("KotlinxCoroutinesGuideFlow24") { kotlinx.coroutines.guide.flow24.main() }.verifyLinesArbitraryTime( + fun testExampleFlow24() { + test("ExampleFlow24") { kotlinx.coroutines.guide.exampleFlow24.main() }.verifyLinesArbitraryTime( "1: First at 136 ms from start", "2: First at 231 ms from start", "3: First at 333 ms from start", @@ -260,8 +263,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow25() { - test("KotlinxCoroutinesGuideFlow25") { kotlinx.coroutines.guide.flow25.main() }.verifyLinesArbitraryTime( + fun testExampleFlow25() { + test("ExampleFlow25") { kotlinx.coroutines.guide.exampleFlow25.main() }.verifyLinesArbitraryTime( "1: First at 142 ms from start", "2: First at 322 ms from start", "3: First at 425 ms from start", @@ -270,8 +273,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow26() { - test("KotlinxCoroutinesGuideFlow26") { kotlinx.coroutines.guide.flow26.main() }.verifyLines( + fun testExampleFlow26() { + test("ExampleFlow26") { kotlinx.coroutines.guide.exampleFlow26.main() }.verifyLines( "Emitting 1", "1", "Emitting 2", @@ -281,8 +284,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow27() { - test("KotlinxCoroutinesGuideFlow27") { kotlinx.coroutines.guide.flow27.main() }.verifyLines( + fun testExampleFlow27() { + test("ExampleFlow27") { kotlinx.coroutines.guide.exampleFlow27.main() }.verifyLines( "Emitting 1", "string 1", "Emitting 2", @@ -291,8 +294,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow28() { - test("KotlinxCoroutinesGuideFlow28") { kotlinx.coroutines.guide.flow28.main() }.verifyLines( + fun testExampleFlow28() { + test("ExampleFlow28") { kotlinx.coroutines.guide.exampleFlow28.main() }.verifyLines( "Emitting 1", "string 1", "Emitting 2", @@ -301,19 +304,19 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow29() { - test("KotlinxCoroutinesGuideFlow29") { kotlinx.coroutines.guide.flow29.main() }.verifyExceptions( + fun testExampleFlow29() { + test("ExampleFlow29") { kotlinx.coroutines.guide.exampleFlow29.main() }.verifyExceptions( "Emitting 1", "1", "Emitting 2", "Exception in thread \"main\" java.lang.IllegalStateException: Collected 2", - " at ..." + "\tat ..." ) } @Test - fun testKotlinxCoroutinesGuideFlow30() { - test("KotlinxCoroutinesGuideFlow30") { kotlinx.coroutines.guide.flow30.main() }.verifyExceptions( + fun testExampleFlow30() { + test("ExampleFlow30") { kotlinx.coroutines.guide.exampleFlow30.main() }.verifyExceptions( "Emitting 1", "1", "Emitting 2", @@ -322,8 +325,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow31() { - test("KotlinxCoroutinesGuideFlow31") { kotlinx.coroutines.guide.flow31.main() }.verifyLines( + fun testExampleFlow31() { + test("ExampleFlow31") { kotlinx.coroutines.guide.exampleFlow31.main() }.verifyLines( "1", "2", "3", @@ -332,8 +335,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow32() { - test("KotlinxCoroutinesGuideFlow32") { kotlinx.coroutines.guide.flow32.main() }.verifyLines( + fun testExampleFlow32() { + test("ExampleFlow32") { kotlinx.coroutines.guide.exampleFlow32.main() }.verifyLines( "1", "2", "3", @@ -342,8 +345,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow33() { - test("KotlinxCoroutinesGuideFlow33") { kotlinx.coroutines.guide.flow33.main() }.verifyLines( + fun testExampleFlow33() { + test("ExampleFlow33") { kotlinx.coroutines.guide.exampleFlow33.main() }.verifyLines( "1", "Flow completed exceptionally", "Caught exception" @@ -351,8 +354,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow34() { - test("KotlinxCoroutinesGuideFlow34") { kotlinx.coroutines.guide.flow34.main() }.verifyExceptions( + fun testExampleFlow34() { + test("ExampleFlow34") { kotlinx.coroutines.guide.exampleFlow34.main() }.verifyExceptions( "1", "Flow completed with null", "Exception in thread \"main\" java.lang.IllegalStateException: Collected 2" @@ -360,8 +363,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow35() { - test("KotlinxCoroutinesGuideFlow35") { kotlinx.coroutines.guide.flow35.main() }.verifyLines( + fun testExampleFlow35() { + test("ExampleFlow35") { kotlinx.coroutines.guide.exampleFlow35.main() }.verifyLines( "Event: 1", "Event: 2", "Event: 3", @@ -370,8 +373,8 @@ class FlowGuideTest { } @Test - fun testKotlinxCoroutinesGuideFlow36() { - test("KotlinxCoroutinesGuideFlow36") { kotlinx.coroutines.guide.flow36.main() }.verifyLines( + fun testExampleFlow36() { + test("ExampleFlow36") { kotlinx.coroutines.guide.exampleFlow36.main() }.verifyLines( "Done", "Event: 1", "Event: 2", diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt index b5246ff4be..e3f47b9648 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt @@ -1,13 +1,16 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from select-expression.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class SelectGuideTest { - @Test - fun testKotlinxCoroutinesGuideSelect01() { - test("KotlinxCoroutinesGuideSelect01") { kotlinx.coroutines.guide.select01.main() }.verifyLines( + fun testExampleSelect01() { + test("ExampleSelect01") { kotlinx.coroutines.guide.exampleSelect01.main() }.verifyLines( "fizz -> 'Fizz'", "buzz -> 'Buzz!'", "fizz -> 'Fizz'", @@ -19,8 +22,8 @@ class SelectGuideTest { } @Test - fun testKotlinxCoroutinesGuideSelect02() { - test("KotlinxCoroutinesGuideSelect02") { kotlinx.coroutines.guide.select02.main() }.verifyLines( + fun testExampleSelect02() { + test("ExampleSelect02") { kotlinx.coroutines.guide.exampleSelect02.main() }.verifyLines( "a -> 'Hello 0'", "a -> 'Hello 1'", "b -> 'World 0'", @@ -33,8 +36,8 @@ class SelectGuideTest { } @Test - fun testKotlinxCoroutinesGuideSelect03() { - test("KotlinxCoroutinesGuideSelect03") { kotlinx.coroutines.guide.select03.main() }.verifyLines( + fun testExampleSelect03() { + test("ExampleSelect03") { kotlinx.coroutines.guide.exampleSelect03.main() }.verifyLines( "Consuming 1", "Side channel has 2", "Side channel has 3", @@ -50,16 +53,16 @@ class SelectGuideTest { } @Test - fun testKotlinxCoroutinesGuideSelect04() { - test("KotlinxCoroutinesGuideSelect04") { kotlinx.coroutines.guide.select04.main() }.verifyLines( + fun testExampleSelect04() { + test("ExampleSelect04") { kotlinx.coroutines.guide.exampleSelect04.main() }.verifyLines( "Deferred 4 produced answer 'Waited for 128 ms'", "11 coroutines are still active" ) } @Test - fun testKotlinxCoroutinesGuideSelect05() { - test("KotlinxCoroutinesGuideSelect05") { kotlinx.coroutines.guide.select05.main() }.verifyLines( + fun testExampleSelect05() { + test("ExampleSelect05") { kotlinx.coroutines.guide.exampleSelect05.main() }.verifyLines( "BEGIN", "Replace", "END", diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt index 45988570ba..8d534a09ea 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt @@ -1,61 +1,64 @@ -// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from shared-mutable-state-and-concurrency.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.test import org.junit.Test class SharedStateGuideTest { - @Test - fun testKotlinxCoroutinesGuideSync01() { - test("KotlinxCoroutinesGuideSync01") { kotlinx.coroutines.guide.sync01.main() }.verifyLinesStart( + fun testExampleSync01() { + test("ExampleSync01") { kotlinx.coroutines.guide.exampleSync01.main() }.verifyLinesStart( "Completed 100000 actions in", "Counter =" ) } @Test - fun testKotlinxCoroutinesGuideSync02() { - test("KotlinxCoroutinesGuideSync02") { kotlinx.coroutines.guide.sync02.main() }.verifyLinesStart( + fun testExampleSync02() { + test("ExampleSync02") { kotlinx.coroutines.guide.exampleSync02.main() }.verifyLinesStart( "Completed 100000 actions in", "Counter =" ) } @Test - fun testKotlinxCoroutinesGuideSync03() { - test("KotlinxCoroutinesGuideSync03") { kotlinx.coroutines.guide.sync03.main() }.verifyLinesArbitraryTime( + fun testExampleSync03() { + test("ExampleSync03") { kotlinx.coroutines.guide.exampleSync03.main() }.verifyLinesArbitraryTime( "Completed 100000 actions in xxx ms", "Counter = 100000" ) } @Test - fun testKotlinxCoroutinesGuideSync04() { - test("KotlinxCoroutinesGuideSync04") { kotlinx.coroutines.guide.sync04.main() }.verifyLinesArbitraryTime( + fun testExampleSync04() { + test("ExampleSync04") { kotlinx.coroutines.guide.exampleSync04.main() }.verifyLinesArbitraryTime( "Completed 100000 actions in xxx ms", "Counter = 100000" ) } @Test - fun testKotlinxCoroutinesGuideSync05() { - test("KotlinxCoroutinesGuideSync05") { kotlinx.coroutines.guide.sync05.main() }.verifyLinesArbitraryTime( + fun testExampleSync05() { + test("ExampleSync05") { kotlinx.coroutines.guide.exampleSync05.main() }.verifyLinesArbitraryTime( "Completed 100000 actions in xxx ms", "Counter = 100000" ) } @Test - fun testKotlinxCoroutinesGuideSync06() { - test("KotlinxCoroutinesGuideSync06") { kotlinx.coroutines.guide.sync06.main() }.verifyLinesArbitraryTime( + fun testExampleSync06() { + test("ExampleSync06") { kotlinx.coroutines.guide.exampleSync06.main() }.verifyLinesArbitraryTime( "Completed 100000 actions in xxx ms", "Counter = 100000" ) } @Test - fun testKotlinxCoroutinesGuideSync07() { - test("KotlinxCoroutinesGuideSync07") { kotlinx.coroutines.guide.sync07.main() }.verifyLinesArbitraryTime( + fun testExampleSync07() { + test("ExampleSync07") { kotlinx.coroutines.guide.exampleSync07.main() }.verifyLinesArbitraryTime( "Completed 100000 actions in xxx ms", "Counter = 100000" ) diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt b/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt index 11fe97e91c..fb1c85bce1 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt @@ -7,7 +7,7 @@ package kotlinx.coroutines.guide.test import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.scheduling.* -import java.io.* +import kotlinx.knit.test.* import java.util.concurrent.* import kotlin.test.* @@ -25,81 +25,35 @@ private inline fun outputException(name: String, block: () -> T): T = private const val SHUTDOWN_TIMEOUT = 5000L // 5 sec at most to wait private val OUT_ENABLED = systemProp("guide.tests.sout", false) -@Suppress("DEPRECATION") fun test(name: String, block: () -> R): List = outputException(name) { - val sout = System.out - val oldOut = if (OUT_ENABLED) System.out else NullOut - val oldErr = System.err - val bytesOut = ByteArrayOutputStream() - val tee = TeeOutput(bytesOut, oldOut) - val ps = PrintStream(tee) - - oldOut.println("--- Running test$name") - System.setErr(ps) - System.setOut(ps) - CommonPool.usePrivatePool() - DefaultScheduler.usePrivateScheduler() - DefaultExecutor.shutdown(SHUTDOWN_TIMEOUT) - resetCoroutineId() - val threadsBefore = currentThreads() - var bytes = ByteArray(0) - withVirtualTimeSource(oldOut) { - try { - val result = block() - require(result === Unit) { "Test 'main' shall return Unit" } - } catch (e: Throwable) { - System.err.print("Exception in thread \"main\" ") - e.printStackTrace() - } finally { - // capture output - bytes = bytesOut.toByteArray() - oldOut.println("--- shutting down") - // the shutdown - CommonPool.shutdown(SHUTDOWN_TIMEOUT) - DefaultScheduler.shutdown(SHUTDOWN_TIMEOUT) - shutdownDispatcherPools(SHUTDOWN_TIMEOUT) - DefaultExecutor.shutdown(SHUTDOWN_TIMEOUT) // the last man standing -- cleanup all pending tasks - if (tee.flushLine()) oldOut.println() - oldOut.println("--- done") - System.setOut(sout) - System.setErr(oldErr) - checkTestThreads(threadsBefore) - } - } - CommonPool.restore() - DefaultScheduler.restore() - return ByteArrayInputStream(bytes).bufferedReader().readLines() -} - -private class TeeOutput( - private val bytesOut: OutputStream, - private val oldOut: PrintStream -) : OutputStream() { - val limit = 200 - var lineLength = 0 - - fun flushLine(): Boolean { - if (lineLength > limit) - oldOut.print(" ($lineLength chars in total)") - val result = lineLength > 0 - lineLength = 0 - return result - } - - override fun write(b: Int) { - bytesOut.write(b) - if (b == 0x0d || b == 0x0a) { // new line - flushLine() - oldOut.write(b) - } else { - lineLength++ - if (lineLength <= limit) - oldOut.write(b) + try { + captureOutput(name, stdoutEnabled = OUT_ENABLED) { log -> + CommonPool.usePrivatePool() + DefaultScheduler.usePrivateScheduler() + DefaultExecutor.shutdown(SHUTDOWN_TIMEOUT) + resetCoroutineId() + val threadsBefore = currentThreads() + try { + withVirtualTimeSource(log) { + val result = block() + require(result === Unit) { "Test 'main' shall return Unit" } + } + } finally { + // the shutdown + log.println("--- shutting down") + CommonPool.shutdown(SHUTDOWN_TIMEOUT) + DefaultScheduler.shutdown(SHUTDOWN_TIMEOUT) + shutdownDispatcherPools(SHUTDOWN_TIMEOUT) + DefaultExecutor.shutdown(SHUTDOWN_TIMEOUT) // the last man standing -- cleanup all pending tasks + } + checkTestThreads(threadsBefore) // check thread if the main completed successfully } + } finally { + CommonPool.restore() + DefaultScheduler.restore() } } - private fun shutdownDispatcherPools(timeout: Long) { val threads = arrayOfNulls(Thread.activeCount()) val n = Thread.enumerate(threads) @@ -212,12 +166,6 @@ fun List.verifyLinesStart(vararg expected: String) = verify { checkEqualNumberOfLines(expected) } -private object NullOut : PrintStream(NullOutputStream()) - -private class NullOutputStream : OutputStream() { - override fun write(b: Int) = Unit -} - private inline fun List.verify(verification: () -> Unit) { try { verification() @@ -226,7 +174,6 @@ private inline fun List.verify(verification: () -> Unit) { println("Printing [delayed] test output") forEach { println(it) } } - throw t } } \ No newline at end of file diff --git a/reactive/knit.properties b/reactive/knit.properties new file mode 100644 index 0000000000..18aecba666 --- /dev/null +++ b/reactive/knit.properties @@ -0,0 +1,6 @@ +# +# Copyright 2016-2020 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 diff --git a/reactive/knit.test.include b/reactive/knit.test.include new file mode 100644 index 0000000000..dd9e61d041 --- /dev/null +++ b/reactive/knit.test.include @@ -0,0 +1,11 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +// This file was automatically generated from ${file.name} by Knit tool. Do not edit. +package ${test.package} + +import kotlinx.coroutines.guide.test.* +import org.junit.Test + +class ${test.name} : ReactiveTestBase() { \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-reactor/README.md b/reactive/kotlinx-coroutines-reactor/README.md index db1af0dab2..50e1602a3a 100644 --- a/reactive/kotlinx-coroutines-reactor/README.md +++ b/reactive/kotlinx-coroutines-reactor/README.md @@ -19,7 +19,7 @@ Integration with [Flow]: | --------------- | -------------- | --------------- | [Flow.asFlux] | `Flux` | Converts the given flow to the TCK-compliant Flux. -This adapter is integrated with Reactor's `Context` and coroutines [ReactiveContext]. +This adapter is integrated with Reactor's `Context` and coroutines [ReactorContext]. Conversion functions: @@ -35,11 +35,14 @@ 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 +[ReactorContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/-reactor-context/index.html [kotlinx.coroutines.Job.asMono]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-reactor/kotlinx.coroutines.reactor/kotlinx.coroutines.-job/as-mono.html [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 diff --git a/reactive/kotlinx-coroutines-rx2/README.md b/reactive/kotlinx-coroutines-rx2/README.md index b3874b05d3..7fbad95369 100644 --- a/reactive/kotlinx-coroutines-rx2/README.md +++ b/reactive/kotlinx-coroutines-rx2/README.md @@ -56,6 +56,8 @@ Conversion functions: [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 diff --git a/settings.gradle b/settings.gradle index 2925355dc1..3c1dc0c558 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,7 +15,6 @@ def module(String path) { // --------------------------- include('benchmarks') -include('knit') include('site') include "kotlinx-coroutines-core" diff --git a/ui/coroutines-guide-ui.md b/ui/coroutines-guide-ui.md index fc020cbd86..2ebe58f0e8 100644 --- a/ui/coroutines-guide-ui.md +++ b/ui/coroutines-guide-ui.md @@ -1,58 +1,3 @@ - - - # Guide to UI programming with coroutines This guide assumes familiarity with basic coroutine concepts that are @@ -100,7 +45,7 @@ context object for your favourite UI library, even if it is not included out of * [Advanced topics](#advanced-topics) * [Starting coroutine in UI event handlers without dispatch](#starting-coroutine-in-ui-event-handlers-without-dispatch) - + ## Setup @@ -409,7 +354,6 @@ You cannot do that from the main UI thread nor from the UI-confined coroutine di block the main UI thread and cause the freeze up of the UI. ## Debugging coroutines + Debugging asynchronous programs is challenging, because multiple concurrent coroutines are typically working at the same time. To help with that, `kotlinx.coroutines` comes with additional features for debugging: debug mode, stacktrace recovery and debug agent. @@ -86,6 +88,14 @@ java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/Mana at kotlinx.coroutines.debug.DebugProbes.install(DebugProbes.kt:49) --> +## Android optimization + +In optimized (release) builds with R8 version 1.6.0 or later both +[Debugging mode](../../docs/debugging.md#debug-mode) and +[Stacktrace recovery](../../docs/debugging.md#stacktrace-recovery) +are permanently turned off. +For more details see ["Optimization" section for Android](../ui/kotlinx-coroutines-android/README.md#optimization). + [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 diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt index 98ead14dee..b741a1a40f 100644 --- a/kotlinx-coroutines-core/common/src/selects/Select.kt +++ b/kotlinx-coroutines-core/common/src/selects/Select.kt @@ -264,7 +264,10 @@ internal class SelectBuilderImpl( assert { isSelected } // "Must be selected first" _result.loop { result -> when { - result === UNDECIDED -> if (_result.compareAndSet(UNDECIDED, value())) return + result === UNDECIDED -> { + val update = value() + if (_result.compareAndSet(UNDECIDED, update)) return + } result === COROUTINE_SUSPENDED -> if (_result.compareAndSet(COROUTINE_SUSPENDED, RESUMED)) { block() return diff --git a/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt index e835d343f3..94e3818ad9 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -16,7 +16,9 @@ internal actual typealias ReentrantLock = java.util.concurrent.locks.ReentrantLo internal actual inline fun ReentrantLock.withLock(action: () -> T) = this.withLockJvm(action) -internal actual fun identitySet(expectedSize: Int): MutableSet = Collections.newSetFromMap(IdentityHashMap(expectedSize)) +@Suppress("NOTHING_TO_INLINE") // So that R8 can completely remove ConcurrentKt class +internal actual inline fun identitySet(expectedSize: Int): MutableSet = + Collections.newSetFromMap(IdentityHashMap(expectedSize)) private val REMOVE_FUTURE_ON_CANCEL: Method? = try { ScheduledThreadPoolExecutor::class.java.getMethod("setRemoveOnCancelPolicy", Boolean::class.java) diff --git a/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt index 6f11cdf795..fe21a25a87 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.internal import kotlinx.coroutines.* @@ -30,11 +34,12 @@ internal object MainDispatcherLoader { MainDispatcherFactory::class.java.classLoader ).iterator().asSequence().toList() } + @Suppress("ConstantConditionIf") factories.maxBy { it.loadPriority }?.tryCreateDispatcher(factories) - ?: MissingMainCoroutineDispatcher(null) + ?: createMissingDispatcher() } catch (e: Throwable) { // Service loader can throw an exception as well - MissingMainCoroutineDispatcher(e) + createMissingDispatcher(e) } } } @@ -51,13 +56,30 @@ public fun MainDispatcherFactory.tryCreateDispatcher(factories: List E.sanitizeStackTrace(): E { return this } -internal actual fun recoverStackTrace(exception: E, continuation: Continuation<*>): E { +@Suppress("NOTHING_TO_INLINE") // Inline for better R8 optimization +internal actual inline fun recoverStackTrace(exception: E, continuation: Continuation<*>): E { if (!RECOVER_STACK_TRACES || continuation !is CoroutineStackFrame) return exception return recoverFromStackFrame(exception, continuation) } @@ -155,8 +156,11 @@ internal actual suspend inline fun recoverAndThrow(exception: Throwable): Nothin } } -internal actual fun unwrap(exception: E): E { - if (!RECOVER_STACK_TRACES) return exception +@Suppress("NOTHING_TO_INLINE") // Inline for better R8 optimizations +internal actual inline fun unwrap(exception: E): E = + if (!RECOVER_STACK_TRACES) exception else unwrapImpl(exception) + +internal fun unwrapImpl(exception: E): E { val cause = exception.cause // Fast-path to avoid array cloning if (cause == null || cause.javaClass != exception.javaClass) { diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt index 7a52d34849..03604ce436 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt @@ -73,7 +73,7 @@ import kotlin.random.* * Only [corePoolSize] workers can be created for regular CPU tasks) * * ### Support for blocking tasks - * The scheduler also supports the notion of [blocking][TaskMode.PROBABLY_BLOCKING] tasks. + * The scheduler also supports the notion of [blocking][TASK_PROBABLY_BLOCKING] tasks. * When executing or enqueuing blocking tasks, the scheduler notifies or creates one more worker in * addition to core pool size, so at any given moment, it has [corePoolSize] threads (potentially not yet created) * to serve CPU-bound tasks. To properly guarantee liveness, the scheduler maintains @@ -394,7 +394,7 @@ internal class CoroutineScheduler( } val skipUnpark = tailDispatch && currentWorker != null // Checking 'task' instead of 'notAdded' is completely okay - if (task.mode == TaskMode.NON_BLOCKING) { + if (task.mode == TASK_NON_BLOCKING) { if (skipUnpark) return signalCpuWork() } else { @@ -499,7 +499,7 @@ internal class CoroutineScheduler( */ if (state === WorkerState.TERMINATED) return task // Do not add CPU tasks in local queue if we are not able to execute it - if (task.mode === TaskMode.NON_BLOCKING && state === WorkerState.BLOCKING) { + if (task.mode == TASK_NON_BLOCKING && state === WorkerState.BLOCKING) { return task } mayHaveLocalTasks = true @@ -739,16 +739,16 @@ internal class CoroutineScheduler( afterTask(taskMode) } - private fun beforeTask(taskMode: TaskMode) { - if (taskMode == TaskMode.NON_BLOCKING) return + private fun beforeTask(taskMode: Int) { + if (taskMode == TASK_NON_BLOCKING) return // Always notify about new work when releasing CPU-permit to execute some blocking task if (tryReleaseCpu(WorkerState.BLOCKING)) { signalCpuWork() } } - private fun afterTask(taskMode: TaskMode) { - if (taskMode == TaskMode.NON_BLOCKING) return + private fun afterTask(taskMode: Int) { + if (taskMode == TASK_NON_BLOCKING) return decrementBlockingTasks() val currentState = state // Shutdown sequence of blocking dispatcher @@ -846,10 +846,10 @@ internal class CoroutineScheduler( } // It is invoked by this worker when it finds a task - private fun idleReset(mode: TaskMode) { + private fun idleReset(mode: Int) { terminationDeadline = 0L // reset deadline for termination if (state == WorkerState.PARKING) { - assert { mode == TaskMode.PROBABLY_BLOCKING } + assert { mode == TASK_PROBABLY_BLOCKING } state = WorkerState.BLOCKING } } @@ -926,12 +926,12 @@ internal class CoroutineScheduler( enum class WorkerState { /** - * Has CPU token and either executes [TaskMode.NON_BLOCKING] task or tries to find one. + * Has CPU token and either executes [TASK_NON_BLOCKING] task or tries to find one. */ CPU_ACQUIRED, /** - * Executing task with [TaskMode.PROBABLY_BLOCKING]. + * Executing task with [TASK_PROBABLY_BLOCKING]. */ BLOCKING, diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt index bbc2b35b16..bbbb706802 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling @@ -85,7 +85,7 @@ open class ExperimentalCoroutineDispatcher( */ public fun blocking(parallelism: Int = BLOCKING_DEFAULT_PARALLELISM): CoroutineDispatcher { require(parallelism > 0) { "Expected positive parallelism level, but have $parallelism" } - return LimitingDispatcher(this, parallelism, TaskMode.PROBABLY_BLOCKING) + return LimitingDispatcher(this, parallelism, TASK_PROBABLY_BLOCKING) } /** @@ -98,7 +98,7 @@ open class ExperimentalCoroutineDispatcher( public fun limited(parallelism: Int): CoroutineDispatcher { require(parallelism > 0) { "Expected positive parallelism level, but have $parallelism" } require(parallelism <= corePoolSize) { "Expected parallelism level lesser than core pool size ($corePoolSize), but have $parallelism" } - return LimitingDispatcher(this, parallelism, TaskMode.NON_BLOCKING) + return LimitingDispatcher(this, parallelism, TASK_NON_BLOCKING) } internal fun dispatchWithContext(block: Runnable, context: TaskContext, tailDispatch: Boolean) { @@ -132,7 +132,7 @@ open class ExperimentalCoroutineDispatcher( private class LimitingDispatcher( val dispatcher: ExperimentalCoroutineDispatcher, val parallelism: Int, - override val taskMode: TaskMode + override val taskMode: Int ) : ExecutorCoroutineDispatcher(), TaskContext, Executor { private val queue = ConcurrentLinkedQueue() diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt index c0a3e6435d..ca0b2de902 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.scheduling @@ -51,26 +51,23 @@ internal val IDLE_WORKER_KEEP_ALIVE_NS = TimeUnit.SECONDS.toNanos( @JvmField internal var schedulerTimeSource: TimeSource = NanoTimeSource -internal enum class TaskMode { - - /** - * Marker indicating that task is CPU-bound and will not block - */ - NON_BLOCKING, +/** + * Marker indicating that task is CPU-bound and will not block + */ +internal const val TASK_NON_BLOCKING = 0 - /** - * Marker indicating that task may potentially block, thus giving scheduler a hint that additional thread may be required - */ - PROBABLY_BLOCKING, -} +/** + * Marker indicating that task may potentially block, thus giving scheduler a hint that additional thread may be required + */ +internal const val TASK_PROBABLY_BLOCKING = 1 internal interface TaskContext { - val taskMode: TaskMode + val taskMode: Int // TASK_XXX fun afterTask() } internal object NonBlockingContext : TaskContext { - override val taskMode: TaskMode = TaskMode.NON_BLOCKING + override val taskMode: Int = TASK_NON_BLOCKING override fun afterTask() { // Nothing for non-blocking context @@ -82,10 +79,10 @@ internal abstract class Task( @JvmField var taskContext: TaskContext ) : Runnable { constructor() : this(0, NonBlockingContext) - inline val mode: TaskMode get() = taskContext.taskMode + inline val mode: Int get() = taskContext.taskMode // TASK_XXX } -internal inline val Task.isBlocking get() = taskContext.taskMode == TaskMode.PROBABLY_BLOCKING +internal inline val Task.isBlocking get() = taskContext.taskMode == TASK_PROBABLY_BLOCKING // Non-reusable Task implementation to wrap Runnable instances that do not otherwise implement task internal class TaskImpl( diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt index 38145af8c9..b0a5954b70 100644 --- a/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt +++ b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt @@ -12,11 +12,12 @@ import kotlin.coroutines.* import kotlin.test.* class CoroutineSchedulerTest : TestBase() { + private val taskModes = listOf(TASK_NON_BLOCKING, TASK_PROBABLY_BLOCKING) @Test fun testModesExternalSubmission() { // Smoke CoroutineScheduler(1, 1).use { - for (mode in TaskMode.values()) { + for (mode in taskModes) { val latch = CountDownLatch(1) it.dispatch(Runnable { latch.countDown() @@ -30,9 +31,9 @@ class CoroutineSchedulerTest : TestBase() { @Test fun testModesInternalSubmission() { // Smoke CoroutineScheduler(2, 2).use { - val latch = CountDownLatch(TaskMode.values().size) + val latch = CountDownLatch(taskModes.size) it.dispatch(Runnable { - for (mode in TaskMode.values()) { + for (mode in taskModes) { it.dispatch(Runnable { latch.countDown() }, TaskContextImpl(mode)) @@ -167,7 +168,7 @@ class CoroutineSchedulerTest : TestBase() { } } - private class TaskContextImpl(override val taskMode: TaskMode) : TaskContext { + private class TaskContextImpl(override val taskMode: Int) : TaskContext { override fun afterTask() {} } } \ No newline at end of file diff --git a/ui/kotlinx-coroutines-android/README.md b/ui/kotlinx-coroutines-android/README.md index 77bd2afb98..5be286cee1 100644 --- a/ui/kotlinx-coroutines-android/README.md +++ b/ui/kotlinx-coroutines-android/README.md @@ -5,6 +5,23 @@ Provides `Dispatchers.Main` context for Android applications. Read [Guide to UI programming with coroutines](https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md) for tutorial on this module. +# Optimization + +R8 and ProGuard rules are bundled into this module. +R8 is a replacement for ProGuard in Android ecosystem, it is enabled by default since Android gradle plugin 3.4.0 +(3.3.0-beta also had it enabled). +For best results it is recommended to use a recent version of R8, which produces a smaller binary. + +When optimizations are enabled with R8 version 1.6.0 or later +the following debugging features are permanently turned off to reduce the size of the resulting binary: + +* [Debugging mode](../../docs/debugging.md#debug-mode) +* [Stacktrace recovery](../../docs/debugging.md#stacktrace-recovery) +* The internal assertions in the library are also permanently removed. + +You can examine the corresponding rules in this +[`coroutines.pro`](resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro) file. + # Package kotlinx.coroutines.android Provides `Dispatchers.Main` context for Android applications. diff --git a/ui/kotlinx-coroutines-android/build.gradle b/ui/kotlinx-coroutines-android/build.gradle index c05881eb6c..68e2232cf2 100644 --- a/ui/kotlinx-coroutines-android/build.gradle +++ b/ui/kotlinx-coroutines-android/build.gradle @@ -4,13 +4,6 @@ repositories { google() - // TODO Remove once R8 is updated to a 1.6.x version. - maven { - url "http://storage.googleapis.com/r8-releases/raw/master" - metadataSources { - artifact() - } - } } configurations { @@ -25,8 +18,7 @@ dependencies { testImplementation "org.robolectric:robolectric:$robolectric_version" testImplementation "org.smali:baksmali:$baksmali_version" - // TODO Replace with a 1.6.x version once released to maven.google.com. - r8 'com.android.tools:r8:a7ce65837bec81c62261bf0adac73d9c09d32af2' + r8 'com.android.tools.build:builder:4.0.0-alpha06' // Contains r8-2.0.4-dev } class RunR8Task extends JavaExec { @@ -38,7 +30,7 @@ class RunR8Task extends JavaExec { File inputConfig @InputFile - final File inputConfigCommon = new File('r8-test-common.pro') + final File inputConfigCommon = new File('testdata/r8-test-common.pro') @InputFiles final File jarFile = project.jar.archivePath @@ -74,30 +66,36 @@ class RunR8Task extends JavaExec { } } -def optimizedDex = new File(buildDir, "dex-optim/") -def unOptimizedDex = new File(buildDir, "dex-unoptim/") +def optimizedDexDir = new File(buildDir, "dex-optim/") +def unOptimizedDexDir = new File(buildDir, "dex-unoptim/") + +def optimizedDexFile = new File(optimizedDexDir, "classes.dex") +def unOptimizedDexFile = new File(unOptimizedDexDir, "classes.dex") task runR8(type: RunR8Task, dependsOn: 'jar'){ - outputDex = optimizedDex - inputConfig = file('r8-test-rules.pro') + outputDex = optimizedDexDir + inputConfig = file('testdata/r8-test-rules.pro') } task runR8NoOptim(type: RunR8Task, dependsOn: 'jar'){ - outputDex = unOptimizedDex - inputConfig = file('r8-test-rules-no-optim.pro') + outputDex = unOptimizedDexDir + inputConfig = file('testdata/r8-test-rules-no-optim.pro') } test { // Ensure the R8-processed dex is built and supply its path as a property to the test. dependsOn(runR8) dependsOn(runR8NoOptim) - def dex1 = new File(optimizedDex, "classes.dex") - def dex2 = new File(unOptimizedDex, "classes.dex") - inputs.files(dex1, dex2) + inputs.files(optimizedDexFile, unOptimizedDexFile) - systemProperty 'dexPath', dex1.absolutePath - systemProperty 'noOptimDexPath', dex2.absolutePath + systemProperty 'dexPath', optimizedDexFile.absolutePath + systemProperty 'noOptimDexPath', unOptimizedDexFile.absolutePath + + // Output custom metric with the size of the optimized dex + doLast { + println("##teamcity[buildStatisticValue key='optimizedDexSize' value='${optimizedDexFile.length()}']") + } } tasks.withType(dokka.getClass()) { diff --git a/ui/kotlinx-coroutines-android/r8-test-rules.pro b/ui/kotlinx-coroutines-android/r8-test-rules.pro deleted file mode 100644 index 2e7fdd8eb6..0000000000 --- a/ui/kotlinx-coroutines-android/r8-test-rules.pro +++ /dev/null @@ -1,7 +0,0 @@ --include r8-test-common.pro - -# Ensure the custom, fast service loader implementation is removed. In the case of fast service -# loader encountering an exception it falls back to regular ServiceLoader in a way that cannot be -# optimized out by R8. --include resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro --checkdiscard class kotlinx.coroutines.internal.FastServiceLoader \ No newline at end of file diff --git a/ui/kotlinx-coroutines-android/resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro b/ui/kotlinx-coroutines-android/resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro index b57b07713d..fd25b215c3 100644 --- a/ui/kotlinx-coroutines-android/resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro +++ b/ui/kotlinx-coroutines-android/resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro @@ -5,6 +5,18 @@ boolean FAST_SERVICE_LOADER_ENABLED return false; } --assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoader { +-assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoaderKt { boolean ANDROID_DETECTED return true; +} + +# Disable support for "Missing Main Dispatcher", since we always have Android main dispatcher +-assumenosideeffects class kotlinx.coroutines.internal.MainDispatchersKt { + boolean SUPPORT_MISSING return false; +} + +# Statically turn off all debugging facilities and assertions +-assumenosideeffects class kotlinx.coroutines.DebugKt { + boolean getASSERTIONS_ENABLED() return false; + boolean getDEBUG() return false; + boolean getRECOVER_STACK_TRACES() return false; } \ No newline at end of file diff --git a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt index 09443269f7..198fe071f2 100644 --- a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt +++ b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.android @@ -12,17 +12,24 @@ import kotlin.coroutines.* @Keep internal class AndroidExceptionPreHandler : - AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler, Function0 { + AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler +{ + @Volatile + private var _preHandler: Any? = this // uninitialized marker - private val preHandler by lazy(this) - - // Reflectively lookup pre-handler. Implement Function0 to avoid generating second class for lambda - override fun invoke(): Method? = try { - Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { - Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) + // Reflectively lookup pre-handler. + private fun preHandler(): Method? { + val current = _preHandler + if (current !== this) return current as Method? + val declared = try { + Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { + Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) + } + } catch (e: Throwable) { + null /* not found */ } - } catch (e: Throwable) { - null /* not found */ + _preHandler = declared + return declared } override fun handleException(context: CoroutineContext, exception: Throwable) { @@ -39,7 +46,7 @@ internal class AndroidExceptionPreHandler : if (Build.VERSION.SDK_INT >= 28) { thread.uncaughtExceptionHandler.uncaughtException(thread, exception) } else { - (preHandler?.invoke(null) as? Thread.UncaughtExceptionHandler) + (preHandler()?.invoke(null) as? Thread.UncaughtExceptionHandler) ?.uncaughtException(thread, exception) } } diff --git a/ui/kotlinx-coroutines-android/r8-test-common.pro b/ui/kotlinx-coroutines-android/testdata/r8-test-common.pro similarity index 73% rename from ui/kotlinx-coroutines-android/r8-test-common.pro rename to ui/kotlinx-coroutines-android/testdata/r8-test-common.pro index 03f36a82fa..d29377eb40 100644 --- a/ui/kotlinx-coroutines-android/r8-test-common.pro +++ b/ui/kotlinx-coroutines-android/testdata/r8-test-common.pro @@ -8,5 +8,11 @@ void handleCoroutineException(...); } +# Entry point for the rest of coroutines machinery +-keep class kotlinx.coroutines.BuildersKt { + ** runBlocking(...); + ** launch(...); +} + # We are cheating a bit by not having android.jar on R8's library classpath. Ignore those warnings. -ignorewarnings \ No newline at end of file diff --git a/ui/kotlinx-coroutines-android/r8-test-rules-no-optim.pro b/ui/kotlinx-coroutines-android/testdata/r8-test-rules-no-optim.pro similarity index 58% rename from ui/kotlinx-coroutines-android/r8-test-rules-no-optim.pro rename to ui/kotlinx-coroutines-android/testdata/r8-test-rules-no-optim.pro index d6bd4a420b..61afeed2dd 100644 --- a/ui/kotlinx-coroutines-android/r8-test-rules-no-optim.pro +++ b/ui/kotlinx-coroutines-android/testdata/r8-test-rules-no-optim.pro @@ -1,4 +1,4 @@ -include r8-test-common.pro # Include the shrinker config used by legacy versions of AGP and ProGuard --include resources/META-INF/com.android.tools/proguard/coroutines.pro +-include ../resources/META-INF/com.android.tools/proguard/coroutines.pro diff --git a/ui/kotlinx-coroutines-android/testdata/r8-test-rules.pro b/ui/kotlinx-coroutines-android/testdata/r8-test-rules.pro new file mode 100644 index 0000000000..dde8600854 --- /dev/null +++ b/ui/kotlinx-coroutines-android/testdata/r8-test-rules.pro @@ -0,0 +1,14 @@ +-include r8-test-common.pro + +-include ../resources/META-INF/com.android.tools/r8-from-1.6.0/coroutines.pro + +# Validate that service-loader & debugger classes are discarded +-checkdiscard class kotlinx.coroutines.internal.FastServiceLoader +-checkdiscard class kotlinx.coroutines.DebugKt +-checkdiscard class kotlinx.coroutines.internal.StackTraceRecoveryKt + +# Real android projects do not keep this class, but somehow it is kept in this test (R8 bug) +# -checkdiscard class kotlinx.coroutines.internal.MissingMainCoroutineDispatcher + +# Should not keep this class, but it is still there (R8 bug) +#-checkdiscard class kotlinx.coroutines.CoroutineId \ No newline at end of file From 6d1a6e36e799db8ccc1dce2a252cc7fb16065656 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 18 Feb 2020 15:28:00 +0300 Subject: [PATCH 35/50] Update copyright year --- benchmarks/build.gradle | 2 +- .../flow/scrabble/RxJava2PlaysScrabble.java | 4 ++-- .../flow/scrabble/RxJava2PlaysScrabbleOpt.java | 4 ++-- .../optimizations/FlowableCharSequence.java | 2 +- .../scrabble/optimizations/FlowableSplit.java | 2 +- .../scrabble/optimizations/StringFlowable.java | 2 +- .../ChannelProducerConsumerBenchmark.kt | 4 ++-- .../kotlin/benchmarks/ChannelSinkBenchmark.kt | 2 +- .../benchmarks/ParametrizedDispatcherBase.kt | 4 ++-- .../kotlin/benchmarks/SemaphoreBenchmark.kt | 6 +++++- .../benchmarks/akka/PingPongAkkaBenchmark.kt | 17 +++++++---------- .../akka/StatefulActorAkkaBenchmark.kt | 18 +++++++----------- .../benchmarks/flow/FlatMapMergeBenchmark.kt | 4 ++-- .../flow/FlowFlattenMergeBenchmark.kt | 4 ++-- .../kotlin/benchmarks/flow/NumbersBenchmark.kt | 4 ++-- .../benchmarks/flow/SafeFlowBenchmark.kt | 2 +- .../kotlin/benchmarks/flow/TakeBenchmark.kt | 2 +- .../flow/scrabble/FlowPlaysScrabbleBase.kt | 3 +-- .../flow/scrabble/FlowPlaysScrabbleOpt.kt | 6 ++---- .../flow/scrabble/IterableSpliterator.kt | 2 +- .../flow/scrabble/ReactorPlaysScrabble.kt | 4 +--- .../flow/scrabble/SaneFlowPlaysScrabble.kt | 6 +----- .../flow/scrabble/SequencePlaysScrabble.kt | 3 +-- .../flow/scrabble/ShakespearePlaysScrabble.kt | 2 +- .../DispatchersContextSwitchBenchmark.kt | 2 +- .../benchmarks/scheduler/ForkJoinBenchmark.kt | 4 ++-- .../benchmarks/scheduler/LaunchBenchmark.kt | 4 ++-- .../scheduler/StatefulAwaitsBenchmark.kt | 4 ++-- .../actors/ConcurrentStatefulActorBenchmark.kt | 2 +- .../scheduler/actors/CycledActorsBenchmark.kt | 2 +- .../scheduler/actors/PingPongActorBenchmark.kt | 4 ++-- .../actors/PingPongWithBlockingContext.kt | 2 +- .../scheduler/actors/StatefulActorBenchmark.kt | 2 +- .../benchmarks/tailcall/SimpleChannel.kt | 4 ++-- .../tailcall/SimpleChannelBenchmark.kt | 2 +- .../kotlin/benchmarks/common/BenchmarkUtils.kt | 4 ++-- gradle/compile-common.gradle | 2 +- gradle/compile-js-multiplatform.gradle | 2 +- gradle/compile-js.gradle | 2 +- gradle/compile-jvm-multiplatform.gradle | 2 +- gradle/compile-jvm.gradle | 2 +- gradle/compile-native-multiplatform.gradle | 4 ++++ gradle/dokka.gradle | 2 +- gradle/experimental.gradle | 2 +- gradle/maven-central.gradle | 2 +- gradle/node-js.gradle | 2 +- gradle/publish-bintray.gradle | 2 +- gradle/publish-npm-js.gradle | 2 +- gradle/targets.gradle | 2 +- gradle/test-mocha-js.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../kotlinx-coroutines-guava/build.gradle | 4 ++-- .../src/ListenableFuture.kt | 2 +- .../kotlinx-coroutines-jdk8/build.gradle | 2 +- .../src/future/Future.kt | 2 +- .../src/stream/Stream.kt | 2 +- .../kotlinx-coroutines-jdk8/src/time/Time.kt | 2 +- .../src/Tasks.kt | 2 +- .../kotlinx-coroutines-slf4j/build.gradle | 6 +++++- .../kotlinx-coroutines-slf4j/src/MDCContext.kt | 2 +- js/example-frontend-js/build.gradle | 2 +- js/example-frontend-js/npm/webpack.config.js | 4 ++-- js/example-frontend-js/src/ExampleMain.kt | 18 +----------------- js/example-frontend-js/src/main/web/main.js | 2 +- js/example-frontend-js/src/main/web/style.css | 4 ++-- js/js-stub/build.gradle | 4 ++-- js/js-stub/src/Performance.kt | 4 ++-- js/js-stub/src/Promise.kt | 4 ++-- js/js-stub/src/Window.kt | 4 ++-- kotlinx-coroutines-bom/build.gradle | 2 +- .../common/src/AbstractCoroutine.kt | 2 +- .../common/src/Annotations.kt | 2 +- kotlinx-coroutines-core/common/src/Await.kt | 2 +- .../common/src/Builders.common.kt | 2 +- .../common/src/CancellableContinuation.kt | 2 +- .../common/src/CancellableContinuationImpl.kt | 2 +- .../common/src/CompletableDeferred.kt | 2 +- .../common/src/CompletableJob.kt | 4 ++-- .../common/src/CompletedExceptionally.kt | 2 +- .../common/src/CompletionHandler.common.kt | 2 +- .../common/src/CoroutineContext.common.kt | 4 ++-- .../common/src/CoroutineDispatcher.kt | 2 +- .../common/src/CoroutineExceptionHandler.kt | 2 +- .../common/src/CoroutineName.kt | 2 +- .../common/src/CoroutineScope.kt | 2 +- .../common/src/CoroutineStart.kt | 2 +- .../common/src/Debug.common.kt | 2 +- kotlinx-coroutines-core/common/src/Deferred.kt | 2 +- kotlinx-coroutines-core/common/src/Delay.kt | 2 +- .../common/src/Dispatchers.common.kt | 2 +- .../common/src/EventLoop.common.kt | 2 +- .../common/src/Exceptions.common.kt | 4 ++-- kotlinx-coroutines-core/common/src/Job.kt | 2 +- .../common/src/JobSupport.kt | 2 +- .../common/src/MainCoroutineDispatcher.kt | 2 +- .../common/src/NonCancellable.kt | 2 +- .../common/src/Runnable.common.kt | 4 ++-- .../common/src/SchedulerTask.common.kt | 2 +- .../common/src/Supervisor.kt | 2 +- kotlinx-coroutines-core/common/src/Timeout.kt | 2 +- .../common/src/Unconfined.kt | 4 ++-- kotlinx-coroutines-core/common/src/Yield.kt | 2 +- .../common/src/channels/AbstractChannel.kt | 2 +- .../src/channels/ArrayBroadcastChannel.kt | 4 ++-- .../common/src/channels/ArrayChannel.kt | 2 +- .../common/src/channels/Broadcast.kt | 2 +- .../common/src/channels/BroadcastChannel.kt | 2 +- .../common/src/channels/Channel.kt | 2 +- .../common/src/channels/ChannelCoroutine.kt | 2 +- .../common/src/channels/Channels.common.kt | 2 +- .../src/channels/ConflatedBroadcastChannel.kt | 2 +- .../common/src/channels/ConflatedChannel.kt | 6 +++++- .../common/src/channels/LinkedListChannel.kt | 2 +- .../common/src/channels/Produce.kt | 2 +- .../common/src/channels/RendezvousChannel.kt | 2 +- .../common/src/flow/Builders.kt | 2 +- .../common/src/flow/Channels.kt | 2 +- .../common/src/flow/Flow.kt | 2 +- .../common/src/flow/FlowCollector.kt | 2 +- .../common/src/flow/Migration.kt | 2 +- .../common/src/flow/internal/ChannelFlow.kt | 2 +- .../common/src/flow/internal/Combine.kt | 2 +- .../common/src/flow/internal/FlowCoroutine.kt | 2 +- .../src/flow/internal/FlowExceptions.common.kt | 2 +- .../common/src/flow/internal/Merge.kt | 2 +- .../common/src/flow/internal/NopCollector.kt | 4 ++-- .../common/src/flow/internal/NullSurrogate.kt | 2 +- .../src/flow/internal/SendingCollector.kt | 2 +- .../common/src/flow/operators/Context.kt | 2 +- .../common/src/flow/operators/Delay.kt | 2 +- .../common/src/flow/operators/Distinct.kt | 2 +- .../common/src/flow/operators/Emitters.kt | 2 +- .../common/src/flow/operators/Errors.kt | 2 +- .../common/src/flow/operators/Limit.kt | 2 +- .../common/src/flow/operators/Merge.kt | 2 +- .../common/src/flow/operators/Transform.kt | 2 +- .../common/src/flow/operators/Zip.kt | 2 +- .../common/src/flow/terminal/Collect.kt | 2 +- .../common/src/flow/terminal/Collection.kt | 2 +- .../common/src/flow/terminal/Count.kt | 2 +- .../common/src/flow/terminal/Reduce.kt | 2 +- .../common/src/internal/ArrayQueue.kt | 2 +- .../common/src/internal/Atomic.kt | 2 +- .../common/src/internal/Concurrent.common.kt | 2 +- .../src/internal/DispatchedContinuation.kt | 2 +- .../common/src/internal/DispatchedTask.kt | 2 +- .../common/src/internal/InlineList.kt | 2 +- .../src/internal/LockFreeLinkedList.common.kt | 4 ++-- .../common/src/internal/LockFreeTaskQueue.kt | 4 ++-- .../src/internal/MainDispatcherFactory.kt | 2 +- .../src/internal/ProbesSupport.common.kt | 2 +- .../common/src/internal/Scopes.kt | 2 +- .../common/src/internal/SegmentQueue.kt | 4 ++-- .../src/internal/StackTraceRecovery.common.kt | 2 +- .../common/src/internal/Symbol.kt | 2 +- .../common/src/internal/Synchronized.common.kt | 4 ++-- .../common/src/internal/SystemProps.common.kt | 4 ++-- .../src/internal/ThreadContext.common.kt | 2 +- .../common/src/internal/ThreadLocal.common.kt | 2 +- .../common/src/internal/ThreadSafeHeap.kt | 2 +- .../common/src/intrinsics/Cancellable.kt | 2 +- .../common/src/intrinsics/Undispatched.kt | 2 +- .../common/src/selects/Select.kt | 2 +- .../common/src/selects/SelectUnbiased.kt | 4 ++-- .../common/src/selects/WhileSelect.kt | 2 +- .../common/src/sync/Mutex.kt | 2 +- .../common/src/sync/Semaphore.kt | 4 ++-- .../js/src/CompletionHandler.kt | 2 +- .../js/src/CoroutineContext.kt | 4 ++-- .../js/src/CoroutineExceptionHandlerImpl.kt | 2 +- kotlinx-coroutines-core/js/src/Debug.kt | 4 ++-- kotlinx-coroutines-core/js/src/Dispatchers.kt | 2 +- kotlinx-coroutines-core/js/src/EventLoop.kt | 2 +- kotlinx-coroutines-core/js/src/Exceptions.kt | 4 ++-- kotlinx-coroutines-core/js/src/JSDispatcher.kt | 2 +- kotlinx-coroutines-core/js/src/Promise.kt | 2 +- kotlinx-coroutines-core/js/src/Runnable.kt | 2 +- .../js/src/SchedulerTask.kt | 2 +- kotlinx-coroutines-core/js/src/Window.kt | 4 ++-- .../js/src/flow/internal/FlowExceptions.kt | 2 +- .../js/src/internal/Concurrent.kt | 2 +- .../js/src/internal/CopyOnWriteList.kt | 2 +- .../js/src/internal/LinkedList.kt | 2 +- .../js/src/internal/ProbesSupport.kt | 2 +- .../js/src/internal/StackTraceRecovery.kt | 4 ++-- .../js/src/internal/Synchronized.kt | 4 ++-- .../js/src/internal/SystemProps.kt | 4 ++-- .../js/src/internal/ThreadContext.kt | 2 +- .../js/src/internal/ThreadLocal.kt | 4 ++-- kotlinx-coroutines-core/jvm/src/Builders.kt | 2 +- kotlinx-coroutines-core/jvm/src/CommonPool.kt | 2 +- .../jvm/src/CompletionHandler.kt | 4 ++-- .../jvm/src/CoroutineContext.kt | 2 +- .../jvm/src/CoroutineExceptionHandlerImpl.kt | 2 +- kotlinx-coroutines-core/jvm/src/Debug.kt | 2 +- .../jvm/src/DebugStrings.kt | 2 +- .../jvm/src/DefaultExecutor.kt | 2 +- kotlinx-coroutines-core/jvm/src/Dispatchers.kt | 2 +- kotlinx-coroutines-core/jvm/src/EventLoop.kt | 4 ++-- kotlinx-coroutines-core/jvm/src/Exceptions.kt | 4 ++-- kotlinx-coroutines-core/jvm/src/Executors.kt | 2 +- kotlinx-coroutines-core/jvm/src/Future.kt | 2 +- kotlinx-coroutines-core/jvm/src/Runnable.kt | 2 +- .../jvm/src/SchedulerTask.kt | 2 +- .../jvm/src/ThreadContextElement.kt | 2 +- .../jvm/src/ThreadPoolDispatcher.kt | 2 +- kotlinx-coroutines-core/jvm/src/TimeSource.kt | 2 +- .../jvm/src/channels/Actor.kt | 2 +- .../jvm/src/channels/TickerChannels.kt | 2 +- .../jvm/src/flow/internal/FlowExceptions.kt | 2 +- .../jvm/src/internal/Concurrent.kt | 2 +- .../jvm/src/internal/ExceptionsConstuctor.kt | 2 +- .../jvm/src/internal/FastServiceLoader.kt | 4 ++++ .../jvm/src/internal/LockFreeLinkedList.kt | 2 +- .../jvm/src/internal/MainDispatchers.kt | 4 ++-- .../jvm/src/internal/ProbesSupport.kt | 2 +- .../jvm/src/internal/StackTraceRecovery.kt | 4 ++-- .../jvm/src/internal/Synchronized.kt | 4 ++-- .../jvm/src/internal/SystemProps.kt | 2 +- .../jvm/src/internal/ThreadContext.kt | 2 +- .../jvm/src/internal/ThreadLocal.kt | 2 +- .../jvm/src/scheduling/CoroutineScheduler.kt | 2 +- .../jvm/src/scheduling/Dispatcher.kt | 2 +- .../jvm/src/scheduling/Tasks.kt | 2 +- .../jvm/src/scheduling/WorkQueue.kt | 2 +- .../jvm/src/test_/TestCoroutineContext.kt | 4 ++-- ...ellableContinuationResumeCloseStressTest.kt | 2 +- kotlinx-coroutines-core/native/src/Builders.kt | 2 +- .../native/src/CompletionHandler.kt | 2 +- .../native/src/CoroutineContext.kt | 4 ++-- .../src/CoroutineExceptionHandlerImpl.kt | 2 +- kotlinx-coroutines-core/native/src/Debug.kt | 4 ++-- .../native/src/Dispatchers.kt | 2 +- .../native/src/EventLoop.kt | 4 ++-- .../native/src/Exceptions.kt | 2 +- kotlinx-coroutines-core/native/src/Runnable.kt | 2 +- .../native/src/SchedulerTask.kt | 2 +- .../native/src/flow/internal/FlowExceptions.kt | 2 +- .../native/src/internal/Concurrent.kt | 2 +- .../native/src/internal/CopyOnWriteList.kt | 2 +- .../native/src/internal/LinkedList.kt | 2 +- .../native/src/internal/ProbesSupport.kt | 2 +- .../native/src/internal/StackTraceRecovery.kt | 4 ++-- .../native/src/internal/Synchronized.kt | 4 ++-- .../native/src/internal/SystemProps.kt | 4 ++-- .../native/src/internal/ThreadContext.kt | 2 +- .../native/src/internal/ThreadLocal.kt | 4 ++-- kotlinx-coroutines-debug/build.gradle | 2 +- kotlinx-coroutines-debug/src/AgentPremain.kt | 2 +- kotlinx-coroutines-debug/src/CoroutineInfo.kt | 2 +- kotlinx-coroutines-debug/src/DebugProbes.kt | 2 +- .../src/internal/DebugProbesImpl.kt | 2 +- .../src/internal/NoOpProbes.kt | 2 +- .../src/junit4/CoroutinesTimeout.kt | 2 +- .../src/junit4/CoroutinesTimeoutStatement.kt | 2 +- kotlinx-coroutines-test/src/DelayController.kt | 4 ++++ kotlinx-coroutines-test/src/TestBuilders.kt | 2 +- .../src/TestCoroutineDispatcher.kt | 4 ++-- .../src/TestCoroutineExceptionHandler.kt | 2 +- .../src/TestCoroutineScope.kt | 4 ++-- kotlinx-coroutines-test/src/TestDispatchers.kt | 2 +- .../src/internal/MainTestDispatcher.kt | 2 +- publication-validator/build.gradle | 2 +- publication-validator/gradle.properties | 6 +++++- .../kotlinx-coroutines-reactive/build.gradle | 4 ++-- .../kotlinx-coroutines-reactive/src/Await.kt | 2 +- .../kotlinx-coroutines-reactive/src/Channel.kt | 2 +- .../src/ContextInjector.kt | 6 +++++- .../kotlinx-coroutines-reactive/src/Convert.kt | 2 +- .../src/Migration.kt | 4 ++-- .../kotlinx-coroutines-reactive/src/Publish.kt | 2 +- .../kotlinx-coroutines-reactor/build.gradle | 4 ++-- ...kotlinx.coroutines.reactive.ContextInjector | 2 +- .../kotlinx-coroutines-reactor/src/Convert.kt | 4 ++-- .../kotlinx-coroutines-reactor/src/Flux.kt | 2 +- .../src/Migration.kt | 4 ++++ .../kotlinx-coroutines-reactor/src/Mono.kt | 2 +- .../src/ReactorContext.kt | 4 ++++ .../src/ReactorContextInjector.kt | 6 +++++- .../src/ReactorFlow.kt | 4 ++-- .../src/Scheduler.kt | 4 ++-- reactive/kotlinx-coroutines-rx2/build.gradle | 2 +- reactive/kotlinx-coroutines-rx2/src/RxAwait.kt | 2 +- .../src/RxCancellable.kt | 4 ++-- .../kotlinx-coroutines-rx2/src/RxChannel.kt | 2 +- .../src/RxCompletable.kt | 2 +- .../kotlinx-coroutines-rx2/src/RxConvert.kt | 2 +- .../kotlinx-coroutines-rx2/src/RxFlowable.kt | 4 ++-- reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt | 2 +- .../kotlinx-coroutines-rx2/src/RxObservable.kt | 2 +- .../kotlinx-coroutines-rx2/src/RxScheduler.kt | 2 +- .../kotlinx-coroutines-rx2/src/RxSingle.kt | 2 +- settings.gradle | 2 +- site/build.gradle | 2 +- site/docs/assets/js/api.js | 15 ++------------- stdlib-stubs/build.gradle | 2 +- stdlib-stubs/src/Continuation.kt | 4 ++-- stdlib-stubs/src/ContinuationInterceptor.kt | 2 +- stdlib-stubs/src/CoroutineContext.kt | 2 +- stdlib-stubs/src/Result.kt | 2 +- .../src/EmptyCoroutineScopeImpl.kt | 11 +++++++---- .../animation-app/app/build.gradle | 2 +- .../app/src/main/AndroidManifest.xml | 6 +++++- .../app/src/main/res/layout/activity_main.xml | 2 +- .../app/src/main/res/layout/content_main.xml | 2 +- .../main/res/mipmap-anydpi-v26/ic_launcher.xml | 6 +++++- .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 +++++- .../animation-app/build.gradle | 2 +- .../animation-app/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../animation-app/settings.gradle | 4 ++++ .../example-app/app/build.gradle | 2 +- .../app/src/main/AndroidManifest.xml | 6 +++++- .../app/src/main/res/layout/activity_main.xml | 2 +- .../app/src/main/res/layout/content_main.xml | 2 +- .../example-app/build.gradle | 2 +- .../example-app/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- ...otlinx.coroutines.CoroutineExceptionHandler | 2 +- ...x.coroutines.internal.MainDispatcherFactory | 2 +- .../src/AndroidExceptionPreHandler.kt | 2 +- .../src/HandlerDispatcher.kt | 2 +- .../src/JavaFxDispatcher.kt | 2 +- .../src/SwingDispatcher.kt | 2 +- 324 files changed, 469 insertions(+), 446 deletions(-) diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index 88148130c5..a192f2795e 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ sourceCompatibility = 1.8 targetCompatibility = 1.8 diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabble.java index 2a85d0dbdd..04f7210381 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble; @@ -160,4 +160,4 @@ public List>> play() throws Exception { .blockingGet() ; return finalList2 ; } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java b/benchmarks/src/jmh/java/benchmarks/flow/scrabble/RxJava2PlaysScrabbleOpt.java index 7a7cb1aa4e..71c7604d0c 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble; @@ -171,4 +171,4 @@ public List>> play() throws Exception { return finalList2 ; } -} \ No newline at end of file +} 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 a45dbdd2c5..5f93b4ee88 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 83c203e42f..af8696c802 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 3d36a0d8e7..cf6cc79b79 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 941e3d84ba..deeea77af9 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks @@ -147,4 +147,4 @@ private fun doWork(): Unit = Blackhole.consumeCPU(ThreadLocalRandom.current().ne private const val WORK_MIN = 50L private const val WORK_MAX = 100L -private const val APPROX_BATCH_SIZE = 100000 \ No newline at end of file +private const val APPROX_BATCH_SIZE = 100000 diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt index 8b5e90aaf5..9c7f38a6f9 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelSinkBenchmark.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-2020 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/ParametrizedDispatcherBase.kt b/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt index fab052370e..b635d1ef2c 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/ParametrizedDispatcherBase.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks @@ -44,4 +44,4 @@ abstract class ParametrizedDispatcherBase : CoroutineScope { closeable?.close() } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt index a651d8fa63..5da5dc8920 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/SemaphoreBenchmark.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package benchmarks import benchmarks.common.* @@ -85,4 +89,4 @@ enum class SemaphoreBenchDispatcherCreator(val create: (parallelism: Int) -> Cor private const val WORK_INSIDE = 80 private const val WORK_OUTSIDE = 40 -private const val BATCH_SIZE = 1000000 \ No newline at end of file +private const val BATCH_SIZE = 1000000 diff --git a/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt index 1a6e9d4036..ea9aeca94d 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/akka/PingPongAkkaBenchmark.kt @@ -1,18 +1,15 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.akka -import akka.actor.ActorRef -import akka.actor.ActorSystem -import akka.actor.Props -import akka.actor.UntypedAbstractActor -import com.typesafe.config.ConfigFactory +import akka.actor.* +import com.typesafe.config.* import org.openjdk.jmh.annotations.* -import scala.concurrent.Await -import scala.concurrent.duration.Duration -import java.util.concurrent.CountDownLatch +import scala.concurrent.* +import scala.concurrent.duration.* +import java.util.concurrent.* const val N_MESSAGES = 100_000 @@ -117,4 +114,4 @@ open class PingPongAkkaBenchmark { } } } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt index 4e3ad6ce4d..5cfb86dda0 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/akka/StatefulActorAkkaBenchmark.kt @@ -1,19 +1,15 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.akka -import akka.actor.ActorRef -import akka.actor.ActorSystem -import akka.actor.Props -import akka.actor.UntypedAbstractActor -import com.typesafe.config.ConfigFactory +import akka.actor.* +import com.typesafe.config.* import org.openjdk.jmh.annotations.* -import scala.concurrent.Await -import scala.concurrent.duration.Duration -import java.util.concurrent.CountDownLatch -import java.util.concurrent.ThreadLocalRandom +import scala.concurrent.* +import scala.concurrent.duration.* +import java.util.concurrent.* const val ROUNDS = 10_000 const val STATE_SIZE = 1024 @@ -171,4 +167,4 @@ open class StatefulActorAkkaBenchmark { initLatch.countDown() } } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlatMapMergeBenchmark.kt index f6690977a2..f3b2082ae1 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow @@ -44,4 +44,4 @@ open class FlatMapMergeBenchmark { } } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/FlowFlattenMergeBenchmark.kt index c91c3da964..3fff2697cc 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow @@ -60,4 +60,4 @@ enum class FlowsNumberStrategy(val get: (concurrency: Int) -> Int) { // If you change this variable please be sure that you change variable elements in the generate_plots_flow_flatten_merge.py // python script as well private const val ELEMENTS = 100_000 -private const val WORK = 100 \ No newline at end of file +private const val WORK = 100 diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/NumbersBenchmark.kt index e0bc2fcc48..0cb31056bb 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @@ -103,4 +103,4 @@ open class NumbersBenchmark { .filter { (it + 1) % 3 == 0L }.count() .blockingGet() } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/SafeFlowBenchmark.kt index f8c459fd0d..258df9b03e 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 84afca2439..1c469a69b9 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/scrabble/FlowPlaysScrabbleBase.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleBase.kt index b556053b5d..9e39b43b8b 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-2019 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble @@ -7,7 +7,6 @@ package benchmarks.flow.scrabble import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.openjdk.jmh.annotations.* -import java.lang.Long.* import java.lang.Long.max import java.util.* import java.util.concurrent.* diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/FlowPlaysScrabbleOpt.kt index 921f390dce..62cc2e5c50 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-2019 JetBrains s.r.o. and contributors Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble @@ -7,11 +7,9 @@ package benchmarks.flow.scrabble import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.openjdk.jmh.annotations.* -import java.lang.Long.max +import java.lang.Long.* import java.util.* import java.util.concurrent.* -import java.util.stream.* -import kotlin.math.* @Warmup(iterations = 7, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 7, time = 1, timeUnit = TimeUnit.SECONDS) diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/IterableSpliterator.kt index 434ea1e19d..32c0d4c8fa 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 9adc4f1f59..2283d6c3fb 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ReactorPlaysScrabble.kt @@ -1,14 +1,12 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble -import org.openjdk.jmh.annotations.* import reactor.core.publisher.* import java.lang.Long.* import java.util.* -import java.util.concurrent.* import java.util.function.Function /*@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt index 597667c1c6..0a4f69672f 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SaneFlowPlaysScrabble.kt @@ -1,9 +1,5 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -/* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 5f4f4c2d1a..87d0e61232 100644 --- a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt +++ b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/SequencePlaysScrabble.kt @@ -1,11 +1,10 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.flow.scrabble import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* import org.openjdk.jmh.annotations.* import java.lang.Long.* import java.util.* diff --git a/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt b/benchmarks/src/jmh/kotlin/benchmarks/flow/scrabble/ShakespearePlaysScrabble.kt index 7eaa3f0a5d..7beb54cc3d 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-2019 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 e7f806760e..3012b9178a 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 0c731c3ba8..724a5909b9 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler @@ -164,4 +164,4 @@ private fun compute(coefficients: LongArray, start: Int, end: Int): Double { } return result -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/LaunchBenchmark.kt index 8435ddc262..a0de6016c4 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler @@ -53,4 +53,4 @@ open class LaunchBenchmark : ParametrizedDispatcherBase() { stopBarrier.reset() } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/StatefulAwaitsBenchmark.kt index 93667c0c2f..f829573c87 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler @@ -117,4 +117,4 @@ open class StatefulAsyncBenchmark : ParametrizedDispatcherBase() { } sum } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/ConcurrentStatefulActorBenchmark.kt index 6998577310..6ac97ad3e7 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 67548f624e..71018abcbc 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 2d547e2660..4c6ae7754c 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.scheduler.actors @@ -100,4 +100,4 @@ fun CoroutineScope.pongActorCoroutine(capacity: Int = 1) = else -> error("Cannot happen $message") } } - } \ No newline at end of file + } diff --git a/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt b/benchmarks/src/jmh/kotlin/benchmarks/scheduler/actors/PingPongWithBlockingContext.kt index 86a9440a58..dcbda090e8 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 fb342295a6..01691a2d77 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 ee1ef724cb..c217fcae91 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.tailcall @@ -95,4 +95,4 @@ class CancellableReusableChannel : SimpleChannel() { producer = it.intercepted() COROUTINE_SUSPENDED } -} \ No newline at end of file +} diff --git a/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/tailcall/SimpleChannelBenchmark.kt index 09ff7697f6..7bb962b3b8 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 fd2832bfeb..0057573bc6 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package benchmarks.common @@ -14,4 +14,4 @@ fun doGeomDistrWork(work: Int) { while (true) { if (r.nextDouble() < p) break } -} \ No newline at end of file +} diff --git a/gradle/compile-common.gradle b/gradle/compile-common.gradle index ebad56a312..403c3345d0 100644 --- a/gradle/compile-common.gradle +++ b/gradle/compile-common.gradle @@ -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-2020 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 a9a4ea29c6..a7da5c6377 100644 --- a/gradle/compile-js-multiplatform.gradle +++ b/gradle/compile-js-multiplatform.gradle @@ -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-2020 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') diff --git a/gradle/compile-js.gradle b/gradle/compile-js.gradle index 4b1e3bde7f..d0697cfd3a 100644 --- a/gradle/compile-js.gradle +++ b/gradle/compile-js.gradle @@ -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-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 diff --git a/gradle/compile-jvm-multiplatform.gradle b/gradle/compile-jvm-multiplatform.gradle index f6d76fcada..b226c97a57 100644 --- a/gradle/compile-jvm-multiplatform.gradle +++ b/gradle/compile-jvm-multiplatform.gradle @@ -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-2020 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 index 3ab25456f8..261136bc87 100644 --- a/gradle/compile-jvm.gradle +++ b/gradle/compile-jvm.gradle @@ -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-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 diff --git a/gradle/compile-native-multiplatform.gradle b/gradle/compile-native-multiplatform.gradle index a51057ee3e..378e4f5f98 100644 --- a/gradle/compile-native-multiplatform.gradle +++ b/gradle/compile-native-multiplatform.gradle @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + project.ext.nativeMainSets = [] project.ext.nativeTestSets = [] diff --git a/gradle/dokka.gradle b/gradle/dokka.gradle index 99201a9f28..bc22189e14 100644 --- a/gradle/dokka.gradle +++ b/gradle/dokka.gradle @@ -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-2020 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 51bda6c595..b045a1f630 100644 --- a/gradle/experimental.gradle +++ b/gradle/experimental.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // For new mpp diff --git a/gradle/maven-central.gradle b/gradle/maven-central.gradle index 4f9df6ab75..eef7993921 100644 --- a/gradle/maven-central.gradle +++ b/gradle/maven-central.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // --------------- pom configuration --------------- diff --git a/gradle/node-js.gradle b/gradle/node-js.gradle index 208f4ad293..d4bd86ca56 100644 --- a/gradle/node-js.gradle +++ b/gradle/node-js.gradle @@ -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-2020 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 9062896b58..c8dd8f12b5 100644 --- a/gradle/publish-bintray.gradle +++ b/gradle/publish-bintray.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // Configures publishing of Maven artifacts to Bintray diff --git a/gradle/publish-npm-js.gradle b/gradle/publish-npm-js.gradle index a2991db492..f471c48047 100644 --- a/gradle/publish-npm-js.gradle +++ b/gradle/publish-npm-js.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ def prop(name, defVal) { diff --git a/gradle/targets.gradle b/gradle/targets.gradle index d4e560fd5a..08f3d989aa 100644 --- a/gradle/targets.gradle +++ b/gradle/targets.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ /* diff --git a/gradle/test-mocha-js.gradle b/gradle/test-mocha-js.gradle index af9d892b07..464898e584 100644 --- a/gradle/test-mocha-js.gradle +++ b/gradle/test-mocha-js.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // -- Testing with Mocha under Node diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c141e3345e..7068436015 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # distributionBase=GRADLE_USER_HOME diff --git a/integration/kotlinx-coroutines-guava/build.gradle b/integration/kotlinx-coroutines-guava/build.gradle index 9e44b99864..16bdea50fd 100644 --- a/integration/kotlinx-coroutines-guava/build.gradle +++ b/integration/kotlinx-coroutines-guava/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ ext.guava_version = '28.0-jre' @@ -13,4 +13,4 @@ tasks.withType(dokka.getClass()) { url = new URL("https://google.github.io/guava/releases/$guava_version/api/docs/") packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL() } -} \ No newline at end of file +} diff --git a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt index e502ff464f..974e246283 100644 --- a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt +++ b/integration/kotlinx-coroutines-guava/src/ListenableFuture.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.guava diff --git a/integration/kotlinx-coroutines-jdk8/build.gradle b/integration/kotlinx-coroutines-jdk8/build.gradle index 3b17101f53..099159292e 100644 --- a/integration/kotlinx-coroutines-jdk8/build.gradle +++ b/integration/kotlinx-coroutines-jdk8/build.gradle @@ -1,4 +1,4 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 16829a8018..3cd848f2cf 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.future diff --git a/integration/kotlinx-coroutines-jdk8/src/stream/Stream.kt b/integration/kotlinx-coroutines-jdk8/src/stream/Stream.kt index 1b5e479fd4..641a83a682 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 031ac61fd9..1673116fac 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.time diff --git a/integration/kotlinx-coroutines-play-services/src/Tasks.kt b/integration/kotlinx-coroutines-play-services/src/Tasks.kt index 4952daa7c4..f9b9a60419 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/build.gradle b/integration/kotlinx-coroutines-slf4j/build.gradle index 161a0b845a..05accb75d3 100644 --- a/integration/kotlinx-coroutines-slf4j/build.gradle +++ b/integration/kotlinx-coroutines-slf4j/build.gradle @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + dependencies { compile 'org.slf4j:slf4j-api:1.7.25' testCompile 'io.github.microutils:kotlin-logging:1.5.4' @@ -10,4 +14,4 @@ tasks.withType(dokka.getClass()) { packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL() url = new URL("https://www.slf4j.org/apidocs/") } -} \ No newline at end of file +} diff --git a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt index c9b1dd9a88..6dbcef6ebe 100644 --- a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt +++ b/integration/kotlinx-coroutines-slf4j/src/MDCContext.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-2020 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 index 52b8bb97de..ff62455494 100644 --- a/js/example-frontend-js/build.gradle +++ b/js/example-frontend-js/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: 'kotlin-dce-js' diff --git a/js/example-frontend-js/npm/webpack.config.js b/js/example-frontend-js/npm/webpack.config.js index 2124d875eb..a208d047b3 100644 --- a/js/example-frontend-js/npm/webpack.config.js +++ b/js/example-frontend-js/npm/webpack.config.js @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // This script is copied to "build" directory and run from there @@ -50,4 +50,4 @@ module.exports = { sourceMap: true }) ] -}; \ No newline at end of file +}; diff --git a/js/example-frontend-js/src/ExampleMain.kt b/js/example-frontend-js/src/ExampleMain.kt index e3952a238e..f3e8c081b1 100644 --- a/js/example-frontend-js/src/ExampleMain.kt +++ b/js/example-frontend-js/src/ExampleMain.kt @@ -1,21 +1,5 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -/* - * Copyright 2016-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2016-2020 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/main.js b/js/example-frontend-js/src/main/web/main.js index c0cb691db5..d2440ffaef 100644 --- a/js/example-frontend-js/src/main/web/main.js +++ b/js/example-frontend-js/src/main/web/main.js @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // ------ Main bundle for example application ------ diff --git a/js/example-frontend-js/src/main/web/style.css b/js/example-frontend-js/src/main/web/style.css index 29dc9ff82f..31d0ebc058 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ #scene { @@ -16,4 +16,4 @@ position: absolute; background: #ffa450; border-radius: 50%; -} \ No newline at end of file +} diff --git a/js/js-stub/build.gradle b/js/js-stub/build.gradle index 20067b7c6b..b2ca0398d9 100644 --- a/js/js-stub/build.gradle +++ b/js/js-stub/build.gradle @@ -1,9 +1,9 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ compileKotlin { kotlinOptions { freeCompilerArgs += "-Xallow-kotlin-package" } -} \ No newline at end of file +} diff --git a/js/js-stub/src/Performance.kt b/js/js-stub/src/Performance.kt index 4c63ed0039..353a08fff8 100644 --- a/js/js-stub/src/Performance.kt +++ b/js/js-stub/src/Performance.kt @@ -1,9 +1,9 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package org.w3c.performance public abstract class Performance { abstract fun now(): Double -} \ No newline at end of file +} diff --git a/js/js-stub/src/Promise.kt b/js/js-stub/src/Promise.kt index a7d501a6e5..7413a872be 100644 --- a/js/js-stub/src/Promise.kt +++ b/js/js-stub/src/Promise.kt @@ -1,7 +1,7 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin.js -public open class Promise \ No newline at end of file +public open class Promise diff --git a/js/js-stub/src/Window.kt b/js/js-stub/src/Window.kt index 82c6fcfdb1..f54ed0d7bb 100644 --- a/js/js-stub/src/Window.kt +++ b/js/js-stub/src/Window.kt @@ -1,7 +1,7 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package org.w3c.dom -public abstract class Window \ No newline at end of file +public abstract class Window diff --git a/kotlinx-coroutines-bom/build.gradle b/kotlinx-coroutines-bom/build.gradle index d78f079e8d..25221e3609 100644 --- a/kotlinx-coroutines-bom/build.gradle +++ b/kotlinx-coroutines-bom/build.gradle @@ -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-2020 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/common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt index 18088777a5..22111f0ce2 100644 --- a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/AbstractCoroutine.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-2020 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 742a7d7c66..106fd03ddb 100644 --- a/kotlinx-coroutines-core/common/src/Annotations.kt +++ b/kotlinx-coroutines-core/common/src/Annotations.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-2020 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 3da0ad5ee9..dd1e1771f2 100644 --- a/kotlinx-coroutines-core/common/src/Await.kt +++ b/kotlinx-coroutines-core/common/src/Await.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-2020 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/Builders.common.kt b/kotlinx-coroutines-core/common/src/Builders.common.kt index ff5d406643..7dd1b174ee 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/CancellableContinuation.kt b/kotlinx-coroutines-core/common/src/CancellableContinuation.kt index d1e99529a5..fd5cd083e2 100644 --- a/kotlinx-coroutines-core/common/src/CancellableContinuation.kt +++ b/kotlinx-coroutines-core/common/src/CancellableContinuation.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-2020 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 27c83256c8..0cc9b57dec 100644 --- a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt +++ b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.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-2020 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/CompletableDeferred.kt b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt index 732d07225f..f6cf90d515 100644 --- a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt +++ b/kotlinx-coroutines-core/common/src/CompletableDeferred.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-2020 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 9a632276fe..4b4d16bc53 100644 --- a/kotlinx-coroutines-core/common/src/CompletableJob.kt +++ b/kotlinx-coroutines-core/common/src/CompletableJob.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -36,4 +36,4 @@ public interface CompletableJob : Job { * a [CancellationException] with the [exception] as a cause for the sake of diagnostic. */ public fun completeExceptionally(exception: Throwable): Boolean -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt b/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt index b75d43070e..b426785bd7 100644 --- a/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt +++ b/kotlinx-coroutines-core/common/src/CompletedExceptionally.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-2020 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 00bac305d5..bf6900087d 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 a8b5686253..51374603c3 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -20,4 +20,4 @@ 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 fun Continuation<*>.toDebugString(): String -internal expect val CoroutineContext.coroutineName: String? \ No newline at end of file +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 393f6cb526..3a54390f0b 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.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-2020 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 ee440b5310..cd7fd0d7ca 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.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-2020 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 4a7e9ea4f8..7f09a5897c 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineName.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineName.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-2020 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 ca387338dc..a6b79bdb5a 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineScope.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineScope.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-2020 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/CoroutineStart.kt b/kotlinx-coroutines-core/common/src/CoroutineStart.kt index 9e283b0db9..1272ce7c3a 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineStart.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineStart.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-2020 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/Debug.common.kt b/kotlinx-coroutines-core/common/src/Debug.common.kt index 3bd7aabe92..013b983a74 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Deferred.kt b/kotlinx-coroutines-core/common/src/Deferred.kt index 04152f903e..f05abbdb43 100644 --- a/kotlinx-coroutines-core/common/src/Deferred.kt +++ b/kotlinx-coroutines-core/common/src/Deferred.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-2020 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 acb924020a..3404f63611 100644 --- a/kotlinx-coroutines-core/common/src/Delay.kt +++ b/kotlinx-coroutines-core/common/src/Delay.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-2020 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 5a957e7555..dba57abc88 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 c8bc384c3f..ba331e20df 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 2c0b5ce2cd..64f8911e9d 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -29,4 +29,4 @@ internal class CoroutinesInternalError(message: String, cause: Throwable) : Erro internal expect fun Throwable.addSuppressedThrowable(other: Throwable) // For use in tests -internal expect val RECOVER_STACK_TRACES: Boolean \ No newline at end of file +internal expect val RECOVER_STACK_TRACES: Boolean diff --git a/kotlinx-coroutines-core/common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt index 133e24fa69..4d4e37ee25 100644 --- a/kotlinx-coroutines-core/common/src/Job.kt +++ b/kotlinx-coroutines-core/common/src/Job.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-2020 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/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index c7a7195acb..e52aaeaa8e 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.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-2020 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/MainCoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt index bead3c89a4..3f2ddcd69f 100644 --- a/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt +++ b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.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-2020 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 c48faea7f8..45803cf945 100644 --- a/kotlinx-coroutines-core/common/src/NonCancellable.kt +++ b/kotlinx-coroutines-core/common/src/NonCancellable.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-2020 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 6c258d854d..692c700b50 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -18,4 +18,4 @@ public expect interface Runnable { * Creates [Runnable] task instance. */ @Suppress("FunctionName") -public expect inline fun Runnable(crossinline block: () -> Unit): Runnable \ No newline at end of file +public expect inline fun Runnable(crossinline block: () -> Unit): Runnable diff --git a/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt b/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt index 7b767f5167..dbdf45ead5 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 63542a9a17..1991119053 100644 --- a/kotlinx-coroutines-core/common/src/Supervisor.kt +++ b/kotlinx-coroutines-core/common/src/Supervisor.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-2020 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/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt index 7e6f0d0e2d..8aedba30a1 100644 --- a/kotlinx-coroutines-core/common/src/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/Timeout.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-2020 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/Unconfined.kt b/kotlinx-coroutines-core/common/src/Unconfined.kt index 794ee1e181..ce03a28765 100644 --- a/kotlinx-coroutines-core/common/src/Unconfined.kt +++ b/kotlinx-coroutines-core/common/src/Unconfined.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -37,4 +37,4 @@ internal class YieldContext : AbstractCoroutineContextElement(Key) { @JvmField var dispatcherWasUnconfined = false -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/Yield.kt b/kotlinx-coroutines-core/common/src/Yield.kt index 5d931340af..e0af04ddb7 100644 --- a/kotlinx-coroutines-core/common/src/Yield.kt +++ b/kotlinx-coroutines-core/common/src/Yield.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-2020 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/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt index dfca3b32d1..8d078e49ca 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/ArrayBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt index 5f3eb32d8f..19334ea706 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels @@ -371,4 +371,4 @@ internal class ArrayBroadcastChannel( override val bufferDebugString: String get() = "(buffer:capacity=${buffer.size},size=$size)" -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt index aa0e1822ed..e26579eff7 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Broadcast.kt b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt index e487a53431..318283cca9 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 2981d8394e..312480f943 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 27334fee72..8dff4ec2b7 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 f824e69f8d..3f53b48c53 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Channels.common.kt b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt index cd37bfbc2e..4a73d5d59d 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channels.common.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @file:JvmName("ChannelsKt") diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt index 74fc444855..5813902dfc 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 ed0f3705a7..ea7c1e5567 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.channels import kotlinx.coroutines.* @@ -133,4 +137,4 @@ internal open class ConflatedChannel : AbstractChannel() { override val bufferDebugString: String get() = "(value=$value)" -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt b/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt index d925be1c50..e66bbb2279 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt index a0c3284240..26bd544811 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 98df176937..700f50908c 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 111bc723b6..4157576aae 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 612fe8c285..e3a64b9568 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 7e98013e83..378b9f148e 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 7254c6d7bb..8c6208bfd2 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 ade6078ff7..16bde89f44 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/internal/ChannelFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt index 8b79c09b6e..2b62be44f4 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 584178d8c4..67da32c9f9 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 1917afb8d7..36d7a3a20d 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 7058dca5f5..3064ed260b 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 6fbbea31dd..798f38b8bd 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 d1b6ad2bf5..62a20a07c3 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.flow.internal @@ -10,4 +10,4 @@ internal object NopCollector : FlowCollector { override suspend fun emit(value: Any?) { // does nothing } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt b/kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt index 97faee0d74..22e1957419 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 b6d578fedc..1620a2ac7c 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 043c839fff..4e6167f0cd 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 5f2f46629f..e473561e3d 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 89491f4166..53c4d6d2aa 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Emitters.kt b/kotlinx-coroutines-core/common/src/flow/operators/Emitters.kt index e87e4802d0..9236fd26d8 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 9b7a91f155..ad77ba9b14 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 6f4e8e754c..988c22f489 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Merge.kt b/kotlinx-coroutines-core/common/src/flow/operators/Merge.kt index d69afad2f3..85fe90b91f 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 da5e288a66..f446c80c23 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 ebc1dcd9d8..03bddf8330 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Collect.kt b/kotlinx-coroutines-core/common/src/flow/terminal/Collect.kt index de7d260d69..52d060f255 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 e07be61688..6b05ca1840 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 d57dfdefc2..63cf52434b 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 eb3ce288a2..ccf8241f41 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 61a3233809..09806cd22b 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 1fb4cefd1c..56fd35b731 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Concurrent.common.kt b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt index d23d09cefb..1836a5284d 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/DispatchedContinuation.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt index 2369f18a51..acb6c48513 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/internal/DispatchedTask.kt b/kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt index 98b45d56a3..9588d22b17 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/internal/InlineList.kt b/kotlinx-coroutines-core/common/src/internal/InlineList.kt index 062a9100f9..bac8610c1a 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/LockFreeLinkedList.common.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt index 2ba7d98e39..216ce7b56b 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -85,4 +85,4 @@ public expect class PrepareOp: OpDescriptor { @JvmField @SharedImmutable -internal val REMOVE_PREPARED: Any = Symbol("REMOVE_PREPARED") \ No newline at end of file +internal val REMOVE_PREPARED: Any = Symbol("REMOVE_PREPARED") diff --git a/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeTaskQueue.kt index c764f51792..dfee8e9f2b 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -304,4 +304,4 @@ internal class LockFreeTaskQueueCore( // FROZEN | CLOSED fun Long.addFailReason(): Int = if (this and CLOSED_MASK != 0L) ADD_CLOSED else ADD_FROZEN } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt b/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt index d5eb42de3e..93142df2cd 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 1124ff313b..763c1ca364 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 6adab128e3..9bb2ce3d29 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/SegmentQueue.kt b/kotlinx-coroutines-core/common/src/internal/SegmentQueue.kt index 370fcfc502..0091d13671 100644 --- a/kotlinx-coroutines-core/common/src/internal/SegmentQueue.kt +++ b/kotlinx-coroutines-core/common/src/internal/SegmentQueue.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -176,4 +176,4 @@ internal abstract class Segment>(val id: Long, prev: S?) { if (this.prev.compareAndSet(curPrev, prev)) return } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt b/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt index 06d6b694b0..15ba40f2f4 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 6f7f673f83..4fa8f540af 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Synchronized.common.kt b/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt index 8bcc8f0419..3afc7e1802 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -16,4 +16,4 @@ public expect open class SynchronizedObject() // marker abstract class * @suppress **This an internal API and should not be used from general code.** */ @InternalCoroutinesApi -public expect inline fun synchronized(lock: SynchronizedObject, block: () -> T): T \ No newline at end of file +public expect inline fun synchronized(lock: SynchronizedObject, block: () -> T): T diff --git a/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt index b7e67ec0bd..4cb629e9df 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmName("SystemPropsKt") @@ -62,4 +62,4 @@ internal fun systemProp( * * **Note: this function should be used in JVM tests only, other platforms use the default value.** */ -internal expect fun systemProp(propertyName: String): String? \ No newline at end of file +internal expect fun systemProp(propertyName: String): String? diff --git a/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt index 43b5dbe652..94695e8a05 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 4c09e62640..0f4ec342df 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 0ee570d154..12d6a38a81 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 2027d9bd50..0951349ebd 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 0aa9cd7f84..525e322f08 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 b741a1a40f..3ba1b06215 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/SelectUnbiased.kt b/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt index 37521d8b49..edcf123b0a 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.selects @@ -66,4 +66,4 @@ internal class UnbiasedSelectBuilderImpl(uCont: Continuation) : override fun onTimeout(timeMillis: Long, block: suspend () -> R) { clauses += { instance.onTimeout(timeMillis, block) } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt b/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt index 1726f5f01a..33d4d7ec16 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 4a223552d8..1b11bc96cc 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 d72f989b61..aa7ed63d3d 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.sync @@ -213,4 +213,4 @@ private val RESUMED = Symbol("RESUMED") @SharedImmutable private val CANCELLED = Symbol("CANCELLED") @SharedImmutable -private val SEGMENT_SIZE = systemProp("kotlinx.coroutines.semaphore.segmentSize", 16) \ No newline at end of file +private val SEGMENT_SIZE = systemProp("kotlinx.coroutines.semaphore.segmentSize", 16) diff --git a/kotlinx-coroutines-core/js/src/CompletionHandler.kt b/kotlinx-coroutines-core/js/src/CompletionHandler.kt index 19a9be884a..e81e43511a 100644 --- a/kotlinx-coroutines-core/js/src/CompletionHandler.kt +++ b/kotlinx-coroutines-core/js/src/CompletionHandler.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-2020 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 3390fc1b8c..c0b0c511f9 100644 --- a/kotlinx-coroutines-core/js/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/js/src/CoroutineContext.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -50,4 +50,4 @@ 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 fun Continuation<*>.toDebugString(): String = toString() -internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on JS \ No newline at end of file +internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on JS diff --git a/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt index 4bc378d376..524d4b5543 100644 --- a/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.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-2020 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 57a94d4364..7cd9bedd2f 100644 --- a/kotlinx-coroutines-core/js/src/Debug.kt +++ b/kotlinx-coroutines-core/js/src/Debug.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -21,4 +21,4 @@ internal actual val Any.hexAddress: String internal actual val Any.classSimpleName: String get() = this::class.simpleName ?: "Unknown" -internal actual inline fun assert(value: () -> Boolean) {} \ No newline at end of file +internal actual inline fun assert(value: () -> Boolean) {} diff --git a/kotlinx-coroutines-core/js/src/Dispatchers.kt b/kotlinx-coroutines-core/js/src/Dispatchers.kt index 3667f2e1b5..995801ea0d 100644 --- a/kotlinx-coroutines-core/js/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/js/src/Dispatchers.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-2020 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 19d75c0925..0039678a93 100644 --- a/kotlinx-coroutines-core/js/src/EventLoop.kt +++ b/kotlinx-coroutines-core/js/src/EventLoop.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-2020 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 2a8968849a..39b3344ac1 100644 --- a/kotlinx-coroutines-core/js/src/Exceptions.kt +++ b/kotlinx-coroutines-core/js/src/Exceptions.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -39,4 +39,4 @@ internal actual class JobCancellationException public actual constructor( internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) { /* empty */ } // For use in tests -internal actual val RECOVER_STACK_TRACES: Boolean = false \ No newline at end of file +internal actual val RECOVER_STACK_TRACES: Boolean = false diff --git a/kotlinx-coroutines-core/js/src/JSDispatcher.kt b/kotlinx-coroutines-core/js/src/JSDispatcher.kt index dc98332fe3..a0dfcba2b7 100644 --- a/kotlinx-coroutines-core/js/src/JSDispatcher.kt +++ b/kotlinx-coroutines-core/js/src/JSDispatcher.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-2020 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 44615d2806..6c3de76426 100644 --- a/kotlinx-coroutines-core/js/src/Promise.kt +++ b/kotlinx-coroutines-core/js/src/Promise.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-2020 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 b240a943d0..19710f971b 100644 --- a/kotlinx-coroutines-core/js/src/Runnable.kt +++ b/kotlinx-coroutines-core/js/src/Runnable.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-2020 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 dce72f5b71..29a92cfb24 100644 --- a/kotlinx-coroutines-core/js/src/SchedulerTask.kt +++ b/kotlinx-coroutines-core/js/src/SchedulerTask.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-2020 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 3c1cdb42a6..8284daef8d 100644 --- a/kotlinx-coroutines-core/js/src/Window.kt +++ b/kotlinx-coroutines-core/js/src/Window.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -60,4 +60,4 @@ private class WindowAnimationQueue(private val window: Window) { with(element) { dispatcher.resumeUndispatched(timestamp) } } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/js/src/flow/internal/FlowExceptions.kt index 2df8a5b73e..f818bfbb37 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 ec8f6b1150..5555137f7f 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 8a7a55d987..8f42160b55 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 7adc7a7865..7daeef2d94 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/js/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt index 81b6476bc2..a13a141f4d 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 75b1d7915f..234bbcadc2 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -22,4 +22,4 @@ internal actual interface CoroutineStackFrame { internal actual typealias StackTraceElement = Any internal actual fun Throwable.initCause(cause: Throwable) { -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/js/src/internal/Synchronized.kt b/kotlinx-coroutines-core/js/src/internal/Synchronized.kt index fbed54622c..0911dbe115 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -17,4 +17,4 @@ public actual typealias SynchronizedObject = Any */ @InternalCoroutinesApi public actual inline fun synchronized(lock: SynchronizedObject, block: () -> T): T = - block() \ No newline at end of file + block() diff --git a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt index 6779d4e5d8..564630f623 100644 --- a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt +++ b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt @@ -1,7 +1,7 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal -internal actual fun systemProp(propertyName: String): String? = null \ No newline at end of file +internal actual fun systemProp(propertyName: String): String? = null diff --git a/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt index d9daf256e3..4a9513ab9e 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 2ee0a4fd0d..09f501a4f5 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -9,4 +9,4 @@ internal actual class CommonThreadLocal actual constructor() { @Suppress("UNCHECKED_CAST") actual fun get(): T = value as T actual fun set(value: T) { this.value = value } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/src/Builders.kt b/kotlinx-coroutines-core/jvm/src/Builders.kt index c6e121f957..b8a250fef6 100644 --- a/kotlinx-coroutines-core/jvm/src/Builders.kt +++ b/kotlinx-coroutines-core/jvm/src/Builders.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-2020 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/CommonPool.kt b/kotlinx-coroutines-core/jvm/src/CommonPool.kt index 1b5aae988f..60f30cfe14 100644 --- a/kotlinx-coroutines-core/jvm/src/CommonPool.kt +++ b/kotlinx-coroutines-core/jvm/src/CommonPool.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-2020 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/CompletionHandler.kt b/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt index d425d6d8d5..706f6c498e 100644 --- a/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt +++ b/kotlinx-coroutines-core/jvm/src/CompletionHandler.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -19,4 +19,4 @@ internal actual abstract class CancelHandlerBase actual constructor() : Completi internal actual inline val CancelHandlerBase.asHandler: CompletionHandler get() = this @Suppress("NOTHING_TO_INLINE") -internal actual inline fun CompletionHandler.invokeIt(cause: Throwable?) = invoke(cause) \ No newline at end of file +internal actual inline fun CompletionHandler.invokeIt(cause: Throwable?) = invoke(cause) diff --git a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt index d0375a61e1..5a69d48aac 100644 --- a/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/jvm/src/CoroutineContext.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-2020 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/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt index 7eb7576fdd..af37e73c39 100644 --- a/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.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-2020 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 5aa37931ef..aac06ade79 100644 --- a/kotlinx-coroutines-core/jvm/src/Debug.kt +++ b/kotlinx-coroutines-core/jvm/src/Debug.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-2020 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 78ad41811a..184fb655e3 100644 --- a/kotlinx-coroutines-core/jvm/src/DebugStrings.kt +++ b/kotlinx-coroutines-core/jvm/src/DebugStrings.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-2020 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 19adcef2be..4e107a7b1d 100644 --- a/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt +++ b/kotlinx-coroutines-core/jvm/src/DefaultExecutor.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-2020 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 1ddad469cc..b9df7ab2e6 100644 --- a/kotlinx-coroutines-core/jvm/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/jvm/src/Dispatchers.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-2020 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/EventLoop.kt b/kotlinx-coroutines-core/jvm/src/EventLoop.kt index 598f424b61..d86f632a69 100644 --- a/kotlinx-coroutines-core/jvm/src/EventLoop.kt +++ b/kotlinx-coroutines-core/jvm/src/EventLoop.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -46,4 +46,4 @@ internal actual fun createEventLoop(): EventLoop = BlockingEventLoop(Thread.curr */ @InternalCoroutinesApi public fun processNextEventInCurrentThread(): Long = - ThreadLocalEventLoop.currentOrNull()?.processNextEvent() ?: Long.MAX_VALUE \ No newline at end of file + ThreadLocalEventLoop.currentOrNull()?.processNextEvent() ?: Long.MAX_VALUE diff --git a/kotlinx-coroutines-core/jvm/src/Exceptions.kt b/kotlinx-coroutines-core/jvm/src/Exceptions.kt index 2aa399c21c..22a02a30bb 100644 --- a/kotlinx-coroutines-core/jvm/src/Exceptions.kt +++ b/kotlinx-coroutines-core/jvm/src/Exceptions.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("FunctionName") @@ -71,4 +71,4 @@ internal actual class JobCancellationException public actual constructor( @Suppress("NOTHING_TO_INLINE") internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) = - addSuppressed(other) \ No newline at end of file + addSuppressed(other) diff --git a/kotlinx-coroutines-core/jvm/src/Executors.kt b/kotlinx-coroutines-core/jvm/src/Executors.kt index 7d7f4ba7be..e4d25a735e 100644 --- a/kotlinx-coroutines-core/jvm/src/Executors.kt +++ b/kotlinx-coroutines-core/jvm/src/Executors.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-2020 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 19a375d49e..54825c309d 100644 --- a/kotlinx-coroutines-core/jvm/src/Future.kt +++ b/kotlinx-coroutines-core/jvm/src/Future.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-2020 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/Runnable.kt b/kotlinx-coroutines-core/jvm/src/Runnable.kt index 2acd55461a..14d011053d 100644 --- a/kotlinx-coroutines-core/jvm/src/Runnable.kt +++ b/kotlinx-coroutines-core/jvm/src/Runnable.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-2020 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 da2c85503b..478df822f4 100644 --- a/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt +++ b/kotlinx-coroutines-core/jvm/src/SchedulerTask.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-2020 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 4e8b6cc42e..1fd851104d 100644 --- a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt +++ b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.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-2020 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 ce2f81c62c..7291f0c4fc 100644 --- a/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt +++ b/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.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-2020 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/TimeSource.kt b/kotlinx-coroutines-core/jvm/src/TimeSource.kt index 99a0ca4586..4b6fd9915c 100644 --- a/kotlinx-coroutines-core/jvm/src/TimeSource.kt +++ b/kotlinx-coroutines-core/jvm/src/TimeSource.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-2020 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 b951505839..95fbb6fca8 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/TickerChannels.kt b/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt index 4bbf77d604..0f9321a58d 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/flow/internal/FlowExceptions.kt b/kotlinx-coroutines-core/jvm/src/flow/internal/FlowExceptions.kt index 3e714321f7..863c2cc4ab 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/internal/Concurrent.kt b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt index 94e3818ad9..171748ff68 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt index 8d11c6fdb7..a03163db36 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 6267581f3c..30cd09ef36 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/FastServiceLoader.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.internal import java.io.* diff --git a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt index 70568aa278..19cb159b6b 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/MainDispatchers.kt b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt index fe21a25a87..b3e49752e0 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -128,4 +128,4 @@ public object MissingMainCoroutineDispatcherFactory : MainDispatcherFactory { override fun createDispatcher(allFactories: List): MainCoroutineDispatcher { return MissingMainCoroutineDispatcher(null) } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt index baa9682788..2f4d1e052e 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 9c9931c96f..f5c5c24b47 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("UNCHECKED_CAST") @@ -213,4 +213,4 @@ internal actual typealias StackTraceElement = java.lang.StackTraceElement internal actual fun Throwable.initCause(cause: Throwable) { // Resolved to member, verified by test initCause(cause) -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt b/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt index 51dcee4baf..2b57b26cbd 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -17,4 +17,4 @@ public actual typealias SynchronizedObject = Any */ @InternalCoroutinesApi public actual inline fun synchronized(lock: SynchronizedObject, block: () -> T): T = - kotlin.synchronized(lock, block) \ No newline at end of file + kotlin.synchronized(lock, block) diff --git a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt index ef5ab24118..bf34c1a97b 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 375dc60b66..9d9d30e41d 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/ThreadLocal.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt index 39c87bed1c..ff0970a219 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 03604ce436..815fa26941 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt index bbbb706802..7398f12fe7 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 ca0b2de902..247615d777 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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/WorkQueue.kt b/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt index 1a0603e413..354b3a1b3b 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 3a1bf3a664..8a0bd1a187 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test @@ -293,4 +293,4 @@ public fun withTestContext(testContext: TestCoroutineContext = TestCoroutineCont throw AssertionError("Coroutine encountered unhandled exceptions:\n$exceptions") } } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt index 45ff86f5a0..b8bc3f00be 100644 --- a/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/CancellableContinuationResumeCloseStressTest.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-2020 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/Builders.kt b/kotlinx-coroutines-core/native/src/Builders.kt index 0dc90d556a..975fc98db7 100644 --- a/kotlinx-coroutines-core/native/src/Builders.kt +++ b/kotlinx-coroutines-core/native/src/Builders.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-2020 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 ac833acb7d..706f6c498e 100644 --- a/kotlinx-coroutines-core/native/src/CompletionHandler.kt +++ b/kotlinx-coroutines-core/native/src/CompletionHandler.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-2020 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 debdc97f74..bcc7f48963 100644 --- a/kotlinx-coroutines-core/native/src/CoroutineContext.kt +++ b/kotlinx-coroutines-core/native/src/CoroutineContext.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -39,4 +39,4 @@ 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 fun Continuation<*>.toDebugString(): String = toString() -internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on native \ No newline at end of file +internal actual val CoroutineContext.coroutineName: String? get() = null // not supported on native diff --git a/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt index 5efa9249ec..dff845b27f 100644 --- a/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt +++ b/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.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-2020 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 653cb06978..26787f865a 100644 --- a/kotlinx-coroutines-core/native/src/Debug.kt +++ b/kotlinx-coroutines-core/native/src/Debug.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -15,4 +15,4 @@ internal actual val Any.classSimpleName: String get() = this::class.simpleName ? @SymbolName("Kotlin_Any_hashCode") external fun Any.id(): Int // Note: can return negative value on K/N -internal actual inline fun assert(value: () -> Boolean) {} \ No newline at end of file +internal actual inline fun assert(value: () -> Boolean) {} diff --git a/kotlinx-coroutines-core/native/src/Dispatchers.kt b/kotlinx-coroutines-core/native/src/Dispatchers.kt index 8aed212973..6c650046a0 100644 --- a/kotlinx-coroutines-core/native/src/Dispatchers.kt +++ b/kotlinx-coroutines-core/native/src/Dispatchers.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-2020 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 8f2dfeb339..d6c6525504 100644 --- a/kotlinx-coroutines-core/native/src/EventLoop.kt +++ b/kotlinx-coroutines-core/native/src/EventLoop.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines @@ -19,4 +19,4 @@ internal class EventLoopImpl: EventLoopImplBase() { internal actual fun createEventLoop(): EventLoop = EventLoopImpl() -internal actual fun nanoTime(): Long = getTimeNanos() \ No newline at end of file +internal actual fun nanoTime(): Long = getTimeNanos() diff --git a/kotlinx-coroutines-core/native/src/Exceptions.kt b/kotlinx-coroutines-core/native/src/Exceptions.kt index b7657da74c..39b3344ac1 100644 --- a/kotlinx-coroutines-core/native/src/Exceptions.kt +++ b/kotlinx-coroutines-core/native/src/Exceptions.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-2020 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 b240a943d0..19710f971b 100644 --- a/kotlinx-coroutines-core/native/src/Runnable.kt +++ b/kotlinx-coroutines-core/native/src/Runnable.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-2020 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 2da03c1bf1..4154d53e07 100644 --- a/kotlinx-coroutines-core/native/src/SchedulerTask.kt +++ b/kotlinx-coroutines-core/native/src/SchedulerTask.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-2020 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 ed74d58313..4705471907 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 84d5d3496b..486dc8f057 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 c81f6530e0..b925317b3d 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 bcdd0e8377..60d0857be5 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-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 81b6476bc2..a13a141f4d 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 c27280072c..49f043da36 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -21,4 +21,4 @@ internal actual interface CoroutineStackFrame { internal actual typealias StackTraceElement = Any internal actual fun Throwable.initCause(cause: Throwable) { -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-core/native/src/internal/Synchronized.kt b/kotlinx-coroutines-core/native/src/internal/Synchronized.kt index fbed54622c..0911dbe115 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -17,4 +17,4 @@ public actual typealias SynchronizedObject = Any */ @InternalCoroutinesApi public actual inline fun synchronized(lock: SynchronizedObject, block: () -> T): T = - block() \ No newline at end of file + block() diff --git a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt index 6779d4e5d8..564630f623 100644 --- a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt +++ b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt @@ -1,7 +1,7 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal -internal actual fun systemProp(propertyName: String): String? = null \ No newline at end of file +internal actual fun systemProp(propertyName: String): String? = null diff --git a/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt index d9daf256e3..4a9513ab9e 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 c214a63bb6..db62371c1f 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-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -12,4 +12,4 @@ internal actual class CommonThreadLocal actual constructor() { @Suppress("UNCHECKED_CAST") actual fun get(): T = value as T actual fun set(value: T) { this.value = value } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-debug/build.gradle b/kotlinx-coroutines-debug/build.gradle index 420a88bd38..7fc2e22369 100644 --- a/kotlinx-coroutines-debug/build.gradle +++ b/kotlinx-coroutines-debug/build.gradle @@ -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-2020 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/AgentPremain.kt b/kotlinx-coroutines-debug/src/AgentPremain.kt index 1ff996e5aa..94ff0098b3 100644 --- a/kotlinx-coroutines-debug/src/AgentPremain.kt +++ b/kotlinx-coroutines-debug/src/AgentPremain.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-2020 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-debug/src/CoroutineInfo.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt index 84cd9f370e..97bc2be595 100644 --- a/kotlinx-coroutines-debug/src/CoroutineInfo.kt +++ b/kotlinx-coroutines-debug/src/CoroutineInfo.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("PropertyName") diff --git a/kotlinx-coroutines-debug/src/DebugProbes.kt b/kotlinx-coroutines-debug/src/DebugProbes.kt index 7508954298..eb6a59b6c1 100644 --- a/kotlinx-coroutines-debug/src/DebugProbes.kt +++ b/kotlinx-coroutines-debug/src/DebugProbes.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-2020 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-debug/src/internal/DebugProbesImpl.kt b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt index 72416ab1f2..a7ceb1468d 100644 --- a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.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-2020 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-debug/src/internal/NoOpProbes.kt b/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt index d32eeb674b..4854f5d7c6 100644 --- a/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt +++ b/kotlinx-coroutines-debug/src/internal/NoOpProbes.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-2020 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 437ec6967e..16b5356721 100644 --- a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.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-2020 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 1fa4ab938a..72413b91f2 100644 --- a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.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-2020 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-test/src/DelayController.kt b/kotlinx-coroutines-test/src/DelayController.kt index 54e9c8ae5e..a777d4b9a3 100644 --- a/kotlinx-coroutines-test/src/DelayController.kt +++ b/kotlinx-coroutines-test/src/DelayController.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.test import kotlinx.coroutines.CoroutineDispatcher diff --git a/kotlinx-coroutines-test/src/TestBuilders.kt b/kotlinx-coroutines-test/src/TestBuilders.kt index 7ef77bd643..3b8efb9fe1 100644 --- a/kotlinx-coroutines-test/src/TestBuilders.kt +++ b/kotlinx-coroutines-test/src/TestBuilders.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-2020 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 386fc8380d..aab869c98b 100644 --- a/kotlinx-coroutines-test/src/TestCoroutineDispatcher.kt +++ b/kotlinx-coroutines-test/src/TestCoroutineDispatcher.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test @@ -212,4 +212,4 @@ private class TimedRunnable( } override fun toString() = "TimedRunnable(time=$time, run=$runnable)" -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt b/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt index 41d14d0841..f585aa03ab 100644 --- a/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.kt +++ b/kotlinx-coroutines-test/src/TestCoroutineExceptionHandler.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-2020 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 d39e6adf53..4034fcaa74 100644 --- a/kotlinx-coroutines-test/src/TestCoroutineScope.kt +++ b/kotlinx-coroutines-test/src/TestCoroutineScope.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.test @@ -69,4 +69,4 @@ private inline val CoroutineContext.delayController: DelayController "TestCoroutineScope requires a DelayController such as TestCoroutineDispatcher as " + "the ContinuationInterceptor (Dispatcher)" ) - } \ No newline at end of file + } diff --git a/kotlinx-coroutines-test/src/TestDispatchers.kt b/kotlinx-coroutines-test/src/TestDispatchers.kt index 532db9381f..a247ca8365 100644 --- a/kotlinx-coroutines-test/src/TestDispatchers.kt +++ b/kotlinx-coroutines-test/src/TestDispatchers.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-2020 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 bb52999d08..c18e4108bb 100644 --- a/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt +++ b/kotlinx-coroutines-test/src/internal/MainTestDispatcher.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-2020 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/publication-validator/build.gradle b/publication-validator/build.gradle index cc19ae4027..993572f6b5 100644 --- a/publication-validator/build.gradle +++ b/publication-validator/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ plugins { diff --git a/publication-validator/gradle.properties b/publication-validator/gradle.properties index 29e08e8ca8..aefd041a54 100644 --- a/publication-validator/gradle.properties +++ b/publication-validator/gradle.properties @@ -1 +1,5 @@ -kotlin.code.style=official \ No newline at end of file +# +# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. +# + +kotlin.code.style=official diff --git a/reactive/kotlinx-coroutines-reactive/build.gradle b/reactive/kotlinx-coroutines-reactive/build.gradle index f544ab448b..ad97c63f45 100644 --- a/reactive/kotlinx-coroutines-reactive/build.gradle +++ b/reactive/kotlinx-coroutines-reactive/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ dependencies { @@ -31,4 +31,4 @@ tasks.withType(dokka.getClass()) { url = new URL("https://www.reactive-streams.org/reactive-streams-$reactive_streams_version-javadoc/") packageListUrl = projectDir.toPath().resolve("package.list").toUri().toURL() } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactive/src/Await.kt b/reactive/kotlinx-coroutines-reactive/src/Await.kt index 072773a4fe..317baab5f5 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Await.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Await.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-2020 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 f27665b702..8c8187c130 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Channel.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Channel.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-2020 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 45f6553093..d5390fd6f2 100644 --- a/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt +++ b/reactive/kotlinx-coroutines-reactive/src/ContextInjector.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.reactive import kotlinx.coroutines.InternalCoroutinesApi @@ -12,4 +16,4 @@ public interface ContextInjector { * This API used as an indirection layer between `reactive` and `reactor` modules. */ public fun injectCoroutineContext(publisher: Publisher, coroutineContext: CoroutineContext): Publisher -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactive/src/Convert.kt b/reactive/kotlinx-coroutines-reactive/src/Convert.kt index f1ebd23a73..fb06ca3a3c 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Convert.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Convert.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-2020 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 40dfec03f5..4e0dca63de 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Migration.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Migration.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -33,4 +33,4 @@ public fun Flow.asPublisherDeprecated(): Publisher = asPublisher level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("asFlow().buffer(batchSize)", imports = ["kotlinx.coroutines.flow.*"]) ) -public fun Publisher.asFlow(batchSize: Int): Flow = asFlow().buffer(batchSize) \ No newline at end of file +public fun Publisher.asFlow(batchSize: Int): Flow = asFlow().buffer(batchSize) diff --git a/reactive/kotlinx-coroutines-reactive/src/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/Publish.kt index 704b7142b3..68c1702913 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Publish.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Publish.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-2020 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/build.gradle b/reactive/kotlinx-coroutines-reactor/build.gradle index c73716d494..a33d3e687a 100644 --- a/reactive/kotlinx-coroutines-reactor/build.gradle +++ b/reactive/kotlinx-coroutines-reactor/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ dependencies { @@ -20,4 +20,4 @@ compileTestKotlin { compileKotlin { kotlinOptions.jvmTarget = "1.8" -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactor/resources/META-INF/services/kotlinx.coroutines.reactive.ContextInjector b/reactive/kotlinx-coroutines-reactor/resources/META-INF/services/kotlinx.coroutines.reactive.ContextInjector index 0097ec3539..9838c12bd4 100644 --- a/reactive/kotlinx-coroutines-reactor/resources/META-INF/services/kotlinx.coroutines.reactive.ContextInjector +++ b/reactive/kotlinx-coroutines-reactor/resources/META-INF/services/kotlinx.coroutines.reactive.ContextInjector @@ -1 +1 @@ -kotlinx.coroutines.reactor.ReactorContextInjector \ No newline at end of file +kotlinx.coroutines.reactor.ReactorContextInjector diff --git a/reactive/kotlinx-coroutines-reactor/src/Convert.kt b/reactive/kotlinx-coroutines-reactor/src/Convert.kt index 3d9aa13e43..dc264f8d89 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Convert.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Convert.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor @@ -51,4 +51,4 @@ public fun Deferred.asMono(context: CoroutineContext): Mono = mono(co public fun ReceiveChannel.asFlux(context: CoroutineContext = EmptyCoroutineContext): Flux = flux(context) { for (t in this@asFlux) send(t) -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactor/src/Flux.kt b/reactive/kotlinx-coroutines-reactor/src/Flux.kt index b6cc1615b0..addc528c32 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Flux.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Flux.kt @@ -1,6 +1,6 @@ /* - * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 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 c80d2690ab..f0c24bb08d 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Migration.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Migration.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + @file:JvmName("FlowKt") package kotlinx.coroutines.reactor diff --git a/reactive/kotlinx-coroutines-reactor/src/Mono.kt b/reactive/kotlinx-coroutines-reactor/src/Mono.kt index 415932dd7d..503c891ea4 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Mono.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Mono.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-2020 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 19240c42ad..9f5eb23169 100644 --- a/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt +++ b/reactive/kotlinx-coroutines-reactor/src/ReactorContext.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.reactor import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt index 68309bbcdb..a9d140a9fd 100644 --- a/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt +++ b/reactive/kotlinx-coroutines-reactor/src/ReactorContextInjector.kt @@ -1,3 +1,7 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.reactor import kotlinx.coroutines.reactive.* @@ -19,4 +23,4 @@ internal class ReactorContextInjector : ContextInjector { else -> publisher } } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt b/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt index 5d47e0218c..d665c88d35 100644 --- a/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt +++ b/reactive/kotlinx-coroutines-reactor/src/ReactorFlow.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor @@ -25,4 +25,4 @@ private class FlowAsFlux(private val flow: Flow) : Flux() { val source = if (hasContext) flow.flowOn(subscriber.currentContext().asCoroutineContext()) else flow subscriber.onSubscribe(FlowSubscription(source, subscriber)) } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt index 78c0c5e1e6..833ceb2d6a 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Scheduler.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.reactor @@ -53,4 +53,4 @@ public class SchedulerCoroutineDispatcher( private fun Disposable.asDisposableHandle(): DisposableHandle = object : DisposableHandle { override fun dispose() = this@asDisposableHandle.dispose() - } \ No newline at end of file + } diff --git a/reactive/kotlinx-coroutines-rx2/build.gradle b/reactive/kotlinx-coroutines-rx2/build.gradle index 8fa85092b5..b583025ce3 100644 --- a/reactive/kotlinx-coroutines-rx2/build.gradle +++ b/reactive/kotlinx-coroutines-rx2/build.gradle @@ -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-2020 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 ce1040e911..d9435b6b9e 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxAwait.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-2020 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 a0c32f9f8a..f7596f27d0 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.rx2 @@ -22,4 +22,4 @@ internal fun handleUndeliverableException(cause: Throwable, context: CoroutineCo } catch (e: Throwable) { handleCoroutineException(context, cause) } -} \ No newline at end of file +} diff --git a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt index 0a19eda860..9f31b2aaa8 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxChannel.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-2020 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 ab96844c60..bc91fa53e0 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.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-2020 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 bd369cad55..a9d423a99b 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxConvert.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-2020 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 7924a3f15c..78d397c3b3 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") @@ -52,4 +52,4 @@ public fun CoroutineScope.rxFlowable( @BuilderInference block: suspend ProducerScope.() -> Unit ): Flowable = Flowable.fromPublisher(publishInternal(this, context, RX_HANDLER, block)) -private val RX_HANDLER: (Throwable, CoroutineContext) -> Unit = ::handleUndeliverableException \ No newline at end of file +private val RX_HANDLER: (Throwable, CoroutineContext) -> Unit = ::handleUndeliverableException diff --git a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt index 9fb5f650f4..bfbcb38d92 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.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-2020 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 b8de66df08..2f483879b8 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxObservable.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-2020 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 610a5bcd6d..3ddb67649e 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.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-2020 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 07088909b5..23040601df 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxSingle.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-2020 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/settings.gradle b/settings.gradle index 3c1dc0c558..5bce054f77 100644 --- a/settings.gradle +++ b/settings.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ rootProject.name = 'kotlinx.coroutines' diff --git a/site/build.gradle b/site/build.gradle index c69d9459a1..6b2c5b7916 100644 --- a/site/build.gradle +++ b/site/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ def buildDocsDir = "$buildDir/docs" diff --git a/site/docs/assets/js/api.js b/site/docs/assets/js/api.js index 9b1d034736..08f41fa087 100644 --- a/site/docs/assets/js/api.js +++ b/site/docs/assets/js/api.js @@ -1,19 +1,8 @@ /* - * Copyright 2016-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ + function addTag(rowElement, tag) { var tags = $(rowElement).find('.tags'); if (tags.length == 0) { diff --git a/stdlib-stubs/build.gradle b/stdlib-stubs/build.gradle index 4d7eee1e2a..b2ca0398d9 100644 --- a/stdlib-stubs/build.gradle +++ b/stdlib-stubs/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ compileKotlin { diff --git a/stdlib-stubs/src/Continuation.kt b/stdlib-stubs/src/Continuation.kt index d5834dacbb..662f9dae8e 100644 --- a/stdlib-stubs/src/Continuation.kt +++ b/stdlib-stubs/src/Continuation.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin.coroutines @@ -7,4 +7,4 @@ package kotlin.coroutines public interface Continuation { public val context: CoroutineContext public fun resumeWith(result: Result) -} \ No newline at end of file +} diff --git a/stdlib-stubs/src/ContinuationInterceptor.kt b/stdlib-stubs/src/ContinuationInterceptor.kt index 6fbfa70a90..47935e3b03 100644 --- a/stdlib-stubs/src/ContinuationInterceptor.kt +++ b/stdlib-stubs/src/ContinuationInterceptor.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-2020 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 e26315475b..ac216a0bec 100644 --- a/stdlib-stubs/src/CoroutineContext.kt +++ b/stdlib-stubs/src/CoroutineContext.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-2020 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 5fe48cb76e..6dc8d9c8f7 100644 --- a/stdlib-stubs/src/Result.kt +++ b/stdlib-stubs/src/Result.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlin 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 06779bf5a7..a08f44ad4c 100644 --- a/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt +++ b/ui/kotlinx-coroutines-android/android-unit-tests/src/EmptyCoroutineScopeImpl.kt @@ -1,8 +1,11 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + package kotlinx.coroutines.android -import kotlinx.coroutines.CoroutineScope -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.* +import kotlin.coroutines.* // Classes for testing service loader internal class EmptyCoroutineScopeImpl1 : CoroutineScope { @@ -18,4 +21,4 @@ internal class EmptyCoroutineScopeImpl2 : CoroutineScope { internal class EmptyCoroutineScopeImpl3 : CoroutineScope { override val coroutineContext: CoroutineContext get() = EmptyCoroutineContext -} \ No newline at end of file +} diff --git a/ui/kotlinx-coroutines-android/animation-app/app/build.gradle b/ui/kotlinx-coroutines-android/animation-app/app/build.gradle index 7fd9c8a98d..44f4a5f589 100644 --- a/ui/kotlinx-coroutines-android/animation-app/app/build.gradle +++ b/ui/kotlinx-coroutines-android/animation-app/app/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: 'com.android.application' 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 index 7625b1bf81..34d0dd14d5 100644 --- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/AndroidManifest.xml +++ b/ui/kotlinx-coroutines-android/animation-app/app/src/main/AndroidManifest.xml @@ -1,4 +1,8 @@ + + @@ -20,4 +24,4 @@ - \ No newline at end of file + 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 index ad11f2aa61..8e06e90179 100644 --- 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 @@ -1,6 +1,6 @@ + + - \ No newline at end of file + 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 index eca70cfe52..8bc717e4ad 100644 --- 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 @@ -1,5 +1,9 @@ + + - \ No newline at end of file + diff --git a/ui/kotlinx-coroutines-android/animation-app/build.gradle b/ui/kotlinx-coroutines-android/animation-app/build.gradle index d198b1ab77..d98ab8cfe7 100644 --- a/ui/kotlinx-coroutines-android/animation-app/build.gradle +++ b/ui/kotlinx-coroutines-android/animation-app/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ // Top-level build file where you can add configuration options common to all sub-projects/modules. diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle.properties b/ui/kotlinx-coroutines-android/animation-app/gradle.properties index c07db5d8f0..db0424ea0b 100644 --- a/ui/kotlinx-coroutines-android/animation-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/animation-app/gradle.properties @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # # Project-wide Gradle settings. diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle/wrapper/gradle-wrapper.properties b/ui/kotlinx-coroutines-android/animation-app/gradle/wrapper/gradle-wrapper.properties index ab5d60b4d9..dfd98a959a 100644 --- a/ui/kotlinx-coroutines-android/animation-app/gradle/wrapper/gradle-wrapper.properties +++ b/ui/kotlinx-coroutines-android/animation-app/gradle/wrapper/gradle-wrapper.properties @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # distributionBase=GRADLE_USER_HOME diff --git a/ui/kotlinx-coroutines-android/animation-app/settings.gradle b/ui/kotlinx-coroutines-android/animation-app/settings.gradle index e7b4def49c..0087705ce7 100644 --- a/ui/kotlinx-coroutines-android/animation-app/settings.gradle +++ b/ui/kotlinx-coroutines-android/animation-app/settings.gradle @@ -1 +1,5 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + include ':app' diff --git a/ui/kotlinx-coroutines-android/example-app/app/build.gradle b/ui/kotlinx-coroutines-android/example-app/app/build.gradle index f970baa6d6..3f013247d7 100644 --- a/ui/kotlinx-coroutines-android/example-app/app/build.gradle +++ b/ui/kotlinx-coroutines-android/example-app/app/build.gradle @@ -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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ apply plugin: 'com.android.application' diff --git a/ui/kotlinx-coroutines-android/example-app/app/src/main/AndroidManifest.xml b/ui/kotlinx-coroutines-android/example-app/app/src/main/AndroidManifest.xml index a04a27e0a3..b8b2a76c90 100644 --- a/ui/kotlinx-coroutines-android/example-app/app/src/main/AndroidManifest.xml +++ b/ui/kotlinx-coroutines-android/example-app/app/src/main/AndroidManifest.xml @@ -1,4 +1,8 @@ + + @@ -21,4 +25,4 @@ - \ No newline at end of file + diff --git a/ui/kotlinx-coroutines-android/example-app/app/src/main/res/layout/activity_main.xml b/ui/kotlinx-coroutines-android/example-app/app/src/main/res/layout/activity_main.xml index b98ce43711..0b72802215 100644 --- a/ui/kotlinx-coroutines-android/example-app/app/src/main/res/layout/activity_main.xml +++ b/ui/kotlinx-coroutines-android/example-app/app/src/main/res/layout/activity_main.xml @@ -1,6 +1,6 @@ Date: Fri, 21 Feb 2020 17:31:05 +0300 Subject: [PATCH 36/50] Make publication validator part of the project (#1820) Before, publication validator was just lying nearby, in these files, and built and run separately. Now, it is compiled alongside the main project (in the `test` gradle configuration), so its breakage will be detected during normal usage. Still, it is only run when a special gradle property, `DeployVersion`, is defined. --- build.gradle | 7 +- publication-validator/README.md | 12 +- publication-validator/build.gradle | 34 ++-- publication-validator/gradle.properties | 5 - .../gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - publication-validator/gradlew | 172 ------------------ publication-validator/gradlew.bat | 84 --------- publication-validator/settings.gradle | 8 - .../tools/NpmPublicationValidator.kt | 4 +- settings.gradle | 2 + 11 files changed, 33 insertions(+), 301 deletions(-) delete mode 100644 publication-validator/gradle.properties delete mode 100644 publication-validator/gradle/wrapper/gradle-wrapper.jar delete mode 100644 publication-validator/gradle/wrapper/gradle-wrapper.properties delete mode 100755 publication-validator/gradlew delete mode 100644 publication-validator/gradlew.bat delete mode 100644 publication-validator/settings.gradle diff --git a/build.gradle b/build.gradle index 67e1e27f71..b6d0483afe 100644 --- a/build.gradle +++ b/build.gradle @@ -8,8 +8,8 @@ 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'] -def internal = ['kotlinx.coroutines', 'site', 'benchmarks', 'js-stub', 'stdlib-stubs'] +def sourceless = ['kotlinx.coroutines', 'site', 'kotlinx-coroutines-bom', 'publication-validator'] +def internal = ['kotlinx.coroutines', 'site', 'benchmarks', 'js-stub', 'stdlib-stubs', 'publication-validator'] // Not published def unpublished = internal + ['example-frontend-js', 'android-unit-tests'] @@ -133,8 +133,7 @@ allprojects { apply plugin: "binary-compatibility-validator" apiValidation { - ignoredProjects += ["stdlib-stubs", "benchmarks", "site", - "kotlinx-coroutines-bom", "android-unit-tests", "js-stub"] + ignoredProjects += unpublished + ["kotlinx-coroutines-bom"] ignoredPackages += "kotlinx.coroutines.internal" } diff --git a/publication-validator/README.md b/publication-validator/README.md index 7437513afa..a60ff00e3c 100644 --- a/publication-validator/README.md +++ b/publication-validator/README.md @@ -1,9 +1,13 @@ # Publication validator -This is a supplementary subproject of kotlinx.coroutines to test its publication correctness. +This is a supplementary subproject of kotlinx.coroutines that provides a new +task, `testPublishing`, to test its publication correctness. -It is used as part of "Dependency validation" build chain on TeamCity: -* kotlinx.corotoutines are built with `publishToMavenLocal` -* kotlinx.coroutines are built with `npmPublish -PdryRun=true` to have a packed publication +The tests are the following: * `NpmPublicationValidator` tests that version of NPM artifact is correct and that it has neither source nor package dependencies on atomicfu * `MavenPublicationValidator` depends on the published artifacts and tests artifacts binary content and absence of atomicfu in the classpath + +To test publication, one needs to run gradle with `-PdryRun=true`, and the +task that actually does the testing is `publication-validator:test`. +`-PdryRun` affects `npmPublish` so that it only provides a packed publication +and does not in fact attempt to send the build for publication. diff --git a/publication-validator/build.gradle b/publication-validator/build.gradle index 993572f6b5..a22ccf46d2 100644 --- a/publication-validator/build.gradle +++ b/publication-validator/build.gradle @@ -2,16 +2,7 @@ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -plugins { - id 'org.jetbrains.kotlin.jvm' version '1.3.30' -} - -def deployVersion = properties['DeployVersion'] -ext.coroutines_version = deployVersion -println "Checking coroutines version $coroutines_version" - -group 'org.jetbrains.kotlinx' -version '1.0-SNAPSHOT' +apply from: rootProject.file("gradle/compile-jvm.gradle") repositories { mavenLocal() @@ -19,17 +10,28 @@ repositories { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" testCompile 'junit:junit:4.12' testCompile 'org.apache.commons:commons-compress:1.18' testCompile 'com.google.code.gson:gson:2.8.5' - testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" + testCompile project(':kotlinx-coroutines-core') + testCompile project(':kotlinx-coroutines-android') } -compileKotlin { - kotlinOptions.jvmTarget = "1.8" -} compileTestKotlin { kotlinOptions.jvmTarget = "1.8" } + +def dryRunNpm = properties['dryRun'] + +test { + onlyIf { dryRunNpm == "true" } // so that we don't accidentally publish anything, especially before the test + doFirst { println "Verifying publishing version $version" } // all modules share the same version + environment "projectRoot", project.rootDir + environment "deployVersion", version + if (dryRunNpm == "true") { // `onlyIf` only affects execution of the task, not the dependency subtree + dependsOn(project(':').getTasksByName("publishNpm", true) + + project(':').getTasksByName("publishToMavenLocal", true)) + dependsOn.remove(project(':').getTasksByName("dokka", true)) + } +} diff --git a/publication-validator/gradle.properties b/publication-validator/gradle.properties deleted file mode 100644 index aefd041a54..0000000000 --- a/publication-validator/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -# -# Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -kotlin.code.style=official diff --git a/publication-validator/gradle/wrapper/gradle-wrapper.jar b/publication-validator/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 94336fcae912db8a11d55634156fa011f4686124..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56177 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 i;x|p)^~-yfPOPa3(|vBayXKz \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/publication-validator/gradlew.bat b/publication-validator/gradlew.bat deleted file mode 100644 index f9553162f1..0000000000 --- a/publication-validator/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/publication-validator/settings.gradle b/publication-validator/settings.gradle deleted file mode 100644 index 552030630d..0000000000 --- a/publication-validator/settings.gradle +++ /dev/null @@ -1,8 +0,0 @@ -pluginManagement { - repositories { - mavenLocal() - mavenCentral() - maven { url 'https://plugins.gradle.org/m2/' } - } -} -rootProject.name = 'kotlinx-coroutines-validator' diff --git a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt index 052d745bb8..52479d56ef 100644 --- a/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt +++ b/publication-validator/src/test/kotlin/kotlinx/coroutines/tools/NpmPublicationValidator.kt @@ -12,8 +12,8 @@ import java.util.zip.* import org.junit.Assert.* class NpmPublicationValidator { - private val VERSION = System.getenv("DeployVersion") - private val BUILD_DIR = System.getenv("teamcity.build.checkoutDir") + private val VERSION = System.getenv("deployVersion")!! + private val BUILD_DIR = System.getenv("projectRoot")!! private val NPM_ARTIFACT = "$BUILD_DIR/kotlinx-coroutines-core/build/npm/kotlinx-coroutines-core-$VERSION.tgz" @Test diff --git a/settings.gradle b/settings.gradle index 5bce054f77..15d377d3f9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -40,3 +40,5 @@ module('ui/kotlinx-coroutines-swing') module('js/js-stub') module('js/example-frontend-js') + +module('publication-validator') From 21bb6fb201b12e26d6763519b46881f89914d6fc Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 26 Feb 2020 17:14:10 +0300 Subject: [PATCH 37/50] Temporary workaround bug in K/N 1.3.70 codegen (KT-37061) --- .../common/src/flow/internal/FlowCoroutine.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt index 36d7a3a20d..0ce0c339a2 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt @@ -48,8 +48,7 @@ internal suspend fun flowScope(@BuilderInference block: suspend CoroutineSco */ internal fun scopedFlow(@BuilderInference block: suspend CoroutineScope.(FlowCollector) -> Unit): Flow = flow { - val collector = this - flowScope { block(collector) } + flowScope { block(this@flow) } } internal fun CoroutineScope.flowProduce( From d4fabbfa287d77294b69d80a2a29654ad3960e0a Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Tue, 3 Mar 2020 10:26:31 +0300 Subject: [PATCH 38/50] Fixed regularized 'when' inference to build train See https://youtrack.jetbrains.com/issue/KT-36776 --- .../common/src/channels/ConflatedBroadcastChannel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt index 5813902dfc..4990c933ec 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt @@ -91,7 +91,7 @@ public class ConflatedBroadcastChannel() : BroadcastChannel { */ public val valueOrNull: E? get() = when (val state = _state.value) { is Closed -> null - is State<*> -> UNDEFINED.unbox(state.value) + is State<*> -> UNDEFINED.unbox(state.value) else -> error("Invalid state $state") } From ca1093cf50fa68c053fcdbd957da2b60c1ef850a Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 3 Mar 2020 11:56:55 +0300 Subject: [PATCH 39/50] Restore AsyncJvmTest --- .../jvm/test/AsyncJvmTest.kt | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt index 9c37b7bf50..026752086c 100644 --- a/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt +++ b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt @@ -6,16 +6,41 @@ package kotlinx.coroutines import kotlin.test.* + class AsyncJvmTest : TestBase() { // This must be a common test but it fails on JS because of KT-21961 @Test fun testAsyncWithFinally() = runTest { - launch(Dispatchers.Default) { - - } - - launch(Dispatchers.IO) { + expect(1) + @Suppress("UNREACHABLE_CODE") + val d = async { + expect(3) + try { + yield() // to main, will cancel + } finally { + expect(6) // will go there on await + return@async "Fail" // result will not override cancellation + } + expectUnreached() + "Fail2" + } + expect(2) + yield() // to async + expect(4) + check(d.isActive && !d.isCompleted && !d.isCancelled) + d.cancel() + check(!d.isActive && !d.isCompleted && d.isCancelled) + check(!d.isActive && !d.isCompleted && d.isCancelled) + expect(5) + try { + d.await() // awaits + expectUnreached() // does not complete normally + } catch (e: Throwable) { + expect(7) + check(e is CancellationException) } + check(!d.isActive && d.isCompleted && d.isCancelled) + finish(8) } } From 4a53d235892c1b7ae38ee5472810c9ff5ef6156d Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 3 Mar 2020 15:33:40 +0300 Subject: [PATCH 40/50] Atomically start coroutines in intermediate Flow operators in order to ensure proper termination, including finally blocks and onCompletion operators (#1829) Fixes #1825 --- .../api/kotlinx-coroutines-core.api | 4 +-- .../common/src/channels/Produce.kt | 3 +- .../common/src/flow/internal/ChannelFlow.kt | 10 ++++++- .../common/src/flow/internal/FlowCoroutine.kt | 2 +- .../flow/channels/ChannelBuildersFlowTest.kt | 11 +++++++ .../test/flow/operators/FlatMapMergeTest.kt | 29 +++++++++++++++++++ .../common/test/flow/operators/FlowOnTest.kt | 27 +++++++++++++++++ 7 files changed, 81 insertions(+), 5 deletions(-) diff --git a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api index 04a4e99c9a..76a0bed462 100644 --- a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api +++ b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api @@ -746,10 +746,10 @@ public final class kotlinx/coroutines/channels/ConflatedBroadcastChannel : kotli public final class kotlinx/coroutines/channels/ProduceKt { public static final fun awaitClose (Lkotlinx/coroutines/channels/ProducerScope;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun awaitClose$default (Lkotlinx/coroutines/channels/ProducerScope;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun produce (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/channels/ReceiveChannel; public static final fun produce (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/channels/ReceiveChannel; - public static synthetic fun produce$default (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; + public static final fun produce (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/channels/ReceiveChannel; public static synthetic fun produce$default (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; + public static synthetic fun produce$default (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;ILkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveChannel; } public abstract interface class kotlinx/coroutines/channels/ProducerScope : kotlinx/coroutines/CoroutineScope, kotlinx/coroutines/channels/SendChannel { diff --git a/kotlinx-coroutines-core/common/src/channels/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt index 26bd544811..24fd399bb7 100644 --- a/kotlinx-coroutines-core/common/src/channels/Produce.kt +++ b/kotlinx-coroutines-core/common/src/channels/Produce.kt @@ -115,6 +115,7 @@ public fun CoroutineScope.produce( public fun CoroutineScope.produce( context: CoroutineContext = EmptyCoroutineContext, capacity: Int = 0, + start: CoroutineStart = CoroutineStart.DEFAULT, onCompletion: CompletionHandler? = null, @BuilderInference block: suspend ProducerScope.() -> Unit ): ReceiveChannel { @@ -122,7 +123,7 @@ public fun CoroutineScope.produce( val newContext = newCoroutineContext(context) val coroutine = ProducerCoroutine(newContext, channel) if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion) - coroutine.start(CoroutineStart.DEFAULT, coroutine, block) + coroutine.start(start, coroutine, block) return coroutine } diff --git a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt index 2b62be44f4..8a18bff30e 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/ChannelFlow.kt @@ -68,8 +68,16 @@ public abstract class ChannelFlow( open fun broadcastImpl(scope: CoroutineScope, start: CoroutineStart): BroadcastChannel = scope.broadcast(context, produceCapacity, start, block = collectToFun) + /** + * Here we use ATOMIC start for a reason (#1825). + * NB: [produceImpl] is used for [flowOn]. + * For non-atomic start it is possible to observe the situation, + * where the pipeline after the [flowOn] call successfully executes (mostly, its `onCompletion`) + * handlers, while the pipeline before does not, because it was cancelled during its dispatch. + * Thus `onCompletion` and `finally` blocks won't be executed and it may lead to a different kinds of memory leaks. + */ open fun produceImpl(scope: CoroutineScope): ReceiveChannel = - scope.produce(context, produceCapacity, block = collectToFun) + scope.produce(context, produceCapacity, start = CoroutineStart.ATOMIC, block = collectToFun) override suspend fun collect(collector: FlowCollector) = coroutineScope { diff --git a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt index 0ce0c339a2..acc6ca04ec 100644 --- a/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/flow/internal/FlowCoroutine.kt @@ -59,7 +59,7 @@ internal fun CoroutineScope.flowProduce( val channel = Channel(capacity) val newContext = newCoroutineContext(context) val coroutine = FlowProduceCoroutine(newContext, channel) - coroutine.start(CoroutineStart.DEFAULT, coroutine, block) + coroutine.start(CoroutineStart.ATOMIC, coroutine, block) return coroutine } diff --git a/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt b/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt index 8dd6e3c8a7..f93d039933 100644 --- a/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/channels/ChannelBuildersFlowTest.kt @@ -265,4 +265,15 @@ class ChannelBuildersFlowTest : TestBase() { fail() } } + + @Test + fun testProduceInAtomicity() = runTest { + val flow = flowOf(1).onCompletion { expect(2) } + val scope = CoroutineScope(wrapperDispatcher()) + flow.produceIn(scope) + expect(1) + scope.cancel() + scope.coroutineContext[Job]?.join() + finish(3) + } } diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt index 511a003a8e..684923c861 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeTest.kt @@ -37,6 +37,35 @@ class FlatMapMergeTest : FlatMapMergeBaseTest() { finish(3) } + @Test + fun testAtomicStart() = runTest { + try { + coroutineScope { + val job = coroutineContext[Job]!! + val flow = flow { + expect(3) + emit(1) + } + .onCompletion { expect(5) } + .flatMapMerge { + expect(4) + flowOf(it).onCompletion { expectUnreached() } } + .onCompletion { expect(6) } + + launch { + expect(1) + flow.collect() + } + launch { + expect(2) + job.cancel() + } + } + } catch (e: CancellationException) { + finish(7) + } + } + @Test fun testCancellationExceptionDownstream() = runTest { val flow = flow { diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt index 34c0476ef6..f8350ff584 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/FlowOnTest.kt @@ -276,6 +276,33 @@ class FlowOnTest : TestBase() { assertEquals(listOf(1, 2), result) } + @Test + fun testAtomicStart() = runTest { + try { + coroutineScope { + val job = coroutineContext[Job]!! + val flow = flow { + expect(3) + emit(1) + } + .onCompletion { expect(4) } + .flowOn(wrapperDispatcher()) + .onCompletion { expect(5) } + + launch { + expect(1) + flow.collect() + } + launch { + expect(2) + job.cancel() + } + } + } catch (e: CancellationException) { + finish(6) + } + } + @Test fun testException() = runTest { val flow = flow { From cf473d2a68b4c46bc1ae009f3c78296eb58561ed Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 4 Mar 2020 12:33:46 +0300 Subject: [PATCH 41/50] Kotlin 1.3.70 (#1837) * atomicfu version 0.14.2 --- README.md | 8 ++++---- gradle.properties | 4 ++-- .../animation-app/gradle.properties | 2 +- .../example-app/gradle.properties | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 42b2b3a181..45e8489704 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.3.3) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.3.3) Library support for Kotlin coroutines with [multiplatform](#multiplatform) support. -This is a companion version for Kotlin `1.3.61` release. +This is a companion version for Kotlin `1.3.70` release. ```kotlin suspend fun main() = coroutineScope { @@ -90,7 +90,7 @@ And make sure that you use the latest Kotlin version: ```xml - 1.3.61 + 1.3.70 ``` @@ -108,7 +108,7 @@ And make sure that you use the latest Kotlin version: ```groovy buildscript { - ext.kotlin_version = '1.3.61' + ext.kotlin_version = '1.3.70' } ``` @@ -134,7 +134,7 @@ And make sure that you use the latest Kotlin version: ```groovy plugins { - kotlin("jvm") version "1.3.61" + kotlin("jvm") version "1.3.70" } ``` diff --git a/gradle.properties b/gradle.properties index 67ebc1cf9a..8b013cc5c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,11 +5,11 @@ # Kotlin version=1.3.3-SNAPSHOT group=org.jetbrains.kotlinx -kotlin_version=1.3.61 +kotlin_version=1.3.70 # Dependencies junit_version=4.12 -atomicfu_version=0.14.1 +atomicfu_version=0.14.2 knit_version=0.1.2 html_version=0.6.8 lincheck_version=2.5.3 diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle.properties b/ui/kotlinx-coroutines-android/animation-app/gradle.properties index db0424ea0b..07c62f8dfd 100644 --- a/ui/kotlinx-coroutines-android/animation-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/animation-app/gradle.properties @@ -20,7 +20,7 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -kotlin_version=1.3.61 +kotlin_version=1.3.70 coroutines_version=1.3.3 android.useAndroidX=true diff --git a/ui/kotlinx-coroutines-android/example-app/gradle.properties b/ui/kotlinx-coroutines-android/example-app/gradle.properties index db0424ea0b..07c62f8dfd 100644 --- a/ui/kotlinx-coroutines-android/example-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/example-app/gradle.properties @@ -20,7 +20,7 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -kotlin_version=1.3.61 +kotlin_version=1.3.70 coroutines_version=1.3.3 android.useAndroidX=true From c684d04de9aceb4e15afae7c736cbb3e79b597d4 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 4 Mar 2020 13:02:25 +0300 Subject: [PATCH 42/50] Knit version 0.1.3 (#1838) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8b013cc5c4..c199d9391d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ kotlin_version=1.3.70 # Dependencies junit_version=4.12 atomicfu_version=0.14.2 -knit_version=0.1.2 +knit_version=0.1.3 html_version=0.6.8 lincheck_version=2.5.3 dokka_version=0.9.16-rdev-2-mpp-hacks From 6862afcb410a2dfcca344a052e618abaaeb63859 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 4 Mar 2020 16:17:31 +0300 Subject: [PATCH 43/50] Simpler and faster lock-free linked list (#1565) Lock-free list implementation is considerably simplified, taking into account a limited number of operations that it needs to support. * prev pointers in the list are not marked for removal, since we don't need to support linearizable backwards iteration. * helpDelete method is completely removed. All "delete-helping" is performed only by correctPrev method. * correctPrev method bails out when the node it works on is removed to reduce contention during concurrent removals. * Special open methods "isRemoved" and "nextIfRemoved" are introduced and are overridden in list head class (which is never removed). This ensures that on long list "removeFist" operation (touching head) does not interfere with "addLast" (touch tail). There is still sharing of cache-lines in this case, but no helping between them. All in all, this improvement reduces the size of implementation code and makes it considerably faster. Operations on LinkedListChannel are now much faster (see timings of ChannelSendReceiveStressTest). --- .../common/src/channels/ConflatedChannel.kt | 4 +- .../jvm/src/internal/LockFreeLinkedList.kt | 328 ++++++++---------- .../channels/ChannelSendReceiveStressTest.kt | 15 +- 3 files changed, 150 insertions(+), 197 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt index ea7c1e5567..399019c3ee 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt @@ -7,12 +7,12 @@ package kotlinx.coroutines.channels import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.selects.* -import kotlin.native.concurrent.SharedImmutable +import kotlin.native.concurrent.* /** * Channel that buffers at most one element and conflates all subsequent `send` and `offer` invocations, * so that the receiver always gets the most recently sent element. - * Back-to-send sent elements are _conflated_ -- only the the most recently sent element is received, + * Back-to-send sent elements are _conflated_ -- only the most recently sent element is received, * while previously sent elements **are lost**. * Sender to this channel never suspends and [offer] always returns `true`. * diff --git a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt index 19cb159b6b..26fd169da3 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt @@ -40,14 +40,18 @@ public actual typealias PrepareOp = LockFreeLinkedListNode.PrepareOp * Doubly-linked concurrent list node with remove support. * Based on paper * ["Lock-Free and Practical Doubly Linked List-Based Deques Using Single-Word Compare-and-Swap"](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.140.4693&rep=rep1&type=pdf) - * by Sundell and Tsigas. + * by Sundell and Tsigas with considerable changes. + * + * The core idea of the algorithm is to maintain a doubly-linked list with an ever-present sentinel node (it is + * never removed) that serves both as a list head and tail and to linearize all operations (both insert and remove) on + * the update of the next pointer. Removed nodes have their next pointer marked with [Removed] class. * * Important notes: - * * The instance of this class serves both as list head/tail sentinel and as the list item. - * Sentinel node should be never removed. * * There are no operations to add items to left side of the list, only to the end (right side), because we cannot * efficiently linearize them with atomic multi-step head-removal operations. In short, * support for [describeRemoveFirst] operation precludes ability to add items at the beginning. + * * Previous pointers are not marked for removal. We don't support linearizable backwards traversal. + * * Remove-helping logic is simplified and consolidated in [correctPrev] method. * * @suppress **This is unstable API and it is subject to change.** */ @@ -55,7 +59,7 @@ public actual typealias PrepareOp = LockFreeLinkedListNode.PrepareOp @InternalCoroutinesApi public actual open class LockFreeLinkedListNode { private val _next = atomic(this) // Node | Removed | OpDescriptor - private val _prev = atomic(this) // Node | Removed + private val _prev = atomic(this) // Node to the left (cannot be marked as removed) private val _removedRef = atomic(null) // lazily cached removed ref to this private fun removed(): Removed = @@ -83,7 +87,7 @@ public actual open class LockFreeLinkedListNode { override fun prepare(affected: Node): Any? = if (condition()) null else CONDITION_FALSE } - public actual val isRemoved: Boolean get() = next is Removed + public actual open val isRemoved: Boolean get() = next is Removed // LINEARIZABLE. Returns Node | Removed public val next: Any get() { @@ -96,19 +100,19 @@ public actual open class LockFreeLinkedListNode { // LINEARIZABLE. Returns next non-removed Node public actual val nextNode: Node get() = next.unwrap() - // LINEARIZABLE. Returns Node | Removed - public val prev: Any get() { - _prev.loop { prev -> - if (prev is Removed) return prev - prev as Node // otherwise, it can be only node - if (prev.next === this) return prev - correctPrev(prev, null) - } + // LINEARIZABLE WHEN THIS NODE IS NOT REMOVED: + // Returns prev non-removed Node, makes sure prev is correct (prev.next === this) + // NOTE: if this node is removed, then returns non-removed previous node without applying + // prev.next correction, which does not provide linearizable backwards iteration, but can be used to + // resume forward iteration when current node was removed. + public actual val prevNode: Node + get() = correctPrev(null) ?: findPrevNonRemoved(_prev.value) + + private tailrec fun findPrevNonRemoved(current: Node): Node { + if (!current.isRemoved) return current + return findPrevNonRemoved(current._prev.value) } - // LINEARIZABLE. Returns prev non-removed Node - public actual val prevNode: Node get() = prev.unwrap() - // ------ addOneIfEmpty ------ public actual fun addOneIfEmpty(node: Node): Boolean { @@ -132,8 +136,7 @@ public actual open class LockFreeLinkedListNode { */ public actual fun addLast(node: Node) { while (true) { // lock-free loop on prev.next - val prev = prev as Node // sentinel node is never removed, so prev is always defined - if (prev.addNext(node, this)) return + if (prevNode.addNext(node, this)) return } } @@ -145,7 +148,7 @@ public actual open class LockFreeLinkedListNode { public actual inline fun addLastIf(node: Node, crossinline condition: () -> Boolean): Boolean { val condAdd = makeCondAddOp(node, condition) while (true) { // lock-free loop on prev.next - val prev = prev as Node // sentinel node is never removed, so prev is always defined + val prev = prevNode // sentinel node is never removed, so prev is always defined when (prev.tryCondAddNext(node, this, condAdd)) { SUCCESS -> return true FAILURE -> return false @@ -155,7 +158,7 @@ public actual open class LockFreeLinkedListNode { public actual inline fun addLastIfPrev(node: Node, predicate: (Node) -> Boolean): Boolean { while (true) { // lock-free loop on prev.next - val prev = prev as Node // sentinel node is never removed, so prev is always defined + val prev = prevNode // sentinel node is never removed, so prev is always defined if (!predicate(prev)) return false if (prev.addNext(node, this)) return true } @@ -168,7 +171,7 @@ public actual open class LockFreeLinkedListNode { ): Boolean { val condAdd = makeCondAddOp(node, condition) while (true) { // lock-free loop on prev.next - val prev = prev as Node // sentinel node is never removed, so prev is always defined + val prev = prevNode // sentinel node is never removed, so prev is always defined if (!predicate(prev)) return false when (prev.tryCondAddNext(node, this, condAdd)) { SUCCESS -> return true @@ -233,55 +236,71 @@ public actual open class LockFreeLinkedListNode { * In particular, invoking [nextNode].[prevNode] might still return this node even though it is "already removed". * Invoke [helpRemove] to make sure that remove was completed. */ - public actual open fun remove(): Boolean { + public actual open fun remove(): Boolean = + removeOrNext() == null + + // returns null if removed successfully or next node if this node is already removed + @PublishedApi + internal fun removeOrNext(): Node? { while (true) { // lock-free loop on next val next = this.next - if (next is Removed) return false // was already removed -- don't try to help (original thread will take care) - if (next === this) return false // was not even added + if (next is Removed) return next.ref // was already removed -- don't try to help (original thread will take care) + if (next === this) return next // was not even added val removed = (next as Node).removed() if (_next.compareAndSet(next, removed)) { // was removed successfully (linearized remove) -- fixup the list - finishRemove(next) - return true + next.correctPrev(null) + return null } } } + // Helps with removal of this node public actual fun helpRemove() { - val removed = this.next as? Removed ?: error("Must be invoked on a removed node") - finishRemove(removed.ref) + // Note: this node must be already removed + (next as Removed).ref.correctPrev(null) } - public actual fun removeFirstOrNull(): Node? { - while (true) { // try to linearize - val first = next as Node - if (first === this) return null - if (first.remove()) return first - first.helpDelete() // must help delete, or loose lock-freedom + // Helps with removal of nodes that are previous to this + @PublishedApi + internal fun helpRemovePrev() { + // We need to call correctPrev on a non-removed node to ensure progress, since correctPrev bails out when + // called on a removed node. There's always at least one non-removed node (list head). + var node = this + while (true) { + val next = node.next + if (next !is Removed) break + node = next.ref } + // Found a non-removed node + node.correctPrev(null) } - public fun describeRemoveFirst(): RemoveFirstDesc = RemoveFirstDesc(this) - - public inline fun removeFirstIfIsInstanceOf(): T? { + public actual fun removeFirstOrNull(): Node? { while (true) { // try to linearize val first = next as Node if (first === this) return null - if (first !is T) return null if (first.remove()) return first - first.helpDelete() // must help delete, or loose lock-freedom + first.helpRemove() // must help remove to ensure lock-freedom } } + public fun describeRemoveFirst(): RemoveFirstDesc = RemoveFirstDesc(this) + // just peek at item when predicate is true public actual inline fun removeFirstIfIsInstanceOfOrPeekIf(predicate: (T) -> Boolean): T? { - while (true) { // try to linearize - val first = next as Node - if (first === this) return null + while (true) { + val first = this.next as Node + if (first === this) return null // got list head -- nothing to remove if (first !is T) return null - if (predicate(first)) return first // just peek when predicate is true - if (first.remove()) return first - first.helpDelete() // must help delete, or loose lock-freedom + if (predicate(first)) { + // check for removal of the current node to make sure "peek" operation is linearizable + if (!first.isRemoved) return first + } + val next = first.removeOrNext() + if (next === null) return first // removed successfully -- return it + // help and start from the beginning + next.helpRemovePrev() } } @@ -296,25 +315,9 @@ public actual open class LockFreeLinkedListNode { assert { node._next.value === node && node._prev.value === node } } - // Returns null when atomic op got into deadlock trying to help operation that started later - final override fun takeAffectedNode(op: OpDescriptor): Node? { - while (true) { - val prev = queue._prev.value as Node // this sentinel node is never removed - val next = prev._next.value - if (next === queue) return prev // all is good -> linked properly - if (next === op) return prev // all is good -> our operation descriptor is already there - if (next is OpDescriptor) { // some other operation descriptor -> help & retry - if (op.isEarlierThan(next)) - return null // RETRY_ATOMIC - next.perform(prev) - continue - } - // linked improperly -- help insert - val affected = queue.correctPrev(prev, op) - // we can find node which this operation is already affecting while trying to correct prev - if (affected != null) return affected - } - } + // Returns null when atomic op got into deadlock trying to help operation that started later (RETRY_ATOMIC) + final override fun takeAffectedNode(op: OpDescriptor): Node? = + queue.correctPrev(op) // queue head is never removed, so null result can only mean RETRY_ATOMIC private val _affectedNode = atomic(null) final override val affectedNode: Node? get() = _affectedNode.value @@ -368,11 +371,11 @@ public actual open class LockFreeLinkedListNode { // check node predicates here, must signal failure if affect is not of type T protected override fun failure(affected: Node): Any? = - if (affected === queue) LIST_EMPTY else null + if (affected === queue) LIST_EMPTY else null final override fun retry(affected: Node, next: Any): Boolean { if (next !is Removed) return false - affected.helpDelete() // must help delete, or loose lock-freedom + next.ref.helpRemovePrev() // must help delete to ensure lock-freedom return true } @@ -385,7 +388,12 @@ public actual open class LockFreeLinkedListNode { } final override fun updatedNext(affected: Node, next: Node): Any = next.removed() - final override fun finishOnSuccess(affected: Node, next: Node) = affected.finishRemove(next) + + final override fun finishOnSuccess(affected: Node, next: Node) { + // Complete removal operation here. It bails out if next node is also removed and it becomes + // responsibility of the next's removes to call correctPrev which would help fix all the links. + next.correctPrev(null) + } } // This is Harris's RDCSS (Restricted Double-Compare Single Swap) operation @@ -404,9 +412,12 @@ public actual open class LockFreeLinkedListNode { val decision = desc.onPrepare(this) if (decision === REMOVE_PREPARED) { // remove element on failure -- do not mark as decided, will try another one + val next = this.next val removed = next.removed() if (affected._next.compareAndSet(this, removed)) { - affected.helpDelete() + // Complete removal operation here. It bails out if next node is also removed and it becomes + // responsibility of the next's removes to call correctPrev which would help fix all the links. + next.correctPrev(null) } return REMOVE_PREPARED } @@ -519,139 +530,68 @@ public actual open class LockFreeLinkedListNode { */ private fun finishAdd(next: Node) { next._prev.loop { nextPrev -> - if (nextPrev is Removed || this.next !== next) return // next was removed, remover fixes up links - if (next._prev.compareAndSet(nextPrev, this)) { - if (this.next is Removed) { - // already removed - next.correctPrev(nextPrev as Node, null) - } - return - } + if (this.next !== next) return // this or next was removed or another node added, remover/adder fixes up links + if (next._prev.compareAndSet(nextPrev, this)) return } } - private fun finishRemove(next: Node) { - helpDelete() - next.correctPrev(_prev.value.unwrap(), null) - } - - private fun markPrev(): Node { - _prev.loop { prev -> - if (prev is Removed) return prev.ref - // See detailed comment in findHead on why `prev === this` is a special case for which we know that - // the prev should have being pointing to the head of list but finishAdd that was supposed - // to do that is not complete yet. - val removedPrev = (if (prev === this) findHead() else (prev as Node)).removed() - if (_prev.compareAndSet(prev, removedPrev)) return prev - } - } + protected open fun nextIfRemoved(): Node? = (next as? Removed)?.ref /** - * Finds the head of the list (implementing [LockFreeLinkedListHead]) by following [next] pointers. + * Returns the corrected value of the previous node while also correcting the `prev` pointer + * (so that `this.prev.next === this`) and helps complete node removals to the left ot this node. * - * The code in [kotlinx.coroutines.JobSupport] performs upgrade of a single node to a list. - * It uses [addOneIfEmpty] to add the list head to "empty list of a single node" once. - * During upgrade a transient state of the list looks like this: + * It returns `null` in two special cases: * - * ``` - * +-----------------+ - * | | - * node V head | - * +---+---+ +---+---+ | - * +-> | P | N | --> | P | N |-+ - * | +---+---+ +---+---+ - * | | ^ | - * +---- + +---------+ - * ``` - * - * The [prev] pointer in `node` still points to itself when [finishAdd] (invoked inside [addOneIfEmpty]) - * has not completed yet. If this state is observed, then we know that [prev] should have been pointing - * to the list head. This function is looking up the head by following consistent chain of [next] pointers. + * * When this node is removed. In this case there is no need to waste time on corrections, because + * remover of this node will ultimately call [correctPrev] on the next node and that will fix all + * the links from this node, too. + * * When [op] descriptor is not `null` and and operation descriptor that is [OpDescriptor.isEarlierThan] + * that current [op] is found while traversing the list. This `null` result will be translated + * by callers to [RETRY_ATOMIC]. */ - private fun findHead(): Node { - var cur = this - while (true) { - if (cur is LockFreeLinkedListHead) return cur - cur = cur.nextNode - assert { cur !== this } // "Cannot loop to this while looking for list head" - } - } - - // fixes next links to the left of this node - @PublishedApi - internal fun helpDelete() { - var last: Node? = null // will set to the node left of prev when found - var prev: Node = markPrev() - var next: Node = (this._next.value as Removed).ref - while (true) { - // move to the right until first non-removed node - val nextNext = next.next - if (nextNext is Removed) { - next.markPrev() - next = nextNext.ref - continue - } - // move the the left until first non-removed node - val prevNext = prev.next - if (prevNext is Removed) { - if (last != null) { - prev.markPrev() - last._next.compareAndSet(prev, prevNext.ref) - prev = last - last = null - } else { - prev = prev._prev.value.unwrap() - } - continue - } - if (prevNext !== this) { - // skipped over some removed nodes to the left -- setup to fixup the next links - last = prev - prev = prevNext as Node - if (prev === next) return // already done!!! - continue - } - // Now prev & next are Ok - if (prev._next.compareAndSet(this, next)) return // success! - } - } - - // fixes prev links from this node - // returns affected node by this operation when this op is in progress (and nothing can be corrected) - // returns null otherwise (prev was corrected) - private fun correctPrev(_prev: Node, op: OpDescriptor?): Node? { - var prev: Node = _prev + private tailrec fun correctPrev(op: OpDescriptor?): Node? { + val oldPrev = _prev.value + var prev: Node = oldPrev var last: Node? = null // will be set so that last.next === prev - while (true) { - // move the the left until first non-removed node - val prevNext = prev._next.value - if (prevNext === op) return prev // part of the same op -- don't recurse, didn't correct prev - if (prevNext is OpDescriptor) { // help & retry - prevNext.perform(prev) - continue - } - if (prevNext is Removed) { - if (last !== null) { - prev.markPrev() - last._next.compareAndSet(prev, prevNext.ref) - prev = last - last = null - } else { - prev = prev._prev.value.unwrap() + while (true) { // move the the left until first non-removed node + val prevNext: Any = prev._next.value + when { + // fast path to find quickly find prev node when everything is properly linked + prevNext === this -> { + if (oldPrev === prev) return prev // nothing to update -- all is fine, prev found + // otherwise need to update prev + if (!this._prev.compareAndSet(oldPrev, prev)) { + // Note: retry from scratch on failure to update prev + return correctPrev(op) + } + return prev // return a correct prev + } + // slow path when we need to help remove operations + this.isRemoved -> return null // nothing to do, this node was removed, bail out asap to save time + prevNext === op -> return prev // part of the same op -- don't recurse, didn't correct prev + prevNext is OpDescriptor -> { // help & retry + if (op != null && op.isEarlierThan(prevNext)) + return null // RETRY_ATOMIC + prevNext.perform(prev) + return correctPrev(op) // retry from scratch + } + prevNext is Removed -> { + if (last !== null) { + // newly added (prev) node is already removed, correct last.next around it + if (!last._next.compareAndSet(prev, prevNext.ref)) { + return correctPrev(op) // retry from scratch on failure to update next + } + prev = last + last = null + } else { + prev = prev._prev.value + } + } + else -> { // prevNext is a regular node, but not this -- help delete + last = prev + prev = prevNext as Node } - continue - } - val oldPrev = this._prev.value - if (oldPrev is Removed) return null // this node was removed, too -- its remover will take care - if (prevNext !== this) { - // need to fixup next - last = prev - prev = prevNext as Node - continue - } - if (oldPrev === prev) return null // it is already linked as needed - if (this._prev.compareAndSet(oldPrev, prev)) { - if (prev._prev.value !is Removed) return null // finish only if prev was not concurrently removed } } } @@ -691,7 +631,11 @@ public actual open class LockFreeLinkedListHead : LockFreeLinkedListNode() { } // just a defensive programming -- makes sure that list head sentinel is never removed - public actual final override fun remove(): Boolean = throw UnsupportedOperationException() + public actual final override fun remove(): Boolean = error("head cannot be removed") + + // optimization: because head is never removed, we don't have to read _next.value to check these: + override val isRemoved: Boolean get() = false + override fun nextIfRemoved(): Node? = null internal fun validate() { var prev: Node = this diff --git a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt index 5fc87abfd6..00c5a6090f 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt @@ -1,11 +1,12 @@ /* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.channels import kotlinx.coroutines.* import kotlinx.coroutines.selects.* +import org.junit.* import org.junit.Test import org.junit.runner.* import org.junit.runners.* @@ -43,12 +44,20 @@ class ChannelSendReceiveStressTest( private val receivedTotal = AtomicInteger() private val receivedBy = IntArray(nReceivers) + private val pool = + newFixedThreadPoolContext(nSenders + nReceivers, "ChannelSendReceiveStressTest") + + @After + fun tearDown() { + pool.close() + } + @Test fun testSendReceiveStress() = runBlocking { println("--- ChannelSendReceiveStressTest $kind with nSenders=$nSenders, nReceivers=$nReceivers") val receivers = List(nReceivers) { receiverIndex -> // different event receivers use different code - launch(Dispatchers.Default + CoroutineName("receiver$receiverIndex")) { + launch(pool + CoroutineName("receiver$receiverIndex")) { when (receiverIndex % 5) { 0 -> doReceive(receiverIndex) 1 -> doReceiveOrNull(receiverIndex) @@ -60,7 +69,7 @@ class ChannelSendReceiveStressTest( } } val senders = List(nSenders) { senderIndex -> - launch(Dispatchers.Default + CoroutineName("sender$senderIndex")) { + launch(pool + CoroutineName("sender$senderIndex")) { when (senderIndex % 2) { 0 -> doSend(senderIndex) 1 -> doSendSelect(senderIndex) From 12e96cdcc628edc2bf22755dafb658e96d1acb35 Mon Sep 17 00:00:00 2001 From: dkhalanskyjb <52952525+dkhalanskyjb@users.noreply.github.com> Date: Wed, 4 Mar 2020 16:58:18 +0300 Subject: [PATCH 44/50] Implement ObservableValue.asFlow() (#1789) * Implement ObservableValue.asFlow() Fixes #1695 --- .../api/kotlinx-coroutines-javafx.api | 4 + .../src/JavaFxConvert.kt | 41 +++++++ .../src/JavaFxDispatcher.kt | 2 +- ...{JavaFxTest.kt => JavaFxDispatcherTest.kt} | 2 +- .../test/JavaFxObservableAsFlowTest.kt | 86 +++++++++++++++ .../test/JavaFxStressTest.kt | 39 +++++++ .../test/examples/FxAsFlow.kt | 101 ++++++++++++++++++ 7 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt rename ui/kotlinx-coroutines-javafx/test/{JavaFxTest.kt => JavaFxDispatcherTest.kt} (97%) create mode 100644 ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt create mode 100644 ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt create mode 100644 ui/kotlinx-coroutines-javafx/test/examples/FxAsFlow.kt diff --git a/ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api b/ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api index 24c5b70b9d..620e904612 100644 --- a/ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api +++ b/ui/kotlinx-coroutines-javafx/api/kotlinx-coroutines-javafx.api @@ -1,3 +1,7 @@ +public final class kotlinx/coroutines/javafx/JavaFxConvertKt { + public static final fun asFlow (Ljavafx/beans/value/ObservableValue;)Lkotlinx/coroutines/flow/Flow; +} + public abstract class kotlinx/coroutines/javafx/JavaFxDispatcher : kotlinx/coroutines/MainCoroutineDispatcher, kotlinx/coroutines/Delay { public fun delay (JLkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun dispatch (Lkotlin/coroutines/CoroutineContext;Ljava/lang/Runnable;)V diff --git a/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt b/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.kt new file mode 100644 index 0000000000..903b60a2cf --- /dev/null +++ b/ui/kotlinx-coroutines-javafx/src/JavaFxConvert.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.javafx + +import javafx.beans.value.ChangeListener +import javafx.beans.value.ObservableValue +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.* + +/** + * Creates an instance of a cold [Flow] that subscribes to the given [ObservableValue] and emits + * its values as they change. The resulting flow is conflated, meaning that if several values arrive in quick + * succession, only the last one will be emitted. + * Since this implementation uses [ObservableValue.addListener], even if this [ObservableValue] + * supports lazy evaluation, eager computation will be enforced while the flow is being collected. + * All the calls to JavaFX API are performed in [Dispatchers.JavaFx]. + * This flow emits at least the initial value. + * + * ### Operator fusion + * + * Adjacent applications of [flowOn], [buffer], [conflate], and [produceIn] to the result of `asFlow` are fused. + * [conflate] has no effect, as this flow is already conflated; one can use [buffer] to change that instead. + */ +@ExperimentalCoroutinesApi +public fun ObservableValue.asFlow(): Flow = callbackFlow { + val listener = ChangeListener { _, _, newValue -> + try { + offer(newValue) + } catch (e: CancellationException) { + // In case the event fires after the channel is closed + } + } + addListener(listener) + send(value) + awaitClose { + removeListener(listener) + } +}.flowOn(Dispatchers.JavaFx).conflate() diff --git a/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt b/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt index 8f5be31dd4..ed74ad6a56 100644 --- a/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt +++ b/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt @@ -116,7 +116,7 @@ private class PulseTimer : AnimationTimer() { } } -/** @return [true] if initialized successfully, and [false] if no display is detected */ +/** @return true if initialized successfully, and false if no display is detected */ internal fun initPlatform(): Boolean = PlatformInitializer.success // Lazily try to initialize JavaFx platform just once diff --git a/ui/kotlinx-coroutines-javafx/test/JavaFxTest.kt b/ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt similarity index 97% rename from ui/kotlinx-coroutines-javafx/test/JavaFxTest.kt rename to ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt index e6a1ddb414..724be6d77b 100644 --- a/ui/kotlinx-coroutines-javafx/test/JavaFxTest.kt +++ b/ui/kotlinx-coroutines-javafx/test/JavaFxDispatcherTest.kt @@ -8,7 +8,7 @@ import javafx.application.* import kotlinx.coroutines.* import org.junit.* -class JavaFxTest : TestBase() { +class JavaFxDispatcherTest : TestBase() { @Before fun setup() { ignoreLostThreads("JavaFX Application Thread", "Thread-", "QuantumRenderer-", "InvokeLaterDispatcher") diff --git a/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt b/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt new file mode 100644 index 0000000000..6964050102 --- /dev/null +++ b/ui/kotlinx-coroutines-javafx/test/JavaFxObservableAsFlowTest.kt @@ -0,0 +1,86 @@ +package kotlinx.coroutines.javafx + +import javafx.beans.property.SimpleIntegerProperty +import kotlinx.coroutines.TestBase +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import org.junit.Before +import org.junit.Test +import kotlin.test.* + + +class JavaFxObservableAsFlowTest : TestBase() { + + @Before + fun setup() { + ignoreLostThreads("JavaFX Application Thread", "Thread-", "QuantumRenderer-", "InvokeLaterDispatcher") + } + + @Test + fun testFlowOrder() = runTest { + if (!initPlatform()) { + println("Skipping JavaFxTest in headless environment") + return@runTest // ignore test in headless environments + } + + val integerProperty = SimpleIntegerProperty(0) + val n = 1000 + val flow = integerProperty.asFlow().takeWhile { j -> j != n } + newSingleThreadContext("setter").use { pool -> + launch(pool) { + for (i in 1..n) { + launch(Dispatchers.JavaFx) { + integerProperty.set(i) + } + } + } + var i = -1 + flow.collect { j -> + assertTrue(i < (j as Int), "Elements are neither repeated nor shuffled") + i = j + } + } + } + + @Test + fun testConflation() = runTest { + if (!initPlatform()) { + println("Skipping JavaFxTest in headless environment") + return@runTest // ignore test in headless environments + } + + withContext(Dispatchers.JavaFx) { + val END_MARKER = -1 + val integerProperty = SimpleIntegerProperty(0) + val flow = integerProperty.asFlow().takeWhile { j -> j != END_MARKER } + launch { + yield() // to subscribe to [integerProperty] + yield() // send 0 + integerProperty.set(1) + expect(3) + yield() // send 1 + expect(5) + integerProperty.set(2) + for (i in (-100..-2)) { + integerProperty.set(i) // should be skipped due to conflation + } + integerProperty.set(3) + expect(6) + yield() // send 2 and 3 + integerProperty.set(-1) + } + expect(1) + flow.collect { i -> + when (i) { + 0 -> expect(2) + 1 -> expect(4) + 2 -> expect(7) + 3 -> expect(8) + else -> fail("i is $i") + } + } + finish(9) + } + } + +} diff --git a/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt b/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt new file mode 100644 index 0000000000..5338835d84 --- /dev/null +++ b/ui/kotlinx-coroutines-javafx/test/JavaFxStressTest.kt @@ -0,0 +1,39 @@ +package kotlinx.coroutines.javafx + +import javafx.beans.property.SimpleIntegerProperty +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.first +import org.junit.* + +class JavaFxStressTest : TestBase() { + + @Before + fun setup() { + ignoreLostThreads("JavaFX Application Thread", "Thread-", "QuantumRenderer-", "InvokeLaterDispatcher") + } + + @get:Rule + val pool = ExecutorRule(1) + + @Test + fun testCancellationRace() = runTest { + if (!initPlatform()) { + println("Skipping JavaFxTest in headless environment") + return@runTest // ignore test in headless environments + } + + val integerProperty = SimpleIntegerProperty(0) + val flow = integerProperty.asFlow() + var i = 1 + val n = 1000 * stressTestMultiplier + repeat (n) { + launch(pool) { + flow.first() + } + withContext(Dispatchers.JavaFx) { + integerProperty.set(i) + } + i += 1 + } + } +} \ No newline at end of file diff --git a/ui/kotlinx-coroutines-javafx/test/examples/FxAsFlow.kt b/ui/kotlinx-coroutines-javafx/test/examples/FxAsFlow.kt new file mode 100644 index 0000000000..00003f7860 --- /dev/null +++ b/ui/kotlinx-coroutines-javafx/test/examples/FxAsFlow.kt @@ -0,0 +1,101 @@ +package examples + +import javafx.application.Application +import javafx.scene.Scene +import javafx.scene.control.* +import javafx.scene.layout.GridPane +import javafx.stage.Stage +import javafx.beans.property.SimpleStringProperty +import javafx.event.EventHandler +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.javafx.* +import kotlin.coroutines.CoroutineContext + +fun main(args: Array) { + Application.launch(FxAsFlowApp::class.java, *args) +} + +/** + * Adapted from + * https://github.com/ReactiveX/RxJavaFX/blob/a78ca7d15f7d82d201df8fafb6eba732ec17e327/src/test/java/io/reactivex/rxjavafx/RxJavaFXTest.java + */ +class FxAsFlowApp: Application(), CoroutineScope { + + private var job = Job() + override val coroutineContext: CoroutineContext + get() = JavaFx + job + + private val incrementButton = Button("Increment") + private val incrementLabel = Label("") + private val textInput = TextField() + private val flippedTextLabel = Label() + private val spinner = Spinner() + private val spinnerChangesLabel = Label() + + public override fun start( primaryStage: Stage) { + val gridPane = GridPane() + gridPane.apply { + hgap = 10.0 + vgap = 10.0 + add(incrementButton, 0, 0) + add(incrementLabel, 1, 0) + add(textInput, 0, 1) + add(flippedTextLabel, 1, 1) + add(spinner, 0, 2) + add(spinnerChangesLabel, 1, 2) + } + val scene = Scene(gridPane) + primaryStage.apply { + width = 275.0 + setScene(scene) + show() + } + } + + public override fun stop() { + super.stop() + job.cancel() + job = Job() + } + + init { + // Initializing the "Increment" button + val stringProperty = SimpleStringProperty() + var i = 0 + incrementButton.onAction = EventHandler { + i += 1 + stringProperty.set(i.toString()) + } + launch { + stringProperty.asFlow().collect { + if (it != null) { + stringProperty.set(it) + } + } + } + incrementLabel.textProperty().bind(stringProperty) + // Initializing the reversed text field + val stringProperty2 = SimpleStringProperty() + launch { + textInput.textProperty().asFlow().collect { + if (it != null) { + stringProperty2.set(it.reversed()) + } + } + } + flippedTextLabel.textProperty().bind(stringProperty2) + // Initializing the spinner + spinner.valueFactory = SpinnerValueFactory.IntegerSpinnerValueFactory(0, 100) + spinner.isEditable = true + val stringProperty3 = SimpleStringProperty() + launch { + spinner.valueProperty().asFlow().collect { + if (it != null) { + stringProperty3.set("NEW: $it") + } + } + } + spinnerChangesLabel.textProperty().bind(stringProperty3) + } +} From d831a862cb688536d564efb1e98af8e3272c31ba Mon Sep 17 00:00:00 2001 From: Marek Langiewicz Date: Sun, 23 Feb 2020 10:12:46 +0100 Subject: [PATCH 45/50] Add ObservableSource.asFlow operator (#1768) --- reactive/kotlinx-coroutines-rx2/README.md | 10 +- .../api/kotlinx-coroutines-rx2.api | 1 + .../kotlinx-coroutines-rx2/src/RxConvert.kt | 31 +++ .../test/ObservableAsFlowTest.kt | 185 ++++++++++++++++++ 4 files changed, 223 insertions(+), 4 deletions(-) create mode 100644 reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt diff --git a/reactive/kotlinx-coroutines-rx2/README.md b/reactive/kotlinx-coroutines-rx2/README.md index 7fbad95369..f0fbeb001e 100644 --- a/reactive/kotlinx-coroutines-rx2/README.md +++ b/reactive/kotlinx-coroutines-rx2/README.md @@ -14,10 +14,11 @@ Coroutine builders: Integration with [Flow]: -| **Name** | **Result** | **Description** -| --------------- | -------------- | --------------- -| [Flow.asFlowable] | `Flowable` | Converts the given flow to a cold Flowable. -| [Flow.asObservable] | `Observable` | Converts the given flow to a cold Observable. +| **Name** | **Result** | **Description** +| --------------- | -------------- | --------------- +| [Flow.asFlowable] | `Flowable` | Converts the given flow to a cold Flowable. +| [Flow.asObservable] | `Observable` | Converts the given flow to a cold Observable. +| [ObservableSource.asFlow] | `Flow` | Converts the given cold ObservableSource to flow Suspending extension functions and suspending iteration: @@ -67,6 +68,7 @@ Conversion functions: [rxFlowable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/rx-flowable.html [Flow.asFlowable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/kotlinx.coroutines.flow.-flow/as-flowable.html [Flow.asObservable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/kotlinx.coroutines.flow.-flow/as-observable.html +[ObservableSource.asFlow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/io.reactivex.-observable-source/as-flow.html [io.reactivex.CompletableSource.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/io.reactivex.-completable-source/await.html [io.reactivex.MaybeSource.await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/io.reactivex.-maybe-source/await.html [io.reactivex.MaybeSource.awaitOrDefault]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-rx2/kotlinx.coroutines.rx2/io.reactivex.-maybe-source/await-or-default.html diff --git a/reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api b/reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api index 54a9663a41..22f40384f0 100644 --- a/reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api +++ b/reactive/kotlinx-coroutines-rx2/api/kotlinx-coroutines-rx2.api @@ -29,6 +29,7 @@ public final class kotlinx/coroutines/rx2/RxCompletableKt { public final class kotlinx/coroutines/rx2/RxConvertKt { public static final fun asCompletable (Lkotlinx/coroutines/Job;Lkotlin/coroutines/CoroutineContext;)Lio/reactivex/Completable; + public static final fun asFlow (Lio/reactivex/ObservableSource;)Lkotlinx/coroutines/flow/Flow; public static final fun asMaybe (Lkotlinx/coroutines/Deferred;Lkotlin/coroutines/CoroutineContext;)Lio/reactivex/Maybe; public static final fun asObservable (Lkotlinx/coroutines/channels/ReceiveChannel;Lkotlin/coroutines/CoroutineContext;)Lio/reactivex/Observable; public static final fun asSingle (Lkotlinx/coroutines/Deferred;Lkotlin/coroutines/CoroutineContext;)Lio/reactivex/Single; diff --git a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt index a9d423a99b..36e8dd955a 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt @@ -5,10 +5,12 @@ package kotlinx.coroutines.rx2 import io.reactivex.* +import io.reactivex.disposables.* import kotlinx.coroutines.* import kotlinx.coroutines.channels.* import kotlinx.coroutines.flow.* import kotlinx.coroutines.reactive.* +import java.util.concurrent.atomic.* import kotlin.coroutines.* /** @@ -77,6 +79,35 @@ public fun ReceiveChannel.asObservable(context: CoroutineContext): send(t) } +/** + * Transforms given cold [ObservableSource] into cold [Flow]. + * + * The resulting flow is _cold_, which means that [ObservableSource.subscribe] is called every time a terminal operator + * is applied to the resulting flow. + * + * A channel with the [default][Channel.BUFFERED] buffer size is used. Use the [buffer] operator on the + * resulting flow to specify a user-defined value and to control what happens when data is produced faster + * than consumed, i.e. to control the back-pressure behavior. Check [callbackFlow] for more details. + */ +@ExperimentalCoroutinesApi +public fun ObservableSource.asFlow(): Flow = callbackFlow { + val disposableRef = AtomicReference() + val observer = object : Observer { + override fun onComplete() { close() } + override fun onSubscribe(d: Disposable) { if (!disposableRef.compareAndSet(null, d)) d.dispose() } + override fun onNext(t: T) { sendBlocking(t) } + override fun onError(e: Throwable) { close(e) } + } + + subscribe(observer) + awaitClose { disposableRef.getAndSet(Disposed)?.dispose() } +} + +private object Disposed : Disposable { + override fun isDisposed() = true + override fun dispose() = Unit +} + /** * Converts the given flow to a cold observable. * The original flow is cancelled when the observable subscriber is disposed. diff --git a/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt b/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt new file mode 100644 index 0000000000..c14c3cc4e8 --- /dev/null +++ b/reactive/kotlinx-coroutines-rx2/test/ObservableAsFlowTest.kt @@ -0,0 +1,185 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.rx2 + +import io.reactivex.Observable +import io.reactivex.ObservableSource +import io.reactivex.Observer +import io.reactivex.disposables.Disposables +import io.reactivex.subjects.PublishSubject +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.* +import kotlinx.coroutines.flow.* +import kotlin.test.* + +class ObservableAsFlowTest : TestBase() { + @Test + fun testCancellation() = runTest { + var onNext = 0 + var onCancelled = 0 + var onError = 0 + + val source = rxObservable(currentDispatcher()) { + coroutineContext[Job]?.invokeOnCompletion { + if (it is CancellationException) ++onCancelled + } + + repeat(100) { + send(it) + } + } + + source.asFlow().launchIn(CoroutineScope(Dispatchers.Unconfined)) { + onEach { + ++onNext + throw RuntimeException() + } + catch { + ++onError + } + }.join() + + + assertEquals(1, onNext) + assertEquals(1, onError) + assertEquals(1, onCancelled) + } + + @Test + fun testImmediateCollection() { + val source = PublishSubject.create() + val flow = source.asFlow() + GlobalScope.launch(Dispatchers.Unconfined) { + expect(1) + flow.collect { expect(it) } + expect(6) + } + expect(2) + source.onNext(3) + expect(4) + source.onNext(5) + source.onComplete() + finish(7) + } + + @Test + fun testOnErrorCancellation() { + val source = PublishSubject.create() + val flow = source.asFlow() + val exception = RuntimeException() + GlobalScope.launch(Dispatchers.Unconfined) { + try { + expect(1) + flow.collect { expect(it) } + expectUnreached() + } + catch (e: Exception) { + assertSame(exception, e.cause) + expect(5) + } + expect(6) + } + expect(2) + source.onNext(3) + expect(4) + source.onError(exception) + finish(7) + } + + @Test + fun testUnsubscribeOnCollectionException() { + val source = PublishSubject.create() + val flow = source.asFlow() + val exception = RuntimeException() + GlobalScope.launch(Dispatchers.Unconfined) { + try { + expect(1) + flow.collect { + expect(it) + if (it == 3) throw exception + } + expectUnreached() + } + catch (e: Exception) { + assertSame(exception, e.cause) + expect(4) + } + expect(5) + } + expect(2) + assertTrue(source.hasObservers()) + source.onNext(3) + assertFalse(source.hasObservers()) + finish(6) + } + + @Test + fun testLateOnSubscribe() { + var observer: Observer? = null + val source = ObservableSource { observer = it } + val flow = source.asFlow() + assertNull(observer) + val job = GlobalScope.launch(Dispatchers.Unconfined) { + expect(1) + flow.collect { expectUnreached() } + expectUnreached() + } + expect(2) + assertNotNull(observer) + job.cancel() + val disposable = Disposables.empty() + observer!!.onSubscribe(disposable) + assertTrue(disposable.isDisposed) + finish(3) + } + + @Test + fun testBufferUnlimited() = runTest { + val source = rxObservable(currentDispatcher()) { + expect(1); send(10) + expect(2); send(11) + expect(3); send(12) + expect(4); send(13) + expect(5); send(14) + expect(6); send(15) + expect(7); send(16) + expect(8); send(17) + expect(9) + } + source.asFlow().buffer(Channel.UNLIMITED).collect { expect(it) } + finish(18) + } + + @Test + fun testConflated() = runTest { + val source = Observable.range(1, 5) + val list = source.asFlow().conflate().toList() + assertEquals(listOf(1, 5), list) + } + + @Test + fun testLongRange() = runTest { + val source = Observable.range(1, 10_000) + val count = source.asFlow().count() + assertEquals(10_000, count) + } + + @Test + fun testProduce() = runTest { + val source = Observable.range(0, 10) + val flow = source.asFlow() + check((0..9).toList(), flow.produceIn(this)) + check((0..9).toList(), flow.buffer(Channel.UNLIMITED).produceIn(this)) + check((0..9).toList(), flow.buffer(2).produceIn(this)) + check((0..9).toList(), flow.buffer(0).produceIn(this)) + check(listOf(0, 9), flow.conflate().produceIn(this)) + } + + private suspend fun check(expected: List, channel: ReceiveChannel) { + val result = ArrayList(10) + channel.consumeEach { result.add(it) } + assertEquals(expected, result) + } +} \ No newline at end of file From 8d8a8fb1b1267576a1bfc21e9240b0ea52106f90 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 4 Mar 2020 23:33:18 +0300 Subject: [PATCH 46/50] Reuse RxJava built-in disposed Disposable (#1841) --- reactive/kotlinx-coroutines-rx2/src/RxConvert.kt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt index 36e8dd955a..0be606ffc2 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt @@ -100,12 +100,7 @@ public fun ObservableSource.asFlow(): Flow = callbackFlow { } subscribe(observer) - awaitClose { disposableRef.getAndSet(Disposed)?.dispose() } -} - -private object Disposed : Disposable { - override fun isDisposed() = true - override fun dispose() = Unit + awaitClose { disposableRef.getAndSet(Disposables.disposed())?.dispose() } } /** From 214f156c7915185b04489c23ad5468cd5266aabb Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 5 Mar 2020 23:02:30 +0300 Subject: [PATCH 47/50] Leverage polymorphic keys un CoroutineDispatcher and ExecutorCoroutineDispatcher (#1840) --- .../api/kotlinx-coroutines-core.api | 8 +++ .../common/src/CoroutineDispatcher.kt | 6 +++ kotlinx-coroutines-core/jvm/src/Executors.kt | 18 ++++--- .../jvm/test/DispatcherKeyTest.kt | 52 +++++++++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt diff --git a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api index 76a0bed462..d86a3d5559 100644 --- a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api +++ b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api @@ -151,6 +151,7 @@ public final class kotlinx/coroutines/CoroutineContextKt { } public abstract class kotlinx/coroutines/CoroutineDispatcher : kotlin/coroutines/AbstractCoroutineContextElement, kotlin/coroutines/ContinuationInterceptor { + public static final field Key Lkotlinx/coroutines/CoroutineDispatcher$Key; public fun ()V public abstract fun dispatch (Lkotlin/coroutines/CoroutineContext;Ljava/lang/Runnable;)V public fun dispatchYield (Lkotlin/coroutines/CoroutineContext;Ljava/lang/Runnable;)V @@ -163,6 +164,9 @@ public abstract class kotlinx/coroutines/CoroutineDispatcher : kotlin/coroutines public fun toString ()Ljava/lang/String; } +public final class kotlinx/coroutines/CoroutineDispatcher$Key : kotlin/coroutines/AbstractCoroutineContextKey { +} + public abstract interface class kotlinx/coroutines/CoroutineExceptionHandler : kotlin/coroutines/CoroutineContext$Element { public static final field Key Lkotlinx/coroutines/CoroutineExceptionHandler$Key; public abstract fun handleException (Lkotlin/coroutines/CoroutineContext;Ljava/lang/Throwable;)V @@ -294,11 +298,15 @@ public final class kotlinx/coroutines/ExceptionsKt { } public abstract class kotlinx/coroutines/ExecutorCoroutineDispatcher : kotlinx/coroutines/CoroutineDispatcher, java/io/Closeable { + public static final field Key Lkotlinx/coroutines/ExecutorCoroutineDispatcher$Key; public fun ()V public abstract fun close ()V public abstract fun getExecutor ()Ljava/util/concurrent/Executor; } +public final class kotlinx/coroutines/ExecutorCoroutineDispatcher$Key : kotlin/coroutines/AbstractCoroutineContextKey { +} + public final class kotlinx/coroutines/ExecutorsKt { public static final fun asExecutor (Lkotlinx/coroutines/CoroutineDispatcher;)Ljava/util/concurrent/Executor; public static final fun from (Ljava/util/concurrent/Executor;)Lkotlinx/coroutines/CoroutineDispatcher; diff --git a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt index 3a54390f0b..a618642f72 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt @@ -30,6 +30,12 @@ import kotlin.coroutines.* public abstract class CoroutineDispatcher : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor { + /** @suppress */ + @ExperimentalStdlibApi + public companion object Key : AbstractCoroutineContextKey( + ContinuationInterceptor, + { it as? CoroutineDispatcher }) + /** * Returns `true` if the execution of the coroutine should be performed with [dispatch] method. * The default behavior for most dispatchers is to return `true`. diff --git a/kotlinx-coroutines-core/jvm/src/Executors.kt b/kotlinx-coroutines-core/jvm/src/Executors.kt index e4d25a735e..a4d6b46c43 100644 --- a/kotlinx-coroutines-core/jvm/src/Executors.kt +++ b/kotlinx-coroutines-core/jvm/src/Executors.kt @@ -5,7 +5,7 @@ package kotlinx.coroutines import kotlinx.coroutines.internal.* -import java.io.Closeable +import java.io.* import java.util.concurrent.* import kotlin.coroutines.* @@ -17,17 +17,23 @@ import kotlin.coroutines.* * asynchronous API which requires instance of the [Executor]. */ public abstract class ExecutorCoroutineDispatcher: CoroutineDispatcher(), Closeable { + /** @suppress */ + @ExperimentalStdlibApi + public companion object Key : AbstractCoroutineContextKey( + CoroutineDispatcher, + { it as? ExecutorCoroutineDispatcher }) + + /** + * Underlying executor of current [CoroutineDispatcher]. + */ + public abstract val executor: Executor + /** * Closes this coroutine dispatcher and shuts down its executor. * * It may throw an exception if this dispatcher is global and cannot be closed. */ public abstract override fun close() - - /** - * Underlying executor of current [CoroutineDispatcher]. - */ - public abstract val executor: Executor } /** diff --git a/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt b/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt new file mode 100644 index 0000000000..e2d8ffaa47 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/DispatcherKeyTest.kt @@ -0,0 +1,52 @@ +/* + * 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.junit.Test +import kotlin.coroutines.* +import kotlin.test.* + +@UseExperimental(ExperimentalStdlibApi::class) +class DispatcherKeyTest : TestBase() { + + companion object CustomInterceptor : AbstractCoroutineContextElement(ContinuationInterceptor), + ContinuationInterceptor { + override fun interceptContinuation(continuation: Continuation): Continuation { + return continuation + } + } + + private val name = CoroutineName("test") + + @Test + fun testDispatcher() { + val context = name + CustomInterceptor + assertNull(context[CoroutineDispatcher]) + assertSame(CustomInterceptor, context[ContinuationInterceptor]) + + val updated = context + Dispatchers.Main + val result: CoroutineDispatcher? = updated[CoroutineDispatcher] + assertSame(Dispatchers.Main, result) + assertSame(Dispatchers.Main, updated[ContinuationInterceptor]) + assertEquals(name, updated.minusKey(CoroutineDispatcher)) + assertEquals(name, updated.minusKey(ContinuationInterceptor)) + } + + @Test + fun testExecutorCoroutineDispatcher() { + val context = name + CustomInterceptor + assertNull(context[ExecutorCoroutineDispatcher]) + val updated = context + Dispatchers.Main + assertNull(updated[ExecutorCoroutineDispatcher]) + val executor = Dispatchers.Default + val updated2 = updated + executor + assertSame(Dispatchers.Default, updated2[ContinuationInterceptor]) + assertSame(Dispatchers.Default, updated2[CoroutineDispatcher]) + assertSame(Dispatchers.Default as ExecutorCoroutineDispatcher, updated2[ExecutorCoroutineDispatcher]) + assertEquals(name, updated2.minusKey(ContinuationInterceptor)) + assertEquals(name, updated2.minusKey(CoroutineDispatcher)) + assertEquals(name, updated2.minusKey(ExecutorCoroutineDispatcher)) + } +} From c67aed05f7c17e6e80c3d18d744861580bb74607 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 5 Mar 2020 23:02:42 +0300 Subject: [PATCH 48/50] Migrate experimental annotations to new API and provide custom warning message (#1842) --- .../common/src/Annotations.kt | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/Annotations.kt b/kotlinx-coroutines-core/common/src/Annotations.kt index 106fd03ddb..5475c6b10e 100644 --- a/kotlinx-coroutines-core/common/src/Annotations.kt +++ b/kotlinx-coroutines-core/common/src/Annotations.kt @@ -4,7 +4,7 @@ package kotlinx.coroutines -import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.* /** * Marks declarations that are still **experimental** in coroutines API, which means that the design of the @@ -14,7 +14,7 @@ import kotlinx.coroutines.flow.Flow */ @MustBeDocumented @Retention(value = AnnotationRetention.BINARY) -@Experimental(level = Experimental.Level.WARNING) +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) public annotation class ExperimentalCoroutinesApi /** @@ -30,7 +30,12 @@ public annotation class ExperimentalCoroutinesApi */ @MustBeDocumented @Retention(value = AnnotationRetention.BINARY) -@Experimental(level = Experimental.Level.WARNING) +@RequiresOptIn( + level = RequiresOptIn.Level.WARNING, + message = "This declaration is in a preview state and can be changed in a backwards-incompatible manner with a best-effort migration. " + + "Its usage should be marked with '@kotlinx.coroutines.FlowPreview' or '@OptIn(kotlinx.coroutines.FlowPreview::class)' " + + "if you accept the drawback of relying on preview API" +) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) public annotation class FlowPreview @@ -42,7 +47,7 @@ public annotation class FlowPreview */ @MustBeDocumented @Retention(value = AnnotationRetention.BINARY) -@Experimental(level = Experimental.Level.WARNING) +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) public annotation class ObsoleteCoroutinesApi /** @@ -51,6 +56,11 @@ public annotation class ObsoleteCoroutinesApi * warnings and without providing any migration aids. */ @Retention(value = AnnotationRetention.BINARY) -@Experimental(level = Experimental.Level.ERROR) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS, AnnotationTarget.PROPERTY) +@RequiresOptIn( + level = RequiresOptIn.Level.ERROR, message = "This is an internal kotlinx.coroutines API that " + + "should not be used from outside of kotlinx.coroutines. No compatibility guarantees are provided." + + "It is recommended to report your use-case of internal API to kotlinx.coroutines issue tracker, " + + "so stable API could be provided instead" +) public annotation class InternalCoroutinesApi From 7df61eec64296bd012915ce2541eea3b7a5cb9c4 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 6 Mar 2020 12:23:21 +0300 Subject: [PATCH 49/50] Fixed memory leak on a race between adding/removing from lock-free list (#1845) * The problem was introduced by #1565. When doing concurrent add+removeFirst the following can happen: - "add" completes, but has not correct prev pointer in next node yet - "removeFirst" removes freshly added element - "add" performs "finishAdd" that adjust prev pointer of the next node and thus removed element is pointed from the list again * A separate LockFreeLinkedListAddRemoveStressTest is added that reproduces this problem. * The old LockFreeLinkedListAtomicLFStressTest is refactored a bit. --- .../jvm/src/internal/LockFreeLinkedList.kt | 15 +++-- .../LockFreeLinkedListAddRemoveStressTest.kt | 56 +++++++++++++++++++ .../LockFreeLinkedListAtomicLFStressTest.kt | 48 ++++++++-------- 3 files changed, 90 insertions(+), 29 deletions(-) create mode 100644 kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAddRemoveStressTest.kt diff --git a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt index 26fd169da3..f718df04b5 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt @@ -390,7 +390,7 @@ public actual open class LockFreeLinkedListNode { final override fun updatedNext(affected: Node, next: Node): Any = next.removed() final override fun finishOnSuccess(affected: Node, next: Node) { - // Complete removal operation here. It bails out if next node is also removed and it becomes + // Complete removal operation here. It bails out if next node is also removed. It becomes // responsibility of the next's removes to call correctPrev which would help fix all the links. next.correctPrev(null) } @@ -531,7 +531,12 @@ public actual open class LockFreeLinkedListNode { private fun finishAdd(next: Node) { next._prev.loop { nextPrev -> if (this.next !== next) return // this or next was removed or another node added, remover/adder fixes up links - if (next._prev.compareAndSet(nextPrev, this)) return + if (next._prev.compareAndSet(nextPrev, this)) { + // This newly added node could have been removed, and the above CAS would have added it physically again. + // Let us double-check for this situation and correct if needed + if (isRemoved) next.correctPrev(null) + return + } } } @@ -546,7 +551,7 @@ public actual open class LockFreeLinkedListNode { * * When this node is removed. In this case there is no need to waste time on corrections, because * remover of this node will ultimately call [correctPrev] on the next node and that will fix all * the links from this node, too. - * * When [op] descriptor is not `null` and and operation descriptor that is [OpDescriptor.isEarlierThan] + * * When [op] descriptor is not `null` and operation descriptor that is [OpDescriptor.isEarlierThan] * that current [op] is found while traversing the list. This `null` result will be translated * by callers to [RETRY_ATOMIC]. */ @@ -554,7 +559,7 @@ public actual open class LockFreeLinkedListNode { val oldPrev = _prev.value var prev: Node = oldPrev var last: Node? = null // will be set so that last.next === prev - while (true) { // move the the left until first non-removed node + while (true) { // move the left until first non-removed node val prevNext: Any = prev._next.value when { // fast path to find quickly find prev node when everything is properly linked @@ -565,7 +570,7 @@ public actual open class LockFreeLinkedListNode { // Note: retry from scratch on failure to update prev return correctPrev(op) } - return prev // return a correct prev + return prev // return the correct prev } // slow path when we need to help remove operations this.isRemoved -> return null // nothing to do, this node was removed, bail out asap to save time diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAddRemoveStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAddRemoveStressTest.kt new file mode 100644 index 0000000000..3229e664c1 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAddRemoveStressTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.internal + +import kotlinx.atomicfu.* +import kotlinx.coroutines.* +import java.util.concurrent.* +import kotlin.concurrent.* +import kotlin.test.* + +class LockFreeLinkedListAddRemoveStressTest : TestBase() { + private class Node : LockFreeLinkedListNode() + + private val nRepeat = 100_000 * stressTestMultiplier + private val list = LockFreeLinkedListHead() + private val barrier = CyclicBarrier(3) + private val done = atomic(false) + private val removed = atomic(0) + + @Test + fun testStressAddRemove() { + val threads = ArrayList() + threads += testThread("adder") { + val node = Node() + list.addLast(node) + if (node.remove()) removed.incrementAndGet() + } + threads += testThread("remover") { + val node = list.removeFirstOrNull() + if (node != null) removed.incrementAndGet() + } + try { + for (i in 1..nRepeat) { + barrier.await() + barrier.await() + assertEquals(i, removed.value) + list.validate() + } + } finally { + done.value = true + barrier.await() + threads.forEach { it.join() } + } + } + + private fun testThread(name: String, op: () -> Unit) = thread(name = name) { + while (true) { + barrier.await() + if (done.value) break + op() + barrier.await() + } + } +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt index b967c46a8f..225b848186 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicLFStressTest.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-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.internal @@ -19,9 +19,9 @@ import kotlin.test.* class LockFreeLinkedListAtomicLFStressTest { private val env = LockFreedomTestEnvironment("LockFreeLinkedListAtomicLFStressTest") - data class IntNode(val i: Int) : LockFreeLinkedListNode() + private data class Node(val i: Long) : LockFreeLinkedListNode() - private val TEST_DURATION_SEC = 5 * stressTestMultiplier + private val nSeconds = 5 * stressTestMultiplier private val nLists = 4 private val nAdderThreads = 4 @@ -32,7 +32,8 @@ class LockFreeLinkedListAtomicLFStressTest { private val undone = AtomicLong() private val missed = AtomicLong() private val removed = AtomicLong() - val error = AtomicReference() + private val error = AtomicReference() + private val index = AtomicLong() @Test fun testStress() { @@ -42,7 +43,7 @@ class LockFreeLinkedListAtomicLFStressTest { when (rnd.nextInt(4)) { 0 -> { val list = lists[rnd.nextInt(nLists)] - val node = IntNode(threadId) + val node = Node(index.incrementAndGet()) addLastOp(list, node) randomSpinWaitIntermission() tryRemoveOp(node) @@ -50,7 +51,7 @@ class LockFreeLinkedListAtomicLFStressTest { 1 -> { // just to test conditional add val list = lists[rnd.nextInt(nLists)] - val node = IntNode(threadId) + val node = Node(index.incrementAndGet()) addLastIfTrueOp(list, node) randomSpinWaitIntermission() tryRemoveOp(node) @@ -58,7 +59,7 @@ class LockFreeLinkedListAtomicLFStressTest { 2 -> { // just to test failed conditional add and burn some time val list = lists[rnd.nextInt(nLists)] - val node = IntNode(threadId) + val node = Node(index.incrementAndGet()) addLastIfFalseOp(list, node) } 3 -> { @@ -68,8 +69,8 @@ class LockFreeLinkedListAtomicLFStressTest { check(idx1 < idx2) // that is our global order val list1 = lists[idx1] val list2 = lists[idx2] - val node1 = IntNode(threadId) - val node2 = IntNode(-threadId - 1) + val node1 = Node(index.incrementAndGet()) + val node2 = Node(index.incrementAndGet()) addTwoOp(list1, node1, list2, node2) randomSpinWaitIntermission() tryRemoveOp(node1) @@ -91,13 +92,13 @@ class LockFreeLinkedListAtomicLFStressTest { removeTwoOp(list1, list2) } } - env.performTest(TEST_DURATION_SEC) { - val _undone = undone.get() - val _missed = missed.get() - val _removed = removed.get() - println(" Adders undone $_undone node additions") - println(" Adders missed $_missed nodes") - println("Remover removed $_removed nodes") + env.performTest(nSeconds) { + val undone = undone.get() + val missed = missed.get() + val removed = removed.get() + println(" Adders undone $undone node additions") + println(" Adders missed $missed nodes") + println("Remover removed $removed nodes") } error.get()?.let { throw it } assertEquals(missed.get(), removed.get()) @@ -106,19 +107,19 @@ class LockFreeLinkedListAtomicLFStressTest { lists.forEach { it.validate() } } - private fun addLastOp(list: LockFreeLinkedListHead, node: IntNode) { + private fun addLastOp(list: LockFreeLinkedListHead, node: Node) { list.addLast(node) } - private fun addLastIfTrueOp(list: LockFreeLinkedListHead, node: IntNode) { - assertTrue(list.addLastIf(node, { true })) + private fun addLastIfTrueOp(list: LockFreeLinkedListHead, node: Node) { + assertTrue(list.addLastIf(node) { true }) } - private fun addLastIfFalseOp(list: LockFreeLinkedListHead, node: IntNode) { - assertFalse(list.addLastIf(node, { false })) + private fun addLastIfFalseOp(list: LockFreeLinkedListHead, node: Node) { + assertFalse(list.addLastIf(node) { false }) } - private fun addTwoOp(list1: LockFreeLinkedListHead, node1: IntNode, list2: LockFreeLinkedListHead, node2: IntNode) { + private fun addTwoOp(list1: LockFreeLinkedListHead, node1: Node, list2: LockFreeLinkedListHead, node2: Node) { val add1 = list1.describeAddLast(node1) val add2 = list2.describeAddLast(node2) val op = object : AtomicOp() { @@ -138,7 +139,7 @@ class LockFreeLinkedListAtomicLFStressTest { assertTrue(op.perform(null) == null) } - private fun tryRemoveOp(node: IntNode) { + private fun tryRemoveOp(node: Node) { if (node.remove()) undone.incrementAndGet() else @@ -165,5 +166,4 @@ class LockFreeLinkedListAtomicLFStressTest { val success = op.perform(null) == null if (success) removed.addAndGet(2) } - } \ No newline at end of file From bb3cf093afe9beaf448736aa8afc806d2b6bba63 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 6 Mar 2020 12:32:30 +0300 Subject: [PATCH 50/50] Version 1.3.4 --- CHANGES.md | 20 +++++++++++++++++++ README.md | 16 +++++++-------- gradle.properties | 2 +- kotlinx-coroutines-debug/README.md | 4 ++-- kotlinx-coroutines-test/README.md | 2 +- ui/coroutines-guide-ui.md | 2 +- .../animation-app/gradle.properties | 2 +- .../example-app/gradle.properties | 2 +- 8 files changed, 35 insertions(+), 15 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bf1c2e90d0..bdd5d7a6f7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,25 @@ # Change log for kotlinx.coroutines +## Version 1.3.4 + +### Flow + +* Detect missing `awaitClose` calls in `callbackFlow` to make it less error-prone when used with callbacks (#1762, #1770). This change makes `callbackFlow` **different** from `channelFlow`. +* `ReceiveChannel.asFlow` extension is introduced (#1490). +* Enforce exception transparency invariant in `flow` builder (#1657). +* Proper `Dispatcher` support in `Flow` reactive integrations (#1765). +* Batch `Subscription.request` calls in `Flow` reactive integration (#766). +* `ObservableValue.asFlow` added to JavaFx integration module (#1695). +* `ObservableSource.asFlow` added to RxJava2 integration module (#1768). + +### Other changes + +* `kotlinx-coroutines-core` is optimized for R8, making it much smaller for Android usages (75 KB for `1.3.4` release). +* Performance of `Dispatchers.Default` is improved (#1704, #1706). +* Kotlin is updated to 1.3.70. +* `CoroutineDispatcher` and `ExecutorCoroutineDispatcher` experimental coroutine context keys are introduced (#1805). +* Performance of various `Channel` operations is improved (#1565). + ## Version 1.3.3 ### Flow diff --git a/README.md b/README.md index 45e8489704..7a827a2bc9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![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.3.3) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.3.3) +[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.3.4) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.3.4) Library support for Kotlin coroutines with [multiplatform](#multiplatform) support. This is a companion version for Kotlin `1.3.70` release. @@ -82,7 +82,7 @@ Add dependencies (you can also add other modules that you need): org.jetbrains.kotlinx kotlinx-coroutines-core - 1.3.3 + 1.3.4 ``` @@ -100,7 +100,7 @@ Add dependencies (you can also add other modules that you need): ```groovy dependencies { - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.4' } ``` @@ -126,7 +126,7 @@ Add dependencies (you can also add other modules that you need): ```groovy dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.4") } ``` @@ -145,7 +145,7 @@ Make sure that you have either `jcenter()` or `mavenCentral()` in the list of re 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, add dependency to -[`kotlinx-coroutines-core-common`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-common/1.3.3/jar) +[`kotlinx-coroutines-core-common`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-common/1.3.4/jar) (follow the link to get the dependency declaration snippet). ### Android @@ -154,7 +154,7 @@ 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.3.3' +implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4' ``` This gives you access to Android [Dispatchers.Main] @@ -170,7 +170,7 @@ For more details see ["Optimization" section for Android](ui/kotlinx-coroutines- ### JS [Kotlin/JS](https://kotlinlang.org/docs/reference/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.3.3/jar) +[`kotlinx-coroutines-core-js`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-js/1.3.4/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. @@ -178,7 +178,7 @@ You can also use [`kotlinx-coroutines-core`](https://www.npmjs.com/package/kotli ### Native [Kotlin/Native](https://kotlinlang.org/docs/reference/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.3.3/jar) +[`kotlinx-coroutines-core-native`](https://search.maven.org/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core-native/1.3.4/jar) (follow the link to get the dependency declaration snippet). Only single-threaded code (JS-style) on Kotlin/Native is currently supported. diff --git a/gradle.properties b/gradle.properties index c199d9391d..53a8de2687 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ # # Kotlin -version=1.3.3-SNAPSHOT +version=1.3.4-SNAPSHOT group=org.jetbrains.kotlinx kotlin_version=1.3.70 diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md index 21cc76e74f..2704859815 100644 --- a/kotlinx-coroutines-debug/README.md +++ b/kotlinx-coroutines-debug/README.md @@ -18,7 +18,7 @@ of coroutines hierarchy referenced by a [Job] or [CoroutineScope] instances usin Add `kotlinx-coroutines-debug` to your project test dependencies: ``` dependencies { - testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.3.3' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.3.4' } ``` @@ -56,7 +56,7 @@ stacktraces will be dumped to the console. ### Using as JVM agent It is possible to use this module 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.3.3.jar`. +You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.3.4.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. diff --git a/kotlinx-coroutines-test/README.md b/kotlinx-coroutines-test/README.md index aefd5a3f07..e348387835 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.3.3' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.4' } ``` diff --git a/ui/coroutines-guide-ui.md b/ui/coroutines-guide-ui.md index 2ebe58f0e8..bfe45f2230 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.3.3" +implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4" ``` You can clone [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) project from GitHub onto your diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle.properties b/ui/kotlinx-coroutines-android/animation-app/gradle.properties index 07c62f8dfd..e7e3beca2d 100644 --- a/ui/kotlinx-coroutines-android/animation-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/animation-app/gradle.properties @@ -21,7 +21,7 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true kotlin_version=1.3.70 -coroutines_version=1.3.3 +coroutines_version=1.3.4 android.useAndroidX=true android.enableJetifier=true diff --git a/ui/kotlinx-coroutines-android/example-app/gradle.properties b/ui/kotlinx-coroutines-android/example-app/gradle.properties index 07c62f8dfd..e7e3beca2d 100644 --- a/ui/kotlinx-coroutines-android/example-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/example-app/gradle.properties @@ -21,7 +21,7 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true kotlin_version=1.3.70 -coroutines_version=1.3.3 +coroutines_version=1.3.4 android.useAndroidX=true android.enableJetifier=true