From 4b60d013508c865dd8430f334e89481d93893ab1 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Sat, 22 Dec 2018 16:38:36 +0300 Subject: [PATCH 01/82] Update CHM in test to containsKey for KT-18053 fix in 1.3.20 --- .../test/scheduling/CoroutineSchedulerStressTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt index 68e38af623..683a889efa 100644 --- a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt +++ b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt @@ -78,7 +78,7 @@ class CoroutineSchedulerStressTest : TestBase() { finishLatch.await() - require(blockingThread!! !in observedThreads) + require(!observedThreads.containsKey(blockingThread!!)) validateResults() } From b5af3efc9a8de01feca66885caecd6cbf205c6fb Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 9 Jan 2019 14:51:34 +0300 Subject: [PATCH 02/82] Do proper checkcast in takeEventLoop, throw ISE instead of TCE Fixes #920 --- .../src/CoroutineContext.kt | 2 +- .../test/DelayExceptionTest.kt | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 native/kotlinx-coroutines-core-native/test/DelayExceptionTest.kt diff --git a/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt b/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt index d846569126..6aef31090c 100644 --- a/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt +++ b/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt @@ -8,7 +8,7 @@ import kotlin.coroutines.* import kotlinx.coroutines.internal.* private fun takeEventLoop(): EventLoopImpl = - ThreadLocalEventLoop.currentOrNull() as EventLoopImpl ?: + ThreadLocalEventLoop.currentOrNull() as? EventLoopImpl ?: error("There is no event loop. Use runBlocking { ... } to start one.") internal object DefaultExecutor : CoroutineDispatcher(), Delay { diff --git a/native/kotlinx-coroutines-core-native/test/DelayExceptionTest.kt b/native/kotlinx-coroutines-core-native/test/DelayExceptionTest.kt new file mode 100644 index 0000000000..463712ce47 --- /dev/null +++ b/native/kotlinx-coroutines-core-native/test/DelayExceptionTest.kt @@ -0,0 +1,28 @@ +/* + * 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.test.Test +import kotlin.test.assertTrue + +class DelayExceptionTest { + private object Dispatcher : CoroutineDispatcher() { + override fun isDispatchNeeded(context: CoroutineContext): Boolean = true + override fun dispatch(context: CoroutineContext, block: Runnable) { block.run() } + } + + private lateinit var exception: Throwable + + + @Test + fun testThrowsTce() { + CoroutineScope(Dispatcher + CoroutineExceptionHandler { _, e -> exception = e }).launch { + delay(10) + } + + assertTrue(exception is IllegalStateException) + } +} From 22c7809614326cc8408048c39cf769fe4f3ae7d6 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 9 Jan 2019 15:01:41 +0300 Subject: [PATCH 03/82] Print stack trace in default exception handler in K/N --- .../src/CoroutineExceptionHandlerImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/kotlinx-coroutines-core-native/src/CoroutineExceptionHandlerImpl.kt b/native/kotlinx-coroutines-core-native/src/CoroutineExceptionHandlerImpl.kt index 2219339af1..5efa9249ec 100644 --- a/native/kotlinx-coroutines-core-native/src/CoroutineExceptionHandlerImpl.kt +++ b/native/kotlinx-coroutines-core-native/src/CoroutineExceptionHandlerImpl.kt @@ -8,5 +8,5 @@ import kotlin.coroutines.* internal actual fun handleCoroutineExceptionImpl(context: CoroutineContext, exception: Throwable) { // log exception - println(exception) + exception.printStackTrace() } From 8c071247dbe5928ebf5138471c1ac905c5de4018 Mon Sep 17 00:00:00 2001 From: Marek Langiewicz Date: Mon, 31 Dec 2018 14:52:33 +0100 Subject: [PATCH 04/82] Replace old UI dispatcher name with Dispatchers.Main --- common/kotlinx-coroutines-core-common/src/CoroutineScope.kt | 2 +- .../kotlinx-coroutines-core-common/src/channels/Channel.kt | 2 +- core/kotlinx-coroutines-core/src/ThreadContextElement.kt | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt b/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt index 32560159fe..178163ca32 100644 --- a/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt +++ b/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt @@ -163,7 +163,7 @@ public object GlobalScope : CoroutineScope { * ... load some UI data ... * } * - * withContext(UI) { + * withContext(Dispatchers.Main) { * doSomeWork() * val result = data.await() * display(result) diff --git a/common/kotlinx-coroutines-core-common/src/channels/Channel.kt b/common/kotlinx-coroutines-core-common/src/channels/Channel.kt index 5a881410b0..389cece115 100644 --- a/common/kotlinx-coroutines-core-common/src/channels/Channel.kt +++ b/common/kotlinx-coroutines-core-common/src/channels/Channel.kt @@ -111,7 +111,7 @@ public interface SendChannel { * events.offer(event) * } * - * val uiUpdater = launch(UI, parent = UILifecycle) { + * val uiUpdater = launch(Dispatchers.Main, parent = UILifecycle) { * events.consume {} * events.cancel() * } diff --git a/core/kotlinx-coroutines-core/src/ThreadContextElement.kt b/core/kotlinx-coroutines-core/src/ThreadContextElement.kt index 959bc38c3a..68098f3829 100644 --- a/core/kotlinx-coroutines-core/src/ThreadContextElement.kt +++ b/core/kotlinx-coroutines-core/src/ThreadContextElement.kt @@ -40,7 +40,7 @@ import kotlin.coroutines.* * } * * // Usage - * launch(UI + CoroutineName("Progress bar coroutine")) { ... } + * launch(Dispatchers.Main + CoroutineName("Progress bar coroutine")) { ... } * ``` * * Every time this coroutine is resumed on a thread, UI thread name is updated to @@ -90,7 +90,7 @@ public interface ThreadContextElement : CoroutineContext.Element { * println(myThreadLocal.get()) // Prints "null" * launch(Dispatchers.Default + myThreadLocal.asContextElement(value = "foo")) { * println(myThreadLocal.get()) // Prints "foo" - * withContext(UI) { + * withContext(Dispatchers.Main) { * println(myThreadLocal.get()) // Prints "foo", but it's on UI thread * } * } @@ -101,7 +101,7 @@ public interface ThreadContextElement : CoroutineContext.Element { * * ``` * myThreadLocal.set("main") - * withContext(UI) { + * withContext(Dispatchers.Main) { * println(myThreadLocal.get()) // Prints "main" * myThreadLocal.set("UI") * } From e50a0fa78aae052e128e8b17666e081e4dfc78be Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 28 Jan 2019 11:34:24 +0300 Subject: [PATCH 05/82] Migration to new multiplatorm plugin (#947) Migration to a new multiplatform plugin * kotlinx-coroutines-core-[common|js|native] are merged into one core module with multiple source sets * Folder structure and readme are restructured * Publication process is patched to preserve backward compatibility with artifact names --- README.md | 13 +- benchmarks/build.gradle | 8 +- .../resources/api.properties | 4 +- .../test/PublicApiTest.kt | 3 +- build.gradle | 187 +++++++----------- common/README.md | 11 -- .../kotlinx-coroutines-core-common/README.md | 9 - .../build.gradle | 4 - core/README.md | 11 -- core/kotlinx-coroutines-core/build.gradle | 69 ------- docs/basics.md | 22 +-- docs/cancellation-and-timeouts.md | 18 +- docs/channels.md | 24 +-- docs/composing-suspending-functions.md | 16 +- docs/coroutine-context-and-dispatchers.md | 26 +-- docs/exception-handling.md | 22 +-- docs/select-expression.md | 14 +- docs/shared-mutable-state-and-concurrency.md | 20 +- gradle.properties | 1 + gradle/atomicfu-common.gradle | 7 - gradle/atomicfu-js.gradle | 10 - gradle/atomicfu-jvm.gradle | 11 -- gradle/atomicfu-native.gradle | 7 - gradle/compile-common.gradle | 18 +- gradle/compile-js-multiplatform.gradle | 61 ++++++ gradle/compile-js.gradle | 5 +- gradle/compile-jvm-multiplatform.gradle | 40 ++++ gradle/compile-jvm.gradle | 4 +- gradle/compile-native-multiplatform.gradle | 34 ++++ gradle/compile-native.gradle | 47 ----- gradle/dokka.gradle | 120 +++++------ gradle/experimental.gradle | 12 ++ gradle/node-js.gradle | 34 +--- gradle/publish-bintray.gradle | 162 +++++++++++---- gradle/publish-npm-js.gradle | 4 +- gradle/targets.gradle | 28 +++ gradle/test-mocha-js.gradle | 31 ++- js/README.md | 18 +- js/kotlinx-coroutines-core-js/build.gradle | 7 - knit/resources/knit.properties | 2 +- .../README.md | 37 +++- kotlinx-coroutines-core/build.gradle | 103 ++++++++++ .../common}/README.md | 0 .../common}/src/AbstractCoroutine.kt | 0 .../common}/src/Annotations.kt | 0 .../common}/src/Await.kt | 0 .../common}/src/Builders.common.kt | 0 .../common}/src/CancellableContinuation.kt | 0 .../src/CancellableContinuationImpl.kt | 0 .../common}/src/CompletableDeferred.kt | 0 .../common}/src/CompletedExceptionally.kt | 0 .../common}/src/CompletionHandler.common.kt | 0 .../common}/src/CoroutineContext.common.kt | 0 .../common}/src/CoroutineDispatcher.kt | 0 .../common}/src/CoroutineExceptionHandler.kt | 0 .../common}/src/CoroutineName.kt | 0 .../common}/src/CoroutineScope.kt | 0 .../common}/src/CoroutineStart.kt | 0 .../common}/src/Debug.common.kt | 0 .../common}/src/Deferred.kt | 0 .../common}/src/Delay.kt | 0 .../common}/src/Dispatched.kt | 0 .../common}/src/Dispatchers.common.kt | 0 .../common}/src/EventLoop.common.kt | 0 .../common}/src/Exceptions.common.kt | 0 .../common}/src/Job.kt | 0 .../common}/src/JobSupport.kt | 0 .../common}/src/MainCoroutineDispatcher.kt | 0 .../common}/src/NonCancellable.kt | 0 .../common}/src/ResumeMode.kt | 0 .../common}/src/Runnable.common.kt | 0 .../common}/src/SchedulerTask.common.kt | 0 .../common}/src/Supervisor.kt | 0 .../common}/src/Timeout.kt | 0 .../common}/src/Unconfined.kt | 0 .../common}/src/Yield.kt | 0 .../common}/src/channels/AbstractChannel.kt | 0 .../src/channels/ArrayBroadcastChannel.kt | 0 .../common}/src/channels/ArrayChannel.kt | 0 .../common}/src/channels/Broadcast.kt | 0 .../common}/src/channels/BroadcastChannel.kt | 0 .../common}/src/channels/Channel.kt | 0 .../common}/src/channels/ChannelCoroutine.kt | 0 .../common}/src/channels/Channels.common.kt | 0 .../src/channels/ConflatedBroadcastChannel.kt | 0 .../common}/src/channels/ConflatedChannel.kt | 0 .../common}/src/channels/LinkedListChannel.kt | 0 .../common}/src/channels/Produce.kt | 0 .../common}/src/channels/RendezvousChannel.kt | 0 .../common}/src/internal/ArrayCopy.common.kt | 0 .../common}/src/internal/ArrayQueue.kt | 0 .../common}/src/internal/Atomic.kt | 0 .../common}/src/internal/Concurrent.common.kt | 0 .../src/internal/LockFreeLinkedList.common.kt | 0 .../src/internal/MainDispatcherFactory.kt | 0 .../src/internal/ProbesSupport.common.kt | 0 .../common}/src/internal/Scopes.kt | 0 .../src/internal/StackTraceRecovery.common.kt | 0 .../common}/src/internal/Symbol.kt | 0 .../src/internal/Synchronized.common.kt | 0 .../src/internal/ThreadContext.common.kt | 0 .../src/internal/ThreadLocal.common.kt | 0 .../common}/src/intrinsics/Cancellable.kt | 0 .../common}/src/intrinsics/Undispatched.kt | 0 .../common}/src/selects/Select.kt | 0 .../common}/src/selects/SelectUnbiased.kt | 0 .../common}/src/selects/WhileSelect.kt | 0 .../common}/src/sync/Mutex.kt | 0 .../common}/test/AbstractCoroutineTest.kt | 0 .../common}/test/AsyncLazyTest.kt | 0 .../common}/test/AsyncTest.kt | 0 .../test/AtomicCancellationCommonTest.kt | 0 .../common}/test/AwaitTest.kt | 0 .../CancellableContinuationHandlersTest.kt | 0 .../test/CancellableContinuationTest.kt | 0 .../common}/test/CompletableDeferredTest.kt | 0 .../test/CoroutineExceptionHandlerTest.kt | 0 .../common}/test/CoroutineScopeTest.kt | 0 .../common}/test/CoroutinesTest.kt | 0 .../common}/test/DelayTest.kt | 0 .../test/ExperimentalDispatchModeTest.kt | 0 .../common}/test/FailedJobTest.kt | 0 .../common}/test/JobStatesTest.kt | 0 .../common}/test/JobTest.kt | 0 .../common}/test/LaunchLazyTest.kt | 0 .../common}/test/NonCancellableTest.kt | 0 .../common}/test/ParentCancellationTest.kt | 0 .../common}/test/SupervisorTest.kt | 0 .../common}/test/TestBase.common.kt | 0 .../common}/test/Try.kt | 0 .../common}/test/UnconfinedTest.kt | 0 .../common}/test/UndispatchedResultTest.kt | 0 .../common}/test/WithContextTest.kt | 0 .../common}/test/WithTimeoutOrNullTest.kt | 0 .../common}/test/WithTimeoutTest.kt | 0 .../channels/ArrayBroadcastChannelTest.kt | 0 .../common}/test/channels/ArrayChannelTest.kt | 0 .../test/channels/BasicOperationsTest.kt | 0 .../channels/BroadcastChannelFactoryTest.kt | 0 .../common}/test/channels/BroadcastTest.kt | 0 .../test/channels/ChannelFactoryTest.kt | 0 .../common}/test/channels/ChannelsTest.kt | 0 .../channels/ConflatedBroadcastChannelTest.kt | 0 .../test/channels/ConflatedChannelTest.kt | 0 .../test/channels/LinkedListChannelTest.kt | 0 .../test/channels/ProduceConsumeTest.kt | 0 .../common}/test/channels/ProduceTest.kt | 0 .../test/channels/RendezvousChannelTest.kt | 0 .../test/channels/SendReceiveStressTest.kt | 0 .../test/channels/TestBroadcastChannelKind.kt | 0 .../common}/test/channels/TestChannelKind.kt | 0 .../test/selects/SelectArrayChannelTest.kt | 0 .../common}/test/selects/SelectBiasTest.kt | 0 .../test/selects/SelectBuilderImplTest.kt | 0 .../test/selects/SelectDeferredTest.kt | 0 .../common}/test/selects/SelectJobTest.kt | 0 .../common}/test/selects/SelectMutexTest.kt | 0 .../selects/SelectRendezvousChannelTest.kt | 0 .../common}/test/selects/SelectTimeoutTest.kt | 0 .../common}/test/sync/MutexTest.kt | 0 .../js}/npm/README.md | 0 .../js}/npm/package.json | 0 .../js}/src/CompletionHandler.kt | 0 .../js}/src/CoroutineContext.kt | 0 .../js}/src/CoroutineExceptionHandlerImpl.kt | 0 .../js}/src/Debug.kt | 0 .../js}/src/Dispatchers.kt | 0 .../js}/src/EventLoop.kt | 0 .../js}/src/Exceptions.kt | 0 .../js}/src/JSDispatcher.kt | 0 .../js}/src/Promise.kt | 0 .../js}/src/Runnable.kt | 0 .../js}/src/SchedulerTask.kt | 0 .../js}/src/Window.kt | 0 .../js}/src/internal/ArrayCopy.kt | 0 .../js}/src/internal/Concurrent.kt | 0 .../js}/src/internal/CopyOnWriteList.kt | 0 .../js}/src/internal/LinkedList.kt | 0 .../js}/src/internal/ProbesSupport.kt | 0 .../js}/src/internal/StackTraceRecovery.kt | 0 .../js}/src/internal/Synchronized.kt | 0 .../js}/src/internal/ThreadContext.kt | 0 .../js}/src/internal/ThreadLocal.kt | 0 .../js}/test/MessageQueueTest.kt | 0 .../js}/test/PromiseTest.kt | 0 .../js}/test/TestBase.kt | 0 .../js}/test/internal/ArrayCopyKtTest.kt | 0 .../js}/test/internal/LinkedListTest.kt | 0 .../META-INF/proguard/coroutines.pro | 0 .../jvm}/src/Builders.kt | 0 .../jvm}/src/CommonPool.kt | 0 .../jvm}/src/CompletionHandler.kt | 0 .../jvm}/src/CoroutineContext.kt | 0 .../jvm}/src/CoroutineExceptionHandlerImpl.kt | 0 .../jvm}/src/Debug.kt | 0 .../jvm}/src/DefaultExecutor.kt | 0 .../jvm}/src/Dispatchers.kt | 0 .../jvm}/src/EventLoop.kt | 0 .../jvm}/src/Exceptions.kt | 0 .../jvm}/src/Executors.kt | 0 .../jvm}/src/Future.kt | 0 .../jvm}/src/Runnable.kt | 0 .../jvm}/src/SchedulerTask.kt | 0 .../jvm}/src/ThreadContextElement.kt | 0 .../jvm}/src/ThreadPoolDispatcher.kt | 0 .../jvm}/src/TimeSource.kt | 0 .../jvm}/src/channels/Actor.kt | 0 .../jvm}/src/channels/Channels.kt | 0 .../jvm}/src/channels/TickerChannels.kt | 0 .../jvm}/src/internal/ArrayCopy.kt | 0 .../jvm}/src/internal/Concurrent.kt | 0 .../jvm}/src/internal/ExceptionsConstuctor.kt | 0 .../jvm}/src/internal/LockFreeLinkedList.kt | 0 .../jvm}/src/internal/LockFreeTaskQueue.kt | 0 .../jvm}/src/internal/MainDispatchers.kt | 0 .../jvm}/src/internal/ProbesSupport.kt | 0 .../jvm}/src/internal/StackTraceRecovery.kt | 0 .../jvm}/src/internal/Synchronized.kt | 0 .../jvm}/src/internal/SystemProps.kt | 0 .../jvm}/src/internal/ThreadContext.kt | 0 .../jvm}/src/internal/ThreadLocal.kt | 0 .../jvm}/src/internal/ThreadSafeHeap.kt | 0 .../jvm}/src/scheduling/CoroutineScheduler.kt | 0 .../jvm}/src/scheduling/Dispatcher.kt | 0 .../jvm}/src/scheduling/Tasks.kt | 0 .../jvm}/src/scheduling/WorkQueue.kt | 0 .../jvm}/src/test_/TestCoroutineContext.kt | 0 .../jvm}/test/AsyncJvmTest.kt | 0 .../jvm}/test/AtomicCancellationTest.kt | 0 .../jvm}/test/AwaitJvmTest.kt | 0 .../jvm}/test/AwaitStressTest.kt | 0 .../test/CancellableContinuationJvmTest.kt | 0 .../jvm}/test/CancelledAwaitStressTest.kt | 0 .../jvm}/test/CommonPoolTest.kt | 0 .../test/ContinuationSerializationTest.kt | 0 .../jvm}/test/CoroutinesJvmTest.kt | 0 .../jvm}/test/DebugThreadNameTest.kt | 0 .../jvm}/test/DefaultExecutorStressTest.kt | 0 .../jvm}/test/DelayJvmTest.kt | 0 .../jvm}/test/EventLoopsTest.kt | 0 .../jvm}/test/ExecutorsTest.kt | 0 .../jvm}/test/FailFastOnStartTest.kt | 0 .../jvm}/test/IODispatcherTest.kt | 0 .../jvm}/test/JobActivationStressTest.kt | 0 .../jvm}/test/JobChildStressTest.kt | 0 .../jvm}/test/JobDisposeStressTest.kt | 0 .../jvm}/test/JobHandlersUpgradeStressTest.kt | 0 .../jvm}/test/JobStressTest.kt | 0 .../jvm}/test/JoinStressTest.kt | 0 .../jvm}/test/RunBlockingTest.kt | 0 .../jvm}/test/TestBase.kt | 0 .../jvm}/test/TestBaseTest.kt | 0 .../jvm}/test/TestSecurityManager.kt | 0 .../jvm}/test/ThreadContextElementTest.kt | 0 .../jvm}/test/ThreadLocalTest.kt | 0 .../jvm}/test/Threads.kt | 0 .../test/UnconfinedConcurrentStressTest.kt | 0 .../jvm}/test/VirtualTimeSource.kt | 0 .../jvm}/test/WithDefaultContextTest.kt | 0 .../WithTimeoutChildDipspatchStressTest.kt | 0 .../jvm}/test/WithTimeoutOrNullJvmTest.kt | 0 .../WithTimeoutOrNullThreadDispatchTest.kt | 0 .../test/WithTimeoutThreadDispatchTest.kt | 0 .../jvm}/test/channels/ActorLazyTest.kt | 0 .../jvm}/test/channels/ActorTest.kt | 0 .../test/channels/ArrayChannelStressTest.kt | 0 .../BroadcastChannelMultiReceiveStressTest.kt | 0 .../channels/BroadcastChannelSubStressTest.kt | 0 .../channels/ChannelAtomicCancelStressTest.kt | 0 .../channels/ChannelSendReceiveStressTest.kt | 0 .../jvm}/test/channels/ChannelsConsumeTest.kt | 0 .../jvm}/test/channels/ChannelsJvmTest.kt | 0 ...nflatedBroadcastChannelNotifyStressTest.kt | 0 .../ConflatedChannelCloseStressTest.kt | 0 .../channels/DoubleChannelCloseStressTest.kt | 0 .../test/channels/InvokeOnCloseStressTest.kt | 0 .../test/channels/ProduceConsumeJvmTest.kt | 0 .../channels/RandevouzChannelStressTest.kt | 0 .../test/channels/SendReceiveJvmStressTest.kt | 0 .../test/channels/SimpleSendReceiveJvmTest.kt | 0 .../test/channels/TickerChannelCommonTest.kt | 0 .../jvm}/test/channels/TickerChannelTest.kt | 0 .../CoroutineExceptionHandlerJvmTest.kt | 0 .../jvm}/test/exceptions/Exceptions.kt | 0 .../exceptions/JobBasicCancellationTest.kt | 0 .../exceptions/JobExceptionHandlingTest.kt | 0 .../exceptions/JobExceptionsStressTest.kt | 0 .../exceptions/JobNestedExceptionsTest.kt | 0 .../test/exceptions/ProduceExceptionsTest.kt | 0 .../StackTraceRecoveryNestedChannelsTest.kt | 0 .../StackTraceRecoveryNestedScopesTest.kt | 0 .../StackTraceRecoveryNestedTest.kt | 0 .../test/exceptions/StackTraceRecoveryTest.kt | 0 .../jvm}/test/exceptions/Stacktraces.kt | 0 .../jvm}/test/exceptions/SuppressionTests.kt | 0 .../WithContextCancellationStressTest.kt | 0 .../WithContextExceptionHandlingTest.kt | 0 .../jvm}/test/guide/example-basic-01.kt | 0 .../jvm}/test/guide/example-basic-02.kt | 0 .../jvm}/test/guide/example-basic-02b.kt | 0 .../jvm}/test/guide/example-basic-03.kt | 0 .../jvm}/test/guide/example-basic-03s.kt | 0 .../jvm}/test/guide/example-basic-04.kt | 0 .../jvm}/test/guide/example-basic-05.kt | 0 .../jvm}/test/guide/example-basic-05s.kt | 0 .../jvm}/test/guide/example-basic-06.kt | 0 .../jvm}/test/guide/example-basic-07.kt | 0 .../jvm}/test/guide/example-cancel-01.kt | 0 .../jvm}/test/guide/example-cancel-02.kt | 0 .../jvm}/test/guide/example-cancel-03.kt | 0 .../jvm}/test/guide/example-cancel-04.kt | 0 .../jvm}/test/guide/example-cancel-05.kt | 0 .../jvm}/test/guide/example-cancel-06.kt | 0 .../jvm}/test/guide/example-cancel-07.kt | 0 .../jvm}/test/guide/example-channel-01.kt | 0 .../jvm}/test/guide/example-channel-02.kt | 0 .../jvm}/test/guide/example-channel-03.kt | 0 .../jvm}/test/guide/example-channel-04.kt | 0 .../jvm}/test/guide/example-channel-05.kt | 0 .../jvm}/test/guide/example-channel-06.kt | 0 .../jvm}/test/guide/example-channel-07.kt | 0 .../jvm}/test/guide/example-channel-08.kt | 0 .../jvm}/test/guide/example-channel-09.kt | 0 .../jvm}/test/guide/example-channel-10.kt | 0 .../jvm}/test/guide/example-compose-01.kt | 0 .../jvm}/test/guide/example-compose-02.kt | 0 .../jvm}/test/guide/example-compose-03.kt | 0 .../jvm}/test/guide/example-compose-04.kt | 0 .../jvm}/test/guide/example-compose-05.kt | 0 .../jvm}/test/guide/example-compose-06.kt | 0 .../jvm}/test/guide/example-context-01.kt | 0 .../jvm}/test/guide/example-context-02.kt | 0 .../jvm}/test/guide/example-context-03.kt | 0 .../jvm}/test/guide/example-context-04.kt | 0 .../jvm}/test/guide/example-context-05.kt | 0 .../jvm}/test/guide/example-context-06.kt | 0 .../jvm}/test/guide/example-context-07.kt | 0 .../jvm}/test/guide/example-context-08.kt | 0 .../jvm}/test/guide/example-context-09.kt | 0 .../jvm}/test/guide/example-context-10.kt | 0 .../jvm}/test/guide/example-context-11.kt | 0 .../jvm}/test/guide/example-exceptions-01.kt | 0 .../jvm}/test/guide/example-exceptions-02.kt | 0 .../jvm}/test/guide/example-exceptions-03.kt | 0 .../jvm}/test/guide/example-exceptions-04.kt | 0 .../jvm}/test/guide/example-exceptions-05.kt | 0 .../jvm}/test/guide/example-exceptions-06.kt | 0 .../jvm}/test/guide/example-select-01.kt | 0 .../jvm}/test/guide/example-select-02.kt | 0 .../jvm}/test/guide/example-select-03.kt | 0 .../jvm}/test/guide/example-select-04.kt | 0 .../jvm}/test/guide/example-select-05.kt | 0 .../jvm}/test/guide/example-supervision-01.kt | 0 .../jvm}/test/guide/example-supervision-02.kt | 0 .../jvm}/test/guide/example-supervision-03.kt | 0 .../jvm}/test/guide/example-sync-01.kt | 0 .../jvm}/test/guide/example-sync-01b.kt | 0 .../jvm}/test/guide/example-sync-02.kt | 0 .../jvm}/test/guide/example-sync-03.kt | 0 .../jvm}/test/guide/example-sync-04.kt | 0 .../jvm}/test/guide/example-sync-05.kt | 0 .../jvm}/test/guide/example-sync-06.kt | 0 .../jvm}/test/guide/example-sync-07.kt | 0 .../jvm}/test/guide/test/BasicsGuideTest.kt | 0 .../test/CancellationTimeOutsGuideTest.kt | 0 .../jvm}/test/guide/test/ChannelsGuideTest.kt | 0 .../test/guide/test/ComposingGuideTest.kt | 0 .../test/guide/test/DispatcherGuideTest.kt | 0 .../test/guide/test/ExceptionsGuideTest.kt | 0 .../jvm}/test/guide/test/GuideTest.kt | 0 .../jvm}/test/guide/test/SelectGuideTest.kt | 0 .../test/guide/test/SharedStateGuideTest.kt | 0 .../jvm}/test/guide/test/TestUtil.kt | 0 .../LockFreeLinkedListAtomicStressLFTest.kt | 0 .../LockFreeLinkedListLongStressTest.kt | 0 .../LockFreeLinkedListShortStressTest.kt | 0 .../test/internal/LockFreeLinkedListTest.kt | 0 .../internal/LockFreeTaskQueueStressTest.kt | 0 .../test/internal/LockFreeTaskQueueTest.kt | 0 .../jvm}/test/internal/ThreadSafeHeapTest.kt | 0 .../ChannelIsClosedLinearizabilityTest.kt | 0 .../ChannelLinearizabilityTest.kt | 0 .../jvm}/test/linearizability/LinTesting.kt | 0 .../LockFreeListLinearizabilityTest.kt | 0 .../LockFreeTaskQueueLinearizabilityTest.kt | 0 ...ockingCoroutineDispatcherRaceStressTest.kt | 0 .../BlockingCoroutineDispatcherStressTest.kt | 0 .../BlockingCoroutineDispatcherTest.kt | 0 .../BlockingIOTerminationStressTest.kt | 0 .../scheduling/CoroutineDispatcherTest.kt | 0 .../CoroutineSchedulerCloseStressTest.kt | 0 .../CoroutineSchedulerShrinkTest.kt | 0 .../CoroutineSchedulerStressTest.kt | 0 .../test/scheduling/CoroutineSchedulerTest.kt | 0 .../LimitingCoroutineDispatcherStressTest.kt | 0 .../test/scheduling/LimitingDispatcherTest.kt | 0 .../jvm}/test/scheduling/SchedulerTestBase.kt | 0 .../jvm}/test/scheduling/TestTimeSource.kt | 0 .../test/scheduling/WorkQueueStressTest.kt | 0 .../jvm}/test/scheduling/WorkQueueTest.kt | 0 .../test/selects/SelectChannelStressTest.kt | 0 .../test/selects/SelectMutexStressTest.kt | 0 .../selects/SelectPhilosophersStressTest.kt | 0 .../jvm}/test/sync/MutexStressTest.kt | 0 .../test/test/TestCoroutineContextTest.kt | 0 .../native}/README.md | 0 .../native}/src/Builders.kt | 0 .../native}/src/CompletionHandler.kt | 0 .../native}/src/CoroutineContext.kt | 0 .../src/CoroutineExceptionHandlerImpl.kt | 0 .../native}/src/Debug.kt | 0 .../native}/src/Dispatchers.kt | 0 .../native}/src/EventLoop.kt | 0 .../native}/src/Exceptions.kt | 0 .../native}/src/Runnable.kt | 0 .../native}/src/SchedulerTask.kt | 0 .../native}/src/internal/ArrayCopy.kt | 0 .../native}/src/internal/Concurrent.kt | 0 .../native}/src/internal/CopyOnWriteList.kt | 0 .../native}/src/internal/LinkedList.kt | 0 .../native}/src/internal/LockFreeMPSCQueue.kt | 0 .../native}/src/internal/ProbesSupport.kt | 0 .../src/internal/StackTraceRecovery.kt | 0 .../native}/src/internal/Synchronized.kt | 0 .../native}/src/internal/ThreadContext.kt | 0 .../native}/src/internal/ThreadLocal.kt | 1 - .../native}/src/internal/ThreadSafeHeap.kt | 0 .../native}/test/DelayExceptionTest.kt | 0 .../native}/test/TestBase.kt | 0 .../native}/test/internal/LinkedListTest.kt | 0 .../README.md | 2 +- .../build.gradle | 0 .../src/AgentPremain.kt | 0 .../src/CoroutineState.kt | 0 .../src/DebugProbes.kt | 0 .../src/internal/DebugProbesImpl.kt | 0 .../src/internal/NoOpProbes.kt | 0 .../test/CoroutinesDumpTest.kt | 0 .../test/DebugProbesTest.kt | 0 .../test/SanitizedProbesTest.kt | 0 .../test/ScopedBuildersTest.kt | 0 .../test/StartModeProbesTest.kt | 0 .../test/StracktraceUtils.kt | 0 .../test/ToStringTest.kt | 0 .../README.md | 0 .../build.gradle | 0 .../META-INF/proguard/coroutines.pro | 0 ....coroutines.internal.MainDispatcherFactory | 0 .../src/TestDispatchers.kt | 0 .../src/internal/MainTestDispatcher.kt | 0 .../test/TestDispatchersTest.kt | 0 .../kotlinx-coroutines-reactor/build.gradle | 16 +- settings.gradle | 12 +- {core/stdlib-stubs => stdlib-stubs}/README.md | 0 .../build.gradle | 0 .../src/Continuation.kt | 0 .../src/ContinuationInterceptor.kt | 0 .../src/CoroutineContext.kt | 0 .../src/Result.kt | 0 .../gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 0 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 0 bytes 462 files changed, 715 insertions(+), 600 deletions(-) delete mode 100644 common/README.md delete mode 100644 common/kotlinx-coroutines-core-common/README.md delete mode 100644 common/kotlinx-coroutines-core-common/build.gradle delete mode 100644 core/README.md delete mode 100644 core/kotlinx-coroutines-core/build.gradle delete mode 100644 gradle/atomicfu-common.gradle delete mode 100644 gradle/atomicfu-js.gradle delete mode 100644 gradle/atomicfu-jvm.gradle delete mode 100644 gradle/atomicfu-native.gradle create mode 100644 gradle/compile-js-multiplatform.gradle create mode 100644 gradle/compile-jvm-multiplatform.gradle create mode 100644 gradle/compile-native-multiplatform.gradle delete mode 100644 gradle/compile-native.gradle create mode 100644 gradle/experimental.gradle create mode 100644 gradle/targets.gradle delete mode 100644 js/kotlinx-coroutines-core-js/build.gradle rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core}/README.md (89%) create mode 100644 kotlinx-coroutines-core/build.gradle rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/common}/README.md (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/AbstractCoroutine.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Annotations.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Await.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Builders.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CancellableContinuation.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CancellableContinuationImpl.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CompletableDeferred.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CompletedExceptionally.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CompletionHandler.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CoroutineContext.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CoroutineDispatcher.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CoroutineExceptionHandler.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CoroutineName.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CoroutineScope.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/CoroutineStart.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Debug.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Deferred.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Delay.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Dispatched.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Dispatchers.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/EventLoop.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Exceptions.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Job.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/JobSupport.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/MainCoroutineDispatcher.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/NonCancellable.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/ResumeMode.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Runnable.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/SchedulerTask.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Supervisor.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Timeout.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Unconfined.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/Yield.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/AbstractChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/ArrayBroadcastChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/ArrayChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/Broadcast.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/BroadcastChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/Channel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/ChannelCoroutine.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/Channels.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/ConflatedBroadcastChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/ConflatedChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/LinkedListChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/Produce.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/channels/RendezvousChannel.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/ArrayCopy.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/ArrayQueue.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/Atomic.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/Concurrent.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/LockFreeLinkedList.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/MainDispatcherFactory.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/ProbesSupport.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/Scopes.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/StackTraceRecovery.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/Symbol.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/Synchronized.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/ThreadContext.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/internal/ThreadLocal.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/intrinsics/Cancellable.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/intrinsics/Undispatched.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/selects/Select.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/selects/SelectUnbiased.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/selects/WhileSelect.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/src/sync/Mutex.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/AbstractCoroutineTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/AsyncLazyTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/AsyncTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/AtomicCancellationCommonTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/AwaitTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/CancellableContinuationHandlersTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/CancellableContinuationTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/CompletableDeferredTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/CoroutineExceptionHandlerTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/CoroutineScopeTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/CoroutinesTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/DelayTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/ExperimentalDispatchModeTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/FailedJobTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/JobStatesTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/JobTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/LaunchLazyTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/NonCancellableTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/ParentCancellationTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/SupervisorTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/TestBase.common.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/Try.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/UnconfinedTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/UndispatchedResultTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/WithContextTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/WithTimeoutOrNullTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/WithTimeoutTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ArrayBroadcastChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ArrayChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/BasicOperationsTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/BroadcastChannelFactoryTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/BroadcastTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ChannelFactoryTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ChannelsTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ConflatedBroadcastChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ConflatedChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/LinkedListChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ProduceConsumeTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/ProduceTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/RendezvousChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/SendReceiveStressTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/TestBroadcastChannelKind.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/channels/TestChannelKind.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectArrayChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectBiasTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectBuilderImplTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectDeferredTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectJobTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectMutexTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectRendezvousChannelTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/selects/SelectTimeoutTest.kt (100%) rename {common/kotlinx-coroutines-core-common => kotlinx-coroutines-core/common}/test/sync/MutexTest.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/npm/README.md (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/npm/package.json (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/CompletionHandler.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/CoroutineContext.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/CoroutineExceptionHandlerImpl.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/Debug.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/Dispatchers.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/EventLoop.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/Exceptions.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/JSDispatcher.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/Promise.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/Runnable.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/SchedulerTask.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/Window.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/ArrayCopy.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/Concurrent.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/CopyOnWriteList.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/LinkedList.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/ProbesSupport.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/StackTraceRecovery.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/Synchronized.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/ThreadContext.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/src/internal/ThreadLocal.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/test/MessageQueueTest.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/test/PromiseTest.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/test/TestBase.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/test/internal/ArrayCopyKtTest.kt (100%) rename {js/kotlinx-coroutines-core-js => kotlinx-coroutines-core/js}/test/internal/LinkedListTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/resources/META-INF/proguard/coroutines.pro (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Builders.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/CommonPool.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/CompletionHandler.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/CoroutineContext.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/CoroutineExceptionHandlerImpl.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Debug.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/DefaultExecutor.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Dispatchers.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/EventLoop.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Exceptions.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Executors.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Future.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/Runnable.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/SchedulerTask.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/ThreadContextElement.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/ThreadPoolDispatcher.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/TimeSource.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/channels/Actor.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/channels/Channels.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/channels/TickerChannels.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/ArrayCopy.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/Concurrent.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/ExceptionsConstuctor.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/LockFreeLinkedList.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/LockFreeTaskQueue.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/MainDispatchers.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/ProbesSupport.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/StackTraceRecovery.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/Synchronized.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/SystemProps.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/ThreadContext.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/ThreadLocal.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/internal/ThreadSafeHeap.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/scheduling/CoroutineScheduler.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/scheduling/Dispatcher.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/scheduling/Tasks.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/scheduling/WorkQueue.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/src/test_/TestCoroutineContext.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/AsyncJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/AtomicCancellationTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/AwaitJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/AwaitStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/CancellableContinuationJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/CancelledAwaitStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/CommonPoolTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/ContinuationSerializationTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/CoroutinesJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/DebugThreadNameTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/DefaultExecutorStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/DelayJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/EventLoopsTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/ExecutorsTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/FailFastOnStartTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/IODispatcherTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/JobActivationStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/JobChildStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/JobDisposeStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/JobHandlersUpgradeStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/JobStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/JoinStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/RunBlockingTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/TestBase.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/TestBaseTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/TestSecurityManager.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/ThreadContextElementTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/ThreadLocalTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/Threads.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/UnconfinedConcurrentStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/VirtualTimeSource.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/WithDefaultContextTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/WithTimeoutChildDipspatchStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/WithTimeoutOrNullJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/WithTimeoutOrNullThreadDispatchTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/WithTimeoutThreadDispatchTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ActorLazyTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ActorTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ArrayChannelStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/BroadcastChannelMultiReceiveStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/BroadcastChannelSubStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ChannelAtomicCancelStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ChannelSendReceiveStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ChannelsConsumeTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ChannelsJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ConflatedChannelCloseStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/DoubleChannelCloseStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/InvokeOnCloseStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/ProduceConsumeJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/RandevouzChannelStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/SendReceiveJvmStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/SimpleSendReceiveJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/TickerChannelCommonTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/channels/TickerChannelTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/CoroutineExceptionHandlerJvmTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/Exceptions.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/JobBasicCancellationTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/JobExceptionHandlingTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/JobExceptionsStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/JobNestedExceptionsTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/ProduceExceptionsTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/StackTraceRecoveryNestedScopesTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/StackTraceRecoveryNestedTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/StackTraceRecoveryTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/Stacktraces.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/SuppressionTests.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/WithContextCancellationStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/exceptions/WithContextExceptionHandlingTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-02b.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-03s.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-05s.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-basic-07.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-cancel-07.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-07.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-08.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-09.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-channel-10.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-compose-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-compose-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-compose-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-compose-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-compose-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-compose-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-07.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-08.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-09.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-10.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-context-11.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-exceptions-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-exceptions-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-exceptions-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-exceptions-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-exceptions-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-exceptions-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-select-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-select-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-select-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-select-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-select-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-supervision-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-supervision-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-supervision-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-01.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-01b.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-02.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-03.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-04.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-05.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-06.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/example-sync-07.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/BasicsGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/CancellationTimeOutsGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/ChannelsGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/ComposingGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/DispatcherGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/ExceptionsGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/GuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/SelectGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/SharedStateGuideTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/guide/test/TestUtil.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/LockFreeLinkedListAtomicStressLFTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/LockFreeLinkedListLongStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/LockFreeLinkedListShortStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/LockFreeLinkedListTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/LockFreeTaskQueueStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/LockFreeTaskQueueTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/internal/ThreadSafeHeapTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/linearizability/ChannelIsClosedLinearizabilityTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/linearizability/ChannelLinearizabilityTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/linearizability/LinTesting.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/linearizability/LockFreeListLinearizabilityTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/linearizability/LockFreeTaskQueueLinearizabilityTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/BlockingCoroutineDispatcherRaceStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/BlockingCoroutineDispatcherStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/BlockingCoroutineDispatcherTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/BlockingIOTerminationStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/CoroutineDispatcherTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/CoroutineSchedulerCloseStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/CoroutineSchedulerShrinkTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/CoroutineSchedulerStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/CoroutineSchedulerTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/LimitingCoroutineDispatcherStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/LimitingDispatcherTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/SchedulerTestBase.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/TestTimeSource.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/WorkQueueStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/scheduling/WorkQueueTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/selects/SelectChannelStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/selects/SelectMutexStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/selects/SelectPhilosophersStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/sync/MutexStressTest.kt (100%) rename {core/kotlinx-coroutines-core => kotlinx-coroutines-core/jvm}/test/test/TestCoroutineContextTest.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/README.md (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/Builders.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/CompletionHandler.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/CoroutineContext.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/CoroutineExceptionHandlerImpl.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/Debug.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/Dispatchers.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/EventLoop.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/Exceptions.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/Runnable.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/SchedulerTask.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/ArrayCopy.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/Concurrent.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/CopyOnWriteList.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/LinkedList.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/LockFreeMPSCQueue.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/ProbesSupport.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/StackTraceRecovery.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/Synchronized.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/ThreadContext.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/ThreadLocal.kt (93%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/src/internal/ThreadSafeHeap.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/test/DelayExceptionTest.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/test/TestBase.kt (100%) rename {native/kotlinx-coroutines-core-native => kotlinx-coroutines-core/native}/test/internal/LinkedListTest.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/README.md (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/build.gradle (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/src/AgentPremain.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/src/CoroutineState.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/src/DebugProbes.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/src/internal/DebugProbesImpl.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/src/internal/NoOpProbes.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/CoroutinesDumpTest.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/DebugProbesTest.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/SanitizedProbesTest.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/ScopedBuildersTest.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/StartModeProbesTest.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/StracktraceUtils.kt (100%) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/ToStringTest.kt (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/README.md (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/build.gradle (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/resources/META-INF/proguard/coroutines.pro (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/src/TestDispatchers.kt (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/src/internal/MainTestDispatcher.kt (100%) rename {core/kotlinx-coroutines-test => kotlinx-coroutines-test}/test/TestDispatchersTest.kt (100%) rename {core/stdlib-stubs => stdlib-stubs}/README.md (100%) rename {core/stdlib-stubs => stdlib-stubs}/build.gradle (100%) rename {core/stdlib-stubs => stdlib-stubs}/src/Continuation.kt (100%) rename {core/stdlib-stubs => stdlib-stubs}/src/ContinuationInterceptor.kt (100%) rename {core/stdlib-stubs => stdlib-stubs}/src/CoroutineContext.kt (100%) rename {core/stdlib-stubs => stdlib-stubs}/src/Result.kt (100%) diff --git a/README.md b/README.md index 94417dc071..2cfd4475f5 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ GlobalScope.launch { ## Modules -* [common](common/README.md) — common coroutines across all platforms: +* [core](kotlinx-coroutines-core/README.md) — common coroutines across all platforms: * `launch` and `async` coroutine builders; * `Job` and `Deferred` light-weight future with cancellation support; * `MainScope` for Android and UI applications. @@ -29,15 +29,16 @@ GlobalScope.launch { * `coroutineScope` and `supervisorScope` scope builders; * `SupervisorJob` and `CoroutineExceptionHandler` for supervision of coroutines hierarchies; * `select` expression support and more. -* [core](core/README.md) — Kotlin/JVM implementation of common coroutines with additional features: +* [core/jvm](kotlinx-coroutines-core/jvm/) — additional core features available on Kotlin/JVM: * `Dispatchers.IO` dispatcher for blocking coroutines; * `Executor.asCoroutineDispatcher()` extension, custom thread pools, and more. -* [test](core/README.md) — test utilities for coroutines +* [core/js](kotlinx-coroutines-core/js/) — additional core features available on Kotlin/JS: + * Integration with `Promise`; + * Integration with `Window`. +* [test](kotlinx-coroutines-test/README.md) — test utilities for coroutines * `Dispatchers.setMain` to override `Dispatchers.Main` in tests. -* [debug](core/README.md) — debug utilities for coroutines. +* [debug](kotlinx-coroutines-debug/README.md) — debug utilities for coroutines. * `DebugProbes` API to probe, keep track of, print and dump active coroutines. -* [js](js/README.md) — Kotlin/JS implementation of common coroutines with `Promise` support. -* [native](native/README.md) — Kotlin/Native implementation of common coroutines with `runBlocking` single-threaded event loop. * [reactive](reactive/README.md) — modules that provide builders and iteration support for various reactive streams libraries: * Reactive Streams, RxJava 2.x, and Project Reactor. * [ui](ui/README.md) — modules that provide coroutine dispatchers for various single-threaded UI libraries: diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index 055a393877..416bbe6b1a 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -12,6 +12,10 @@ repositories { jmh.jmhVersion = '1.21' +jmh { + duplicateClassesStrategy DuplicatesStrategy.INCLUDE +} + jmhJar { baseName 'benchmarks' classifier = null @@ -20,8 +24,8 @@ jmhJar { } 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-common') compile project(':kotlinx-coroutines-core') - compile "org.openjdk.jmh:jmh-core:1.21" } + diff --git a/binary-compatibility-validator/resources/api.properties b/binary-compatibility-validator/resources/api.properties index 3c41251efe..e4598617cd 100644 --- a/binary-compatibility-validator/resources/api.properties +++ b/binary-compatibility-validator/resources/api.properties @@ -2,8 +2,8 @@ # Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # -module.roots=core integration native reactive ui test debug +module.roots=/ integration reactive ui module.marker=build.gradle -module.ignore=kotlinx-coroutines-rx-example stdlib-stubs +module.ignore=kotlinx-coroutines-rx-example stdlib-stubs benchmarks knit binary-compatibility-validator site packages.internal=kotlinx.coroutines.internal \ No newline at end of file diff --git a/binary-compatibility-validator/test/PublicApiTest.kt b/binary-compatibility-validator/test/PublicApiTest.kt index 7b8d4a8dec..8c2ca3fd2f 100644 --- a/binary-compatibility-validator/test/PublicApiTest.kt +++ b/binary-compatibility-validator/test/PublicApiTest.kt @@ -60,7 +60,8 @@ class PublicApiTest( it matches regex && !it.endsWith("-sources.jar") && !it.endsWith("-javadoc.jar") - && !it.endsWith("-tests.jar")} } + && !it.endsWith("-tests.jar")} + && !it.name.contains("-metadata-")} return files.singleOrNull() ?: throw Exception("No single file matching $regex in $libsDir:\n${files.joinToString("\n")}") } } diff --git a/build.gradle b/build.gradle index a6e81b7cbb..01b2ec1392 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,26 @@ /* - * 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. */ +import org.jetbrains.kotlin.konan.target.HostManager + +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'] +def internal = sourceless + ['benchmarks', 'knit', 'js-stub', 'stdlib-stubs', 'binary-compatibility-validator'] +// Not published +def unpublished = internal + ['kotlinx-coroutines-rx-example', 'example-frontend-js', 'android-unit-tests'] + +static def platformOf(project) { + def name = project.name + if (name.endsWith("-js")) return "js" + if (name.endsWith("-common") || name.endsWith("-native")) { + throw IllegalStateException("$name platform is not supported") + } + return "jvm" +} buildscript { ext.useKotlinSnapshot = rootProject.properties['kotlinSnapshot'] != null @@ -19,22 +39,10 @@ buildscript { maven { url "https://jetbrains.bintray.com/kotlin-native-dependencies" } maven { url "https://plugins.gradle.org/m2/" } } - configurations.classpath { - resolutionStrategy { - eachDependency { DependencyResolveDetails details -> - if (details.requested.group == 'org.jetbrains.kotlin' && details.requested.name != 'kotlin-native-gradle-plugin') { - // fix version of all dependencies from org.jetbrains.kotlin group - // even when other dependencies require other versions indirectly, - // except kotlin-native, which has its own pre-release versioning - details.useVersion kotlin_version - } - } - } - } + dependencies { classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$artifactory_plugin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version" classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version" classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicFU_version" classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$bintray_version" @@ -48,19 +56,26 @@ buildscript { } allprojects { + // the only place where HostManager could be instantiated + project.ext.hostManager = new HostManager() +} + +allprojects { + apply plugin: 'kotlinx-atomicfu' + def deployVersion = properties['DeployVersion'] if (deployVersion != null) version = deployVersion if (useKotlinSnapshot) { kotlin_version = '1.2-SNAPSHOT' } - def name = it.name + def projectName = it.name repositories { /* * 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 (name == "kotlinx-coroutines-play-services") { + if (projectName == "kotlinx-coroutines-play-services") { google() } jcenter() @@ -69,98 +84,63 @@ allprojects { maven { url "https://kotlin.bintray.com/kotlin-eap" } maven { url "https://kotlin.bintray.com/kotlinx" } } -} + if (projectName == rootModule || projectName == coreModule) return -// Report Kotlin compiler version when building project -println("Using Kotlin compiler version: $org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION") + // Add dependency to core source sets. Core is configured in kx-core/build.gradle + evaluationDependsOn(":$coreModule") + if (sourceless.contains(projectName)) return -// --------------- Configure sub-projects with Kotlin sources --------------- + def platform = platformOf(it) + apply from: rootProject.file("gradle/compile-${platform}.gradle") -def sourceless = ['site'] -static def platformOf(project) { - if (project.name.endsWith("-common")) return "common" - if (project.name.endsWith("-js")) return "js" - if (project.name.endsWith("-native")) return "native" - return "jvm" -} + dependencies { + // See comment below for rationale, it will be replaced with "project" dependency + compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" + compileOnly "org.jetbrains.kotlinx:atomicfu:$atomicFU_version" -static def platformLib(base, platform) { - if (platform == "jvm") return base - return "$base-$platform" -} + // the only way IDEA can resolve test classes + testCompile project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs + } -subprojects { - if (useKotlinSnapshot) { - repositories { - maven { url "https://oss.sonatype.org/content/repositories/snapshots" } - } + tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all { + kotlinOptions.freeCompilerArgs += experimentalAnnotations.collect { "-Xuse-experimental=" + it } + kotlinOptions.freeCompilerArgs += "-progressive" + // Binary compatibility support + kotlinOptions.freeCompilerArgs += ["-Xdump-declarations-to=${buildDir}/visibilities.json"] } +} + +/* + * Hack to trick nmpp plugin: we are renaming artifacts in order to provide backward compatibility for dependencies, + * but publishing plugin does not re-read artifact names for kotlin-jvm projects, so renaming is not applied in pom files + * for JVM-only projects. + * + * We artificially replace "project" dependency with "module" one to have proper names in pom files, but then substitute it + * to have out "project" dependency back. + */ +configure(subprojects.findAll { it.name != coreModule && it.name != rootModule }) { configurations.all { - resolutionStrategy { - eachDependency { DependencyResolveDetails details -> - if (details.requested.group == 'org.jetbrains.kotlin') { - details.useVersion kotlin_version - } - } + resolutionStrategy.dependencySubstitution { + substitute module("org.jetbrains.kotlinx:kotlinx-coroutines-core:$version") with project(':kotlinx-coroutines-core') } } } -configure(subprojects.findAll { !sourceless.contains(it.name) }) { - def platform = platformOf(it) - apply from: rootProject.file("gradle/compile-${platform}.gradle") -} - -// --------------- Configure sub-projects that are part of the library --------------- - -def internal = sourceless + ['benchmarks', 'knit', 'js-stub', 'stdlib-stubs', 'binary-compatibility-validator'] - -// Reconfigure source sets to avoid long "src/main/kotlin/fqn" -configure(subprojects.findAll { !it.name.contains(sourceless) && it.name != "benchmarks" }) { - def projectName = it.name +// Redefine source sets because we are not using 'kotlin/main/fqn' folder convention +configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != "benchmarks" && it.name != coreModule }) { sourceSets { main.kotlin.srcDirs = ['src'] test.kotlin.srcDirs = ['test'] - // todo: do we still need this workaround? - if (!projectName.endsWith("-native")) { - main.resources.srcDirs = ['resources'] - test.resources.srcDirs = ['test-resources'] - } - } -} - -// configure atomicfu -configure(subprojects.findAll { !internal.contains(it.name) }) { - def platform = platformOf(it) - apply from: rootProject.file("gradle/atomicfu-${platform}.gradle") -} - -// configure dependencies on core -configure(subprojects.findAll { !internal.contains(it.name) && it.name != 'kotlinx-coroutines-core-common'}) { - def platform = platformOf(it) - def coroutines_core = platformLib("kotlinx-coroutines-core", platform) + main.resources.srcDirs = ['resources'] + test.resources.srcDirs = ['test-resources'] - if (it.name == coroutines_core) { - dependencies { - expectedBy project(':kotlinx-coroutines-core-common') - } - } else { - dependencies { - compile project(":$coroutines_core") - //the only way IDEA can resolve test classes - testCompile project(":$coroutines_core").sourceSets.test.output - } } } -// --------------- Configure sub-projects that are published --------------- - -def unpublished = internal + ['kotlinx-coroutines-rx-example', 'example-frontend-js', 'android-unit-tests'] - -def core_docs_url = "https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/" -def core_docs_file = "$projectDir/core/kotlinx-coroutines-core/build/dokka/kotlinx-coroutines-core/package-list" +def core_docs_url = "https://kotlin.github.io/kotlinx.coroutines/$coreModule/" +def core_docs_file = "$projectDir/kotlinx-coroutines-core/build/dokka/kotlinx-coroutines-core/package-list" configure(subprojects.findAll { !unpublished.contains(it.name) }) { apply from: rootProject.file('gradle/dokka.gradle') @@ -168,12 +148,8 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } configure(subprojects.findAll { !unpublished.contains(it.name) }) { - def platform = platformOf(it) - def coroutines_core = platformLib("kotlinx-coroutines-core", platform) - - if (it.name != coroutines_core) { - dokka.dependsOn project(":$coroutines_core").dokka - + if (it.name != coreModule) { + dokka.dependsOn project(":$coreModule").dokka tasks.withType(dokka.getClass()) { externalDocumentationLink { url = new URL(core_docs_url) @@ -182,27 +158,16 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } } - if (platform == "jvm") { - dokkaJavadoc.dependsOn project(":$coroutines_core").dokka - // dump declarations from main JVM module for binary-compatibility-validator - compileKotlin { - kotlinOptions.freeCompilerArgs += ["-Xdump-declarations-to=${buildDir}/visibilities.json"] - } + if (platformOf(it) == "jvm") { + dokkaJavadoc.dependsOn project(":$coreModule").dokka } +} - tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all { - kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlin.Experimental", - "-Xuse-experimental=kotlin.experimental.ExperimentalTypeInference", - "-Xuse-experimental=kotlin.ExperimentalMultiplatform", - "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi", - "-Xuse-experimental=kotlinx.coroutines.ObsoleteCoroutinesApi", - "-Xuse-experimental=kotlinx.coroutines.InternalCoroutinesApi", - "-progressive"] - } -} +// Report Kotlin compiler version when building project +println("Using Kotlin compiler version: $org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION") -// main deployment task +// --------------- Configure sub-projects that are published --------------- task deploy(dependsOn: getTasksByName("bintrayUpload", true) + getTasksByName("publishNpm", true)) apply plugin: 'base' diff --git a/common/README.md b/common/README.md deleted file mode 100644 index 07dd61b491..0000000000 --- a/common/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Common coroutines core - -This directory contains modules that provide `expect` declarations for common coroutines support across -various platforms for [mutliplatform Kotlin projects](https://kotlinlang.org/docs/reference/multiplatform.html). -Note, that documentation is currently provided in platform-specific modules only. -Module name below corresponds to the artifact name in Maven/Gradle. - -## Modules - -* [kotlinx-coroutines-core-common](kotlinx-coroutines-core-common/README.md) -- common declarations for coroutine builders and primitives. - diff --git a/common/kotlinx-coroutines-core-common/README.md b/common/kotlinx-coroutines-core-common/README.md deleted file mode 100644 index 7ff030e799..0000000000 --- a/common/kotlinx-coroutines-core-common/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Module kotlinx-coroutines-core-js - -Common primitives to work with coroutines in -[multiplatform Kotlin projects](https://kotlinlang.org/docs/reference/multiplatform.html). - -Documentation is provided in platform-specific modules: -* [kotlinx-coroutines-core](../../core/kotlinx-coroutines-core/README.md) for Kotlin/JVM. -* [kotlinx-coroutines-core-js](../../js/kotlinx-coroutines-core-js/README.md) for Kotlin/JS. -* [kotlinx-coroutines-core-native](../../native/kotlinx-coroutines-core-native/README.md) for Kotlin/Native. diff --git a/common/kotlinx-coroutines-core-common/build.gradle b/common/kotlinx-coroutines-core-common/build.gradle deleted file mode 100644 index 3b17101f53..0000000000 --- a/common/kotlinx-coroutines-core-common/build.gradle +++ /dev/null @@ -1,4 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - diff --git a/core/README.md b/core/README.md deleted file mode 100644 index 5719a8628b..0000000000 --- a/core/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Coroutines core for Kotlin/JVM - -This directory contains modules that provide core coroutines support on Kotlin/JVM. -Module name below corresponds to the artifact name in Maven/Gradle. - -## Modules - -* [kotlinx-coroutines-core](kotlinx-coroutines-core/README.md) — core coroutine builders and synchronization primitives. -* [kotlinx-coroutines-debug](kotlinx-coroutines-debug/README.md) — coroutines debug utilities. -* [kotlinx-coroutines-test](kotlinx-coroutines-test/README.md) — coroutines test utilities. - diff --git a/core/kotlinx-coroutines-core/build.gradle b/core/kotlinx-coroutines-core/build.gradle deleted file mode 100644 index 7e3c0bf47e..0000000000 --- a/core/kotlinx-coroutines-core/build.gradle +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -dependencies { - testCompile "com.devexperts.lincheck:lincheck:$lincheck_version" - testCompile "com.esotericsoftware:kryo:4.0.0" -} - -task checkJdk16() { - // only fail w/o JDK_16 when actually trying to compile, not during project setup phase - doLast { - if (!System.env.JDK_16) { - throw new GradleException("JDK_16 environment variable is not defined. " + - "Can't build against JDK 1.6 runtime and run JDK 1.6 compatibility tests. " + - "Please ensure JDK 1.6 is installed and that JDK_16 points to it.") - } - } -} - -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { - kotlinOptions.jdkHome = System.env.JDK_16 - // only fail when actually trying to compile, not during project setup phase - dependsOn(checkJdk16) -} - -tasks.withType(Test) { - minHeapSize = '1g' - maxHeapSize = '1g' - enableAssertions = true - systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager' -} - -test { - exclude '**/*LFTest.*' - systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test -} - -task lockFreedomTest(type: Test, dependsOn: testClasses) { - classpath = files(configurations.testRuntime, - sourceSets.main.output.classesDirs, //clear, untransformed classes - sourceSets.test.output.classesDirs) - include '**/*LFTest.*' -} - -task jdk16Test(type: Test, dependsOn: [testClasses, checkJdk16]) { - executable = "$System.env.JDK_16/bin/java" - exclude '**/*LinearizabilityTest.*' - exclude '**/*LFTest.*' - exclude '**/exceptions/**' - exclude '**/ExceptionsGuideTest.*' -} - -// Run these tests only during nightly stress test -jdk16Test.onlyIf { project.properties['stressTest'] != null } - -// Always run those tests -task moreTest(dependsOn: [lockFreedomTest, jdk16Test]) - -build.dependsOn moreTest - -task testsJar(type: Jar, dependsOn: testClasses) { - classifier = 'tests' - from sourceSets.test.output -} - -artifacts { - archives testsJar -} diff --git a/docs/basics.md b/docs/basics.md index 1f772e67fd..6c077874ea 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -6,8 +6,8 @@ // This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.$$1$$2 --> - - + @@ -386,7 +386,7 @@ fun main() = runBlocking { -> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-07.kt) +> You can get full code [here](../kotlinx-coroutines-core/jvm/test/guide/example-basic-07.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 571b80ce23..742eea0a06 100644 --- a/docs/cancellation-and-timeouts.md +++ b/docs/cancellation-and-timeouts.md @@ -6,8 +6,8 @@ // This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit. package kotlinx.coroutines.guide.$$1$$2 --> - - + - - + - - + - - + - - + - - + - - + [launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html @@ -66,6 +95,7 @@ helper function. [NonCancellable] job object is provided to suppress cancellatio [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html [async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html [Deferred]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html +[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html [Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html [Dispatchers.Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-unconfined.html @@ -106,4 +136,5 @@ helper function. [NonCancellable] job object is provided to suppress cancellatio [kotlinx.coroutines.selects.select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/select.html [kotlinx.coroutines.selects.SelectBuilder.onTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.selects/-select-builder/on-timeout.html + diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle new file mode 100644 index 0000000000..fd52c4237e --- /dev/null +++ b/kotlinx-coroutines-core/build.gradle @@ -0,0 +1,103 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +apply plugin: 'kotlin-multiplatform' +apply from: rootProject.file("gradle/targets.gradle") +apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle") +apply from: rootProject.file("gradle/compile-common.gradle") +apply from: rootProject.file("gradle/compile-js-multiplatform.gradle") +apply from: rootProject.file("gradle/compile-native-multiplatform.gradle") +apply from: rootProject.file('gradle/publish-npm-js.gradle') + +/* + * All platform plugins and configuration magic happens here instead of build.gradle + * because JMV-only projects depend on core, thus core should always be initialized before configuration. + */ +kotlin { + configure(sourceSets) { + def srcDir = name.endsWith('Main') ? 'src' : 'test' + def platform = name[0..-5] + kotlin.srcDir "$platform/$srcDir" + languageSettings { + progressiveMode = true + experimentalAnnotations.each { useExperimentalAnnotation(it) } + } + } + + configure(targets) { + def targetName = it.name + compilations.all { compilation -> + def compileTask = tasks.getByName(compilation.compileKotlinTaskName) + // binary compatibility support + if (targetName.contains("jvm") && compilation.compilationName == "main") { + compileTask.kotlinOptions.freeCompilerArgs += ["-Xdump-declarations-to=${buildDir}/visibilities.json"] + } + } + } +} + +kotlin.sourceSets { + jvmTest.dependencies { + api "com.devexperts.lincheck:lincheck:$lincheck_version" + api "com.esotericsoftware:kryo:4.0.0" + } +} + +task checkJdk16() { + // only fail w/o JDK_16 when actually trying to compile, not during project setup phase + doLast { + if (!System.env.JDK_16) { + throw new GradleException("JDK_16 environment variable is not defined. " + + "Can't build against JDK 1.6 runtime and run JDK 1.6 compatibility tests. " + + "Please ensure JDK 1.6 is installed and that JDK_16 points to it.") + } + } +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + kotlinOptions.jdkHome = System.env.JDK_16 + // only fail when actually trying to compile, not during project setup phase + dependsOn(checkJdk16) +} + +jvmTest { + minHeapSize = '1g' + maxHeapSize = '1g' + enableAssertions = true + systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager' + exclude '**/*LFTest.*' + systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test +} + +task lockFreedomTest(type: Test, dependsOn: compileTestKotlinJvm) { + classpath = files { jvmTest.classpath } + testClassesDirs = files { jvmTest.testClassesDirs } + include '**/*LFTest.*' +} + +task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) { + classpath = files { jvmTest.classpath } + testClassesDirs = files { jvmTest.testClassesDirs } + executable = "$System.env.JDK_16/bin/java" + exclude '**/*LinearizabilityTest.*' + exclude '**/*LFTest.*' + exclude '**/exceptions/**' + exclude '**/ExceptionsGuideTest.*' +} + +// Run these tests only during nightly stress test +jdk16Test.onlyIf { project.properties['stressTest'] != null } + +// Always run those tests +task moreTest(dependsOn: [lockFreedomTest, jdk16Test]) +build.dependsOn moreTest + +task testsJar(type: Jar, dependsOn: jvmTestClasses) { + classifier = 'tests' + from compileTestKotlinJvm.destinationDir +} + +artifacts { + archives testsJar +} diff --git a/core/kotlinx-coroutines-core/README.md b/kotlinx-coroutines-core/common/README.md similarity index 100% rename from core/kotlinx-coroutines-core/README.md rename to kotlinx-coroutines-core/common/README.md diff --git a/common/kotlinx-coroutines-core-common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/AbstractCoroutine.kt rename to kotlinx-coroutines-core/common/src/AbstractCoroutine.kt diff --git a/common/kotlinx-coroutines-core-common/src/Annotations.kt b/kotlinx-coroutines-core/common/src/Annotations.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Annotations.kt rename to kotlinx-coroutines-core/common/src/Annotations.kt diff --git a/common/kotlinx-coroutines-core-common/src/Await.kt b/kotlinx-coroutines-core/common/src/Await.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Await.kt rename to kotlinx-coroutines-core/common/src/Await.kt diff --git a/common/kotlinx-coroutines-core-common/src/Builders.common.kt b/kotlinx-coroutines-core/common/src/Builders.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Builders.common.kt rename to kotlinx-coroutines-core/common/src/Builders.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/CancellableContinuation.kt b/kotlinx-coroutines-core/common/src/CancellableContinuation.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CancellableContinuation.kt rename to kotlinx-coroutines-core/common/src/CancellableContinuation.kt diff --git a/common/kotlinx-coroutines-core-common/src/CancellableContinuationImpl.kt b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CancellableContinuationImpl.kt rename to kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt diff --git a/common/kotlinx-coroutines-core-common/src/CompletableDeferred.kt b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CompletableDeferred.kt rename to kotlinx-coroutines-core/common/src/CompletableDeferred.kt diff --git a/common/kotlinx-coroutines-core-common/src/CompletedExceptionally.kt b/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CompletedExceptionally.kt rename to kotlinx-coroutines-core/common/src/CompletedExceptionally.kt diff --git a/common/kotlinx-coroutines-core-common/src/CompletionHandler.common.kt b/kotlinx-coroutines-core/common/src/CompletionHandler.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CompletionHandler.common.kt rename to kotlinx-coroutines-core/common/src/CompletionHandler.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineContext.common.kt b/kotlinx-coroutines-core/common/src/CoroutineContext.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CoroutineContext.common.kt rename to kotlinx-coroutines-core/common/src/CoroutineContext.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CoroutineDispatcher.kt rename to kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineExceptionHandler.kt b/kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CoroutineExceptionHandler.kt rename to kotlinx-coroutines-core/common/src/CoroutineExceptionHandler.kt diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineName.kt b/kotlinx-coroutines-core/common/src/CoroutineName.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CoroutineName.kt rename to kotlinx-coroutines-core/common/src/CoroutineName.kt diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt b/kotlinx-coroutines-core/common/src/CoroutineScope.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CoroutineScope.kt rename to kotlinx-coroutines-core/common/src/CoroutineScope.kt diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineStart.kt b/kotlinx-coroutines-core/common/src/CoroutineStart.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/CoroutineStart.kt rename to kotlinx-coroutines-core/common/src/CoroutineStart.kt diff --git a/common/kotlinx-coroutines-core-common/src/Debug.common.kt b/kotlinx-coroutines-core/common/src/Debug.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Debug.common.kt rename to kotlinx-coroutines-core/common/src/Debug.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/Deferred.kt b/kotlinx-coroutines-core/common/src/Deferred.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Deferred.kt rename to kotlinx-coroutines-core/common/src/Deferred.kt diff --git a/common/kotlinx-coroutines-core-common/src/Delay.kt b/kotlinx-coroutines-core/common/src/Delay.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Delay.kt rename to kotlinx-coroutines-core/common/src/Delay.kt diff --git a/common/kotlinx-coroutines-core-common/src/Dispatched.kt b/kotlinx-coroutines-core/common/src/Dispatched.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Dispatched.kt rename to kotlinx-coroutines-core/common/src/Dispatched.kt diff --git a/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt b/kotlinx-coroutines-core/common/src/Dispatchers.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt rename to kotlinx-coroutines-core/common/src/Dispatchers.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/EventLoop.common.kt b/kotlinx-coroutines-core/common/src/EventLoop.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/EventLoop.common.kt rename to kotlinx-coroutines-core/common/src/EventLoop.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/Exceptions.common.kt b/kotlinx-coroutines-core/common/src/Exceptions.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Exceptions.common.kt rename to kotlinx-coroutines-core/common/src/Exceptions.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Job.kt rename to kotlinx-coroutines-core/common/src/Job.kt diff --git a/common/kotlinx-coroutines-core-common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/JobSupport.kt rename to kotlinx-coroutines-core/common/src/JobSupport.kt diff --git a/common/kotlinx-coroutines-core-common/src/MainCoroutineDispatcher.kt b/kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/MainCoroutineDispatcher.kt rename to kotlinx-coroutines-core/common/src/MainCoroutineDispatcher.kt diff --git a/common/kotlinx-coroutines-core-common/src/NonCancellable.kt b/kotlinx-coroutines-core/common/src/NonCancellable.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/NonCancellable.kt rename to kotlinx-coroutines-core/common/src/NonCancellable.kt diff --git a/common/kotlinx-coroutines-core-common/src/ResumeMode.kt b/kotlinx-coroutines-core/common/src/ResumeMode.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/ResumeMode.kt rename to kotlinx-coroutines-core/common/src/ResumeMode.kt diff --git a/common/kotlinx-coroutines-core-common/src/Runnable.common.kt b/kotlinx-coroutines-core/common/src/Runnable.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Runnable.common.kt rename to kotlinx-coroutines-core/common/src/Runnable.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/SchedulerTask.common.kt b/kotlinx-coroutines-core/common/src/SchedulerTask.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/SchedulerTask.common.kt rename to kotlinx-coroutines-core/common/src/SchedulerTask.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/Supervisor.kt b/kotlinx-coroutines-core/common/src/Supervisor.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Supervisor.kt rename to kotlinx-coroutines-core/common/src/Supervisor.kt diff --git a/common/kotlinx-coroutines-core-common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Timeout.kt rename to kotlinx-coroutines-core/common/src/Timeout.kt diff --git a/common/kotlinx-coroutines-core-common/src/Unconfined.kt b/kotlinx-coroutines-core/common/src/Unconfined.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Unconfined.kt rename to kotlinx-coroutines-core/common/src/Unconfined.kt diff --git a/common/kotlinx-coroutines-core-common/src/Yield.kt b/kotlinx-coroutines-core/common/src/Yield.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/Yield.kt rename to kotlinx-coroutines-core/common/src/Yield.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/AbstractChannel.kt rename to kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/ArrayBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/ArrayBroadcastChannel.kt rename to kotlinx-coroutines-core/common/src/channels/ArrayBroadcastChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/ArrayChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/ArrayChannel.kt rename to kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/Broadcast.kt b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/Broadcast.kt rename to kotlinx-coroutines-core/common/src/channels/Broadcast.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/BroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/BroadcastChannel.kt rename to kotlinx-coroutines-core/common/src/channels/BroadcastChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/Channel.kt rename to kotlinx-coroutines-core/common/src/channels/Channel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/ChannelCoroutine.kt b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/ChannelCoroutine.kt rename to kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/Channels.common.kt b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/Channels.common.kt rename to kotlinx-coroutines-core/common/src/channels/Channels.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/ConflatedBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/ConflatedBroadcastChannel.kt rename to kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/ConflatedChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/ConflatedChannel.kt rename to kotlinx-coroutines-core/common/src/channels/ConflatedChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/LinkedListChannel.kt b/kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/LinkedListChannel.kt rename to kotlinx-coroutines-core/common/src/channels/LinkedListChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/Produce.kt rename to kotlinx-coroutines-core/common/src/channels/Produce.kt diff --git a/common/kotlinx-coroutines-core-common/src/channels/RendezvousChannel.kt b/kotlinx-coroutines-core/common/src/channels/RendezvousChannel.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/channels/RendezvousChannel.kt rename to kotlinx-coroutines-core/common/src/channels/RendezvousChannel.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/ArrayCopy.common.kt b/kotlinx-coroutines-core/common/src/internal/ArrayCopy.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/ArrayCopy.common.kt rename to kotlinx-coroutines-core/common/src/internal/ArrayCopy.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/ArrayQueue.kt b/kotlinx-coroutines-core/common/src/internal/ArrayQueue.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/ArrayQueue.kt rename to kotlinx-coroutines-core/common/src/internal/ArrayQueue.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/Atomic.kt b/kotlinx-coroutines-core/common/src/internal/Atomic.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/Atomic.kt rename to kotlinx-coroutines-core/common/src/internal/Atomic.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/Concurrent.common.kt b/kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/Concurrent.common.kt rename to kotlinx-coroutines-core/common/src/internal/Concurrent.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/LockFreeLinkedList.common.kt b/kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/LockFreeLinkedList.common.kt rename to kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/MainDispatcherFactory.kt b/kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/MainDispatcherFactory.kt rename to kotlinx-coroutines-core/common/src/internal/MainDispatcherFactory.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/ProbesSupport.common.kt b/kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/ProbesSupport.common.kt rename to kotlinx-coroutines-core/common/src/internal/ProbesSupport.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/Scopes.kt b/kotlinx-coroutines-core/common/src/internal/Scopes.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/Scopes.kt rename to kotlinx-coroutines-core/common/src/internal/Scopes.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/StackTraceRecovery.common.kt b/kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/StackTraceRecovery.common.kt rename to kotlinx-coroutines-core/common/src/internal/StackTraceRecovery.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/Symbol.kt b/kotlinx-coroutines-core/common/src/internal/Symbol.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/Symbol.kt rename to kotlinx-coroutines-core/common/src/internal/Symbol.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/Synchronized.common.kt b/kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/Synchronized.common.kt rename to kotlinx-coroutines-core/common/src/internal/Synchronized.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/ThreadContext.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/ThreadContext.common.kt rename to kotlinx-coroutines-core/common/src/internal/ThreadContext.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/internal/ThreadLocal.common.kt b/kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/internal/ThreadLocal.common.kt rename to kotlinx-coroutines-core/common/src/internal/ThreadLocal.common.kt diff --git a/common/kotlinx-coroutines-core-common/src/intrinsics/Cancellable.kt b/kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/intrinsics/Cancellable.kt rename to kotlinx-coroutines-core/common/src/intrinsics/Cancellable.kt diff --git a/common/kotlinx-coroutines-core-common/src/intrinsics/Undispatched.kt b/kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/intrinsics/Undispatched.kt rename to kotlinx-coroutines-core/common/src/intrinsics/Undispatched.kt diff --git a/common/kotlinx-coroutines-core-common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/selects/Select.kt rename to kotlinx-coroutines-core/common/src/selects/Select.kt diff --git a/common/kotlinx-coroutines-core-common/src/selects/SelectUnbiased.kt b/kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/selects/SelectUnbiased.kt rename to kotlinx-coroutines-core/common/src/selects/SelectUnbiased.kt diff --git a/common/kotlinx-coroutines-core-common/src/selects/WhileSelect.kt b/kotlinx-coroutines-core/common/src/selects/WhileSelect.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/selects/WhileSelect.kt rename to kotlinx-coroutines-core/common/src/selects/WhileSelect.kt diff --git a/common/kotlinx-coroutines-core-common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/src/sync/Mutex.kt rename to kotlinx-coroutines-core/common/src/sync/Mutex.kt diff --git a/common/kotlinx-coroutines-core-common/test/AbstractCoroutineTest.kt b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/AbstractCoroutineTest.kt rename to kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/AsyncLazyTest.kt b/kotlinx-coroutines-core/common/test/AsyncLazyTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/AsyncLazyTest.kt rename to kotlinx-coroutines-core/common/test/AsyncLazyTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/AsyncTest.kt b/kotlinx-coroutines-core/common/test/AsyncTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/AsyncTest.kt rename to kotlinx-coroutines-core/common/test/AsyncTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/AtomicCancellationCommonTest.kt b/kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/AtomicCancellationCommonTest.kt rename to kotlinx-coroutines-core/common/test/AtomicCancellationCommonTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/AwaitTest.kt b/kotlinx-coroutines-core/common/test/AwaitTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/AwaitTest.kt rename to kotlinx-coroutines-core/common/test/AwaitTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/CancellableContinuationHandlersTest.kt b/kotlinx-coroutines-core/common/test/CancellableContinuationHandlersTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/CancellableContinuationHandlersTest.kt rename to kotlinx-coroutines-core/common/test/CancellableContinuationHandlersTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/CancellableContinuationTest.kt b/kotlinx-coroutines-core/common/test/CancellableContinuationTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/CancellableContinuationTest.kt rename to kotlinx-coroutines-core/common/test/CancellableContinuationTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/CompletableDeferredTest.kt b/kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/CompletableDeferredTest.kt rename to kotlinx-coroutines-core/common/test/CompletableDeferredTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/CoroutineExceptionHandlerTest.kt b/kotlinx-coroutines-core/common/test/CoroutineExceptionHandlerTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/CoroutineExceptionHandlerTest.kt rename to kotlinx-coroutines-core/common/test/CoroutineExceptionHandlerTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt b/kotlinx-coroutines-core/common/test/CoroutineScopeTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt rename to kotlinx-coroutines-core/common/test/CoroutineScopeTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt b/kotlinx-coroutines-core/common/test/CoroutinesTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt rename to kotlinx-coroutines-core/common/test/CoroutinesTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/DelayTest.kt b/kotlinx-coroutines-core/common/test/DelayTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/DelayTest.kt rename to kotlinx-coroutines-core/common/test/DelayTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/ExperimentalDispatchModeTest.kt b/kotlinx-coroutines-core/common/test/ExperimentalDispatchModeTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/ExperimentalDispatchModeTest.kt rename to kotlinx-coroutines-core/common/test/ExperimentalDispatchModeTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/FailedJobTest.kt b/kotlinx-coroutines-core/common/test/FailedJobTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/FailedJobTest.kt rename to kotlinx-coroutines-core/common/test/FailedJobTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/JobStatesTest.kt b/kotlinx-coroutines-core/common/test/JobStatesTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/JobStatesTest.kt rename to kotlinx-coroutines-core/common/test/JobStatesTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/JobTest.kt b/kotlinx-coroutines-core/common/test/JobTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/JobTest.kt rename to kotlinx-coroutines-core/common/test/JobTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/LaunchLazyTest.kt b/kotlinx-coroutines-core/common/test/LaunchLazyTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/LaunchLazyTest.kt rename to kotlinx-coroutines-core/common/test/LaunchLazyTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/NonCancellableTest.kt b/kotlinx-coroutines-core/common/test/NonCancellableTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/NonCancellableTest.kt rename to kotlinx-coroutines-core/common/test/NonCancellableTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/ParentCancellationTest.kt b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/ParentCancellationTest.kt rename to kotlinx-coroutines-core/common/test/ParentCancellationTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/SupervisorTest.kt b/kotlinx-coroutines-core/common/test/SupervisorTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/SupervisorTest.kt rename to kotlinx-coroutines-core/common/test/SupervisorTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/TestBase.common.kt b/kotlinx-coroutines-core/common/test/TestBase.common.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/TestBase.common.kt rename to kotlinx-coroutines-core/common/test/TestBase.common.kt diff --git a/common/kotlinx-coroutines-core-common/test/Try.kt b/kotlinx-coroutines-core/common/test/Try.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/Try.kt rename to kotlinx-coroutines-core/common/test/Try.kt diff --git a/common/kotlinx-coroutines-core-common/test/UnconfinedTest.kt b/kotlinx-coroutines-core/common/test/UnconfinedTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/UnconfinedTest.kt rename to kotlinx-coroutines-core/common/test/UnconfinedTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/UndispatchedResultTest.kt b/kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/UndispatchedResultTest.kt rename to kotlinx-coroutines-core/common/test/UndispatchedResultTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/WithContextTest.kt b/kotlinx-coroutines-core/common/test/WithContextTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/WithContextTest.kt rename to kotlinx-coroutines-core/common/test/WithContextTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/WithTimeoutOrNullTest.kt rename to kotlinx-coroutines-core/common/test/WithTimeoutOrNullTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/WithTimeoutTest.kt b/kotlinx-coroutines-core/common/test/WithTimeoutTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/WithTimeoutTest.kt rename to kotlinx-coroutines-core/common/test/WithTimeoutTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ArrayBroadcastChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ArrayBroadcastChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ArrayBroadcastChannelTest.kt rename to kotlinx-coroutines-core/common/test/channels/ArrayBroadcastChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ArrayChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ArrayChannelTest.kt rename to kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/BasicOperationsTest.kt b/kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/BasicOperationsTest.kt rename to kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/BroadcastChannelFactoryTest.kt b/kotlinx-coroutines-core/common/test/channels/BroadcastChannelFactoryTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/BroadcastChannelFactoryTest.kt rename to kotlinx-coroutines-core/common/test/channels/BroadcastChannelFactoryTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/BroadcastTest.kt b/kotlinx-coroutines-core/common/test/channels/BroadcastTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/BroadcastTest.kt rename to kotlinx-coroutines-core/common/test/channels/BroadcastTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ChannelFactoryTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelFactoryTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ChannelFactoryTest.kt rename to kotlinx-coroutines-core/common/test/channels/ChannelFactoryTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ChannelsTest.kt b/kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ChannelsTest.kt rename to kotlinx-coroutines-core/common/test/channels/ChannelsTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ConflatedBroadcastChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ConflatedBroadcastChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ConflatedBroadcastChannelTest.kt rename to kotlinx-coroutines-core/common/test/channels/ConflatedBroadcastChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ConflatedChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ConflatedChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ConflatedChannelTest.kt rename to kotlinx-coroutines-core/common/test/channels/ConflatedChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/LinkedListChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/LinkedListChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/LinkedListChannelTest.kt rename to kotlinx-coroutines-core/common/test/channels/LinkedListChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ProduceConsumeTest.kt b/kotlinx-coroutines-core/common/test/channels/ProduceConsumeTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ProduceConsumeTest.kt rename to kotlinx-coroutines-core/common/test/channels/ProduceConsumeTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt b/kotlinx-coroutines-core/common/test/channels/ProduceTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt rename to kotlinx-coroutines-core/common/test/channels/ProduceTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/RendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/RendezvousChannelTest.kt rename to kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/SendReceiveStressTest.kt b/kotlinx-coroutines-core/common/test/channels/SendReceiveStressTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/SendReceiveStressTest.kt rename to kotlinx-coroutines-core/common/test/channels/SendReceiveStressTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/TestBroadcastChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestBroadcastChannelKind.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/TestBroadcastChannelKind.kt rename to kotlinx-coroutines-core/common/test/channels/TestBroadcastChannelKind.kt diff --git a/common/kotlinx-coroutines-core-common/test/channels/TestChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/channels/TestChannelKind.kt rename to kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectArrayChannelTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectArrayChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectArrayChannelTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectArrayChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectBiasTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectBiasTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectBiasTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectBiasTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectBuilderImplTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectBuilderImplTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectBuilderImplTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectBuilderImplTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectDeferredTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectDeferredTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectDeferredTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectDeferredTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectJobTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectJobTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectJobTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectJobTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectMutexTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectMutexTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectMutexTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectMutexTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectRendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectRendezvousChannelTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectRendezvousChannelTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectRendezvousChannelTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectTimeoutTest.kt b/kotlinx-coroutines-core/common/test/selects/SelectTimeoutTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/selects/SelectTimeoutTest.kt rename to kotlinx-coroutines-core/common/test/selects/SelectTimeoutTest.kt diff --git a/common/kotlinx-coroutines-core-common/test/sync/MutexTest.kt b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt similarity index 100% rename from common/kotlinx-coroutines-core-common/test/sync/MutexTest.kt rename to kotlinx-coroutines-core/common/test/sync/MutexTest.kt diff --git a/js/kotlinx-coroutines-core-js/npm/README.md b/kotlinx-coroutines-core/js/npm/README.md similarity index 100% rename from js/kotlinx-coroutines-core-js/npm/README.md rename to kotlinx-coroutines-core/js/npm/README.md diff --git a/js/kotlinx-coroutines-core-js/npm/package.json b/kotlinx-coroutines-core/js/npm/package.json similarity index 100% rename from js/kotlinx-coroutines-core-js/npm/package.json rename to kotlinx-coroutines-core/js/npm/package.json diff --git a/js/kotlinx-coroutines-core-js/src/CompletionHandler.kt b/kotlinx-coroutines-core/js/src/CompletionHandler.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/CompletionHandler.kt rename to kotlinx-coroutines-core/js/src/CompletionHandler.kt diff --git a/js/kotlinx-coroutines-core-js/src/CoroutineContext.kt b/kotlinx-coroutines-core/js/src/CoroutineContext.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/CoroutineContext.kt rename to kotlinx-coroutines-core/js/src/CoroutineContext.kt diff --git a/js/kotlinx-coroutines-core-js/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/CoroutineExceptionHandlerImpl.kt rename to kotlinx-coroutines-core/js/src/CoroutineExceptionHandlerImpl.kt diff --git a/js/kotlinx-coroutines-core-js/src/Debug.kt b/kotlinx-coroutines-core/js/src/Debug.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/Debug.kt rename to kotlinx-coroutines-core/js/src/Debug.kt diff --git a/js/kotlinx-coroutines-core-js/src/Dispatchers.kt b/kotlinx-coroutines-core/js/src/Dispatchers.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/Dispatchers.kt rename to kotlinx-coroutines-core/js/src/Dispatchers.kt diff --git a/js/kotlinx-coroutines-core-js/src/EventLoop.kt b/kotlinx-coroutines-core/js/src/EventLoop.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/EventLoop.kt rename to kotlinx-coroutines-core/js/src/EventLoop.kt diff --git a/js/kotlinx-coroutines-core-js/src/Exceptions.kt b/kotlinx-coroutines-core/js/src/Exceptions.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/Exceptions.kt rename to kotlinx-coroutines-core/js/src/Exceptions.kt diff --git a/js/kotlinx-coroutines-core-js/src/JSDispatcher.kt b/kotlinx-coroutines-core/js/src/JSDispatcher.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/JSDispatcher.kt rename to kotlinx-coroutines-core/js/src/JSDispatcher.kt diff --git a/js/kotlinx-coroutines-core-js/src/Promise.kt b/kotlinx-coroutines-core/js/src/Promise.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/Promise.kt rename to kotlinx-coroutines-core/js/src/Promise.kt diff --git a/js/kotlinx-coroutines-core-js/src/Runnable.kt b/kotlinx-coroutines-core/js/src/Runnable.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/Runnable.kt rename to kotlinx-coroutines-core/js/src/Runnable.kt diff --git a/js/kotlinx-coroutines-core-js/src/SchedulerTask.kt b/kotlinx-coroutines-core/js/src/SchedulerTask.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/SchedulerTask.kt rename to kotlinx-coroutines-core/js/src/SchedulerTask.kt diff --git a/js/kotlinx-coroutines-core-js/src/Window.kt b/kotlinx-coroutines-core/js/src/Window.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/Window.kt rename to kotlinx-coroutines-core/js/src/Window.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/ArrayCopy.kt b/kotlinx-coroutines-core/js/src/internal/ArrayCopy.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/ArrayCopy.kt rename to kotlinx-coroutines-core/js/src/internal/ArrayCopy.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/Concurrent.kt b/kotlinx-coroutines-core/js/src/internal/Concurrent.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/Concurrent.kt rename to kotlinx-coroutines-core/js/src/internal/Concurrent.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/CopyOnWriteList.kt rename to kotlinx-coroutines-core/js/src/internal/CopyOnWriteList.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/LinkedList.kt b/kotlinx-coroutines-core/js/src/internal/LinkedList.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/LinkedList.kt rename to kotlinx-coroutines-core/js/src/internal/LinkedList.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/ProbesSupport.kt rename to kotlinx-coroutines-core/js/src/internal/ProbesSupport.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/StackTraceRecovery.kt rename to kotlinx-coroutines-core/js/src/internal/StackTraceRecovery.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/Synchronized.kt b/kotlinx-coroutines-core/js/src/internal/Synchronized.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/Synchronized.kt rename to kotlinx-coroutines-core/js/src/internal/Synchronized.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/js/src/internal/ThreadContext.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/ThreadContext.kt rename to kotlinx-coroutines-core/js/src/internal/ThreadContext.kt diff --git a/js/kotlinx-coroutines-core-js/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/src/internal/ThreadLocal.kt rename to kotlinx-coroutines-core/js/src/internal/ThreadLocal.kt diff --git a/js/kotlinx-coroutines-core-js/test/MessageQueueTest.kt b/kotlinx-coroutines-core/js/test/MessageQueueTest.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/test/MessageQueueTest.kt rename to kotlinx-coroutines-core/js/test/MessageQueueTest.kt diff --git a/js/kotlinx-coroutines-core-js/test/PromiseTest.kt b/kotlinx-coroutines-core/js/test/PromiseTest.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/test/PromiseTest.kt rename to kotlinx-coroutines-core/js/test/PromiseTest.kt diff --git a/js/kotlinx-coroutines-core-js/test/TestBase.kt b/kotlinx-coroutines-core/js/test/TestBase.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/test/TestBase.kt rename to kotlinx-coroutines-core/js/test/TestBase.kt diff --git a/js/kotlinx-coroutines-core-js/test/internal/ArrayCopyKtTest.kt b/kotlinx-coroutines-core/js/test/internal/ArrayCopyKtTest.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/test/internal/ArrayCopyKtTest.kt rename to kotlinx-coroutines-core/js/test/internal/ArrayCopyKtTest.kt diff --git a/js/kotlinx-coroutines-core-js/test/internal/LinkedListTest.kt b/kotlinx-coroutines-core/js/test/internal/LinkedListTest.kt similarity index 100% rename from js/kotlinx-coroutines-core-js/test/internal/LinkedListTest.kt rename to kotlinx-coroutines-core/js/test/internal/LinkedListTest.kt diff --git a/core/kotlinx-coroutines-core/resources/META-INF/proguard/coroutines.pro b/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro similarity index 100% rename from core/kotlinx-coroutines-core/resources/META-INF/proguard/coroutines.pro rename to kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro diff --git a/core/kotlinx-coroutines-core/src/Builders.kt b/kotlinx-coroutines-core/jvm/src/Builders.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Builders.kt rename to kotlinx-coroutines-core/jvm/src/Builders.kt diff --git a/core/kotlinx-coroutines-core/src/CommonPool.kt b/kotlinx-coroutines-core/jvm/src/CommonPool.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/CommonPool.kt rename to kotlinx-coroutines-core/jvm/src/CommonPool.kt diff --git a/core/kotlinx-coroutines-core/src/CompletionHandler.kt b/kotlinx-coroutines-core/jvm/src/CompletionHandler.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/CompletionHandler.kt rename to kotlinx-coroutines-core/jvm/src/CompletionHandler.kt diff --git a/core/kotlinx-coroutines-core/src/CoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/CoroutineContext.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/CoroutineContext.kt rename to kotlinx-coroutines-core/jvm/src/CoroutineContext.kt diff --git a/core/kotlinx-coroutines-core/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/CoroutineExceptionHandlerImpl.kt rename to kotlinx-coroutines-core/jvm/src/CoroutineExceptionHandlerImpl.kt diff --git a/core/kotlinx-coroutines-core/src/Debug.kt b/kotlinx-coroutines-core/jvm/src/Debug.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Debug.kt rename to kotlinx-coroutines-core/jvm/src/Debug.kt diff --git a/core/kotlinx-coroutines-core/src/DefaultExecutor.kt b/kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/DefaultExecutor.kt rename to kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt diff --git a/core/kotlinx-coroutines-core/src/Dispatchers.kt b/kotlinx-coroutines-core/jvm/src/Dispatchers.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Dispatchers.kt rename to kotlinx-coroutines-core/jvm/src/Dispatchers.kt diff --git a/core/kotlinx-coroutines-core/src/EventLoop.kt b/kotlinx-coroutines-core/jvm/src/EventLoop.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/EventLoop.kt rename to kotlinx-coroutines-core/jvm/src/EventLoop.kt diff --git a/core/kotlinx-coroutines-core/src/Exceptions.kt b/kotlinx-coroutines-core/jvm/src/Exceptions.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Exceptions.kt rename to kotlinx-coroutines-core/jvm/src/Exceptions.kt diff --git a/core/kotlinx-coroutines-core/src/Executors.kt b/kotlinx-coroutines-core/jvm/src/Executors.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Executors.kt rename to kotlinx-coroutines-core/jvm/src/Executors.kt diff --git a/core/kotlinx-coroutines-core/src/Future.kt b/kotlinx-coroutines-core/jvm/src/Future.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Future.kt rename to kotlinx-coroutines-core/jvm/src/Future.kt diff --git a/core/kotlinx-coroutines-core/src/Runnable.kt b/kotlinx-coroutines-core/jvm/src/Runnable.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/Runnable.kt rename to kotlinx-coroutines-core/jvm/src/Runnable.kt diff --git a/core/kotlinx-coroutines-core/src/SchedulerTask.kt b/kotlinx-coroutines-core/jvm/src/SchedulerTask.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/SchedulerTask.kt rename to kotlinx-coroutines-core/jvm/src/SchedulerTask.kt diff --git a/core/kotlinx-coroutines-core/src/ThreadContextElement.kt b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/ThreadContextElement.kt rename to kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt diff --git a/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt b/kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt rename to kotlinx-coroutines-core/jvm/src/ThreadPoolDispatcher.kt diff --git a/core/kotlinx-coroutines-core/src/TimeSource.kt b/kotlinx-coroutines-core/jvm/src/TimeSource.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/TimeSource.kt rename to kotlinx-coroutines-core/jvm/src/TimeSource.kt diff --git a/core/kotlinx-coroutines-core/src/channels/Actor.kt b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/channels/Actor.kt rename to kotlinx-coroutines-core/jvm/src/channels/Actor.kt diff --git a/core/kotlinx-coroutines-core/src/channels/Channels.kt b/kotlinx-coroutines-core/jvm/src/channels/Channels.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/channels/Channels.kt rename to kotlinx-coroutines-core/jvm/src/channels/Channels.kt diff --git a/core/kotlinx-coroutines-core/src/channels/TickerChannels.kt b/kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/channels/TickerChannels.kt rename to kotlinx-coroutines-core/jvm/src/channels/TickerChannels.kt diff --git a/core/kotlinx-coroutines-core/src/internal/ArrayCopy.kt b/kotlinx-coroutines-core/jvm/src/internal/ArrayCopy.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/ArrayCopy.kt rename to kotlinx-coroutines-core/jvm/src/internal/ArrayCopy.kt diff --git a/core/kotlinx-coroutines-core/src/internal/Concurrent.kt b/kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/Concurrent.kt rename to kotlinx-coroutines-core/jvm/src/internal/Concurrent.kt diff --git a/core/kotlinx-coroutines-core/src/internal/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/ExceptionsConstuctor.kt rename to kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt diff --git a/core/kotlinx-coroutines-core/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/LockFreeLinkedList.kt rename to kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt diff --git a/core/kotlinx-coroutines-core/src/internal/LockFreeTaskQueue.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeTaskQueue.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/LockFreeTaskQueue.kt rename to kotlinx-coroutines-core/jvm/src/internal/LockFreeTaskQueue.kt diff --git a/core/kotlinx-coroutines-core/src/internal/MainDispatchers.kt b/kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/MainDispatchers.kt rename to kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt diff --git a/core/kotlinx-coroutines-core/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/ProbesSupport.kt rename to kotlinx-coroutines-core/jvm/src/internal/ProbesSupport.kt diff --git a/core/kotlinx-coroutines-core/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/StackTraceRecovery.kt rename to kotlinx-coroutines-core/jvm/src/internal/StackTraceRecovery.kt diff --git a/core/kotlinx-coroutines-core/src/internal/Synchronized.kt b/kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/Synchronized.kt rename to kotlinx-coroutines-core/jvm/src/internal/Synchronized.kt diff --git a/core/kotlinx-coroutines-core/src/internal/SystemProps.kt b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/SystemProps.kt rename to kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt diff --git a/core/kotlinx-coroutines-core/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/ThreadContext.kt rename to kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt diff --git a/core/kotlinx-coroutines-core/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/ThreadLocal.kt rename to kotlinx-coroutines-core/jvm/src/internal/ThreadLocal.kt diff --git a/core/kotlinx-coroutines-core/src/internal/ThreadSafeHeap.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadSafeHeap.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/internal/ThreadSafeHeap.kt rename to kotlinx-coroutines-core/jvm/src/internal/ThreadSafeHeap.kt diff --git a/core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt rename to kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt diff --git a/core/kotlinx-coroutines-core/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/scheduling/Dispatcher.kt rename to kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt diff --git a/core/kotlinx-coroutines-core/src/scheduling/Tasks.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/scheduling/Tasks.kt rename to kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt diff --git a/core/kotlinx-coroutines-core/src/scheduling/WorkQueue.kt b/kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/scheduling/WorkQueue.kt rename to kotlinx-coroutines-core/jvm/src/scheduling/WorkQueue.kt diff --git a/core/kotlinx-coroutines-core/src/test_/TestCoroutineContext.kt b/kotlinx-coroutines-core/jvm/src/test_/TestCoroutineContext.kt similarity index 100% rename from core/kotlinx-coroutines-core/src/test_/TestCoroutineContext.kt rename to kotlinx-coroutines-core/jvm/src/test_/TestCoroutineContext.kt diff --git a/core/kotlinx-coroutines-core/test/AsyncJvmTest.kt b/kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/AsyncJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/AsyncJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/AtomicCancellationTest.kt b/kotlinx-coroutines-core/jvm/test/AtomicCancellationTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/AtomicCancellationTest.kt rename to kotlinx-coroutines-core/jvm/test/AtomicCancellationTest.kt diff --git a/core/kotlinx-coroutines-core/test/AwaitJvmTest.kt b/kotlinx-coroutines-core/jvm/test/AwaitJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/AwaitJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/AwaitJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/AwaitStressTest.kt b/kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/AwaitStressTest.kt rename to kotlinx-coroutines-core/jvm/test/AwaitStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/CancellableContinuationJvmTest.kt b/kotlinx-coroutines-core/jvm/test/CancellableContinuationJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/CancellableContinuationJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/CancellableContinuationJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/CancelledAwaitStressTest.kt b/kotlinx-coroutines-core/jvm/test/CancelledAwaitStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/CancelledAwaitStressTest.kt rename to kotlinx-coroutines-core/jvm/test/CancelledAwaitStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/CommonPoolTest.kt b/kotlinx-coroutines-core/jvm/test/CommonPoolTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/CommonPoolTest.kt rename to kotlinx-coroutines-core/jvm/test/CommonPoolTest.kt diff --git a/core/kotlinx-coroutines-core/test/ContinuationSerializationTest.kt b/kotlinx-coroutines-core/jvm/test/ContinuationSerializationTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/ContinuationSerializationTest.kt rename to kotlinx-coroutines-core/jvm/test/ContinuationSerializationTest.kt diff --git a/core/kotlinx-coroutines-core/test/CoroutinesJvmTest.kt b/kotlinx-coroutines-core/jvm/test/CoroutinesJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/CoroutinesJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/CoroutinesJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/DebugThreadNameTest.kt b/kotlinx-coroutines-core/jvm/test/DebugThreadNameTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/DebugThreadNameTest.kt rename to kotlinx-coroutines-core/jvm/test/DebugThreadNameTest.kt diff --git a/core/kotlinx-coroutines-core/test/DefaultExecutorStressTest.kt b/kotlinx-coroutines-core/jvm/test/DefaultExecutorStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/DefaultExecutorStressTest.kt rename to kotlinx-coroutines-core/jvm/test/DefaultExecutorStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/DelayJvmTest.kt b/kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/DelayJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/DelayJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/EventLoopsTest.kt b/kotlinx-coroutines-core/jvm/test/EventLoopsTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/EventLoopsTest.kt rename to kotlinx-coroutines-core/jvm/test/EventLoopsTest.kt diff --git a/core/kotlinx-coroutines-core/test/ExecutorsTest.kt b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/ExecutorsTest.kt rename to kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt diff --git a/core/kotlinx-coroutines-core/test/FailFastOnStartTest.kt b/kotlinx-coroutines-core/jvm/test/FailFastOnStartTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/FailFastOnStartTest.kt rename to kotlinx-coroutines-core/jvm/test/FailFastOnStartTest.kt diff --git a/core/kotlinx-coroutines-core/test/IODispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/IODispatcherTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/IODispatcherTest.kt rename to kotlinx-coroutines-core/jvm/test/IODispatcherTest.kt diff --git a/core/kotlinx-coroutines-core/test/JobActivationStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobActivationStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/JobActivationStressTest.kt rename to kotlinx-coroutines-core/jvm/test/JobActivationStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/JobChildStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobChildStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/JobChildStressTest.kt rename to kotlinx-coroutines-core/jvm/test/JobChildStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/JobDisposeStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobDisposeStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/JobDisposeStressTest.kt rename to kotlinx-coroutines-core/jvm/test/JobDisposeStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/JobHandlersUpgradeStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobHandlersUpgradeStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/JobHandlersUpgradeStressTest.kt rename to kotlinx-coroutines-core/jvm/test/JobHandlersUpgradeStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/JobStressTest.kt b/kotlinx-coroutines-core/jvm/test/JobStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/JobStressTest.kt rename to kotlinx-coroutines-core/jvm/test/JobStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/JoinStressTest.kt b/kotlinx-coroutines-core/jvm/test/JoinStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/JoinStressTest.kt rename to kotlinx-coroutines-core/jvm/test/JoinStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/RunBlockingTest.kt b/kotlinx-coroutines-core/jvm/test/RunBlockingTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/RunBlockingTest.kt rename to kotlinx-coroutines-core/jvm/test/RunBlockingTest.kt diff --git a/core/kotlinx-coroutines-core/test/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/TestBase.kt rename to kotlinx-coroutines-core/jvm/test/TestBase.kt diff --git a/core/kotlinx-coroutines-core/test/TestBaseTest.kt b/kotlinx-coroutines-core/jvm/test/TestBaseTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/TestBaseTest.kt rename to kotlinx-coroutines-core/jvm/test/TestBaseTest.kt diff --git a/core/kotlinx-coroutines-core/test/TestSecurityManager.kt b/kotlinx-coroutines-core/jvm/test/TestSecurityManager.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/TestSecurityManager.kt rename to kotlinx-coroutines-core/jvm/test/TestSecurityManager.kt diff --git a/core/kotlinx-coroutines-core/test/ThreadContextElementTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/ThreadContextElementTest.kt rename to kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt diff --git a/core/kotlinx-coroutines-core/test/ThreadLocalTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/ThreadLocalTest.kt rename to kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt diff --git a/core/kotlinx-coroutines-core/test/Threads.kt b/kotlinx-coroutines-core/jvm/test/Threads.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/Threads.kt rename to kotlinx-coroutines-core/jvm/test/Threads.kt diff --git a/core/kotlinx-coroutines-core/test/UnconfinedConcurrentStressTest.kt b/kotlinx-coroutines-core/jvm/test/UnconfinedConcurrentStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/UnconfinedConcurrentStressTest.kt rename to kotlinx-coroutines-core/jvm/test/UnconfinedConcurrentStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/VirtualTimeSource.kt b/kotlinx-coroutines-core/jvm/test/VirtualTimeSource.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/VirtualTimeSource.kt rename to kotlinx-coroutines-core/jvm/test/VirtualTimeSource.kt diff --git a/core/kotlinx-coroutines-core/test/WithDefaultContextTest.kt b/kotlinx-coroutines-core/jvm/test/WithDefaultContextTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/WithDefaultContextTest.kt rename to kotlinx-coroutines-core/jvm/test/WithDefaultContextTest.kt diff --git a/core/kotlinx-coroutines-core/test/WithTimeoutChildDipspatchStressTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/WithTimeoutChildDipspatchStressTest.kt rename to kotlinx-coroutines-core/jvm/test/WithTimeoutChildDipspatchStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/WithTimeoutOrNullJvmTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/WithTimeoutOrNullJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/WithTimeoutOrNullThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/WithTimeoutOrNullThreadDispatchTest.kt rename to kotlinx-coroutines-core/jvm/test/WithTimeoutOrNullThreadDispatchTest.kt diff --git a/core/kotlinx-coroutines-core/test/WithTimeoutThreadDispatchTest.kt b/kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/WithTimeoutThreadDispatchTest.kt rename to kotlinx-coroutines-core/jvm/test/WithTimeoutThreadDispatchTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ActorLazyTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ActorLazyTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ActorTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ActorTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ArrayChannelStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ArrayChannelStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ArrayChannelStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ArrayChannelStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/BroadcastChannelMultiReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/BroadcastChannelMultiReceiveStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelMultiReceiveStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/BroadcastChannelSubStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelSubStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/BroadcastChannelSubStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/BroadcastChannelSubStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelAtomicCancelStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelAtomicCancelStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ChannelAtomicCancelStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ChannelAtomicCancelStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelSendReceiveStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ChannelSendReceiveStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ChannelSendReceiveStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelsConsumeTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelsConsumeTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ChannelsConsumeTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ChannelsConsumeTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelsJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ChannelsJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ChannelsJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ChannelsJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ConflatedChannelCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ConflatedChannelCloseStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ConflatedChannelCloseStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ConflatedChannelCloseStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/DoubleChannelCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/DoubleChannelCloseStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/DoubleChannelCloseStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/DoubleChannelCloseStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/InvokeOnCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/InvokeOnCloseStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/InvokeOnCloseStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/InvokeOnCloseStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/ProduceConsumeJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/ProduceConsumeJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/ProduceConsumeJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/RandevouzChannelStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/RandevouzChannelStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/RandevouzChannelStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/RandevouzChannelStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/SendReceiveJvmStressTest.kt b/kotlinx-coroutines-core/jvm/test/channels/SendReceiveJvmStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/SendReceiveJvmStressTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/SendReceiveJvmStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/SimpleSendReceiveJvmTest.kt b/kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/SimpleSendReceiveJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/SimpleSendReceiveJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/TickerChannelCommonTest.kt b/kotlinx-coroutines-core/jvm/test/channels/TickerChannelCommonTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/TickerChannelCommonTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/TickerChannelCommonTest.kt diff --git a/core/kotlinx-coroutines-core/test/channels/TickerChannelTest.kt b/kotlinx-coroutines-core/jvm/test/channels/TickerChannelTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/channels/TickerChannelTest.kt rename to kotlinx-coroutines-core/jvm/test/channels/TickerChannelTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/CoroutineExceptionHandlerJvmTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/CoroutineExceptionHandlerJvmTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/CoroutineExceptionHandlerJvmTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/CoroutineExceptionHandlerJvmTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/Exceptions.kt b/kotlinx-coroutines-core/jvm/test/exceptions/Exceptions.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/Exceptions.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/Exceptions.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/JobBasicCancellationTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobBasicCancellationTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/JobBasicCancellationTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/JobBasicCancellationTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/JobExceptionHandlingTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionHandlingTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/JobExceptionHandlingTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionHandlingTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/JobExceptionsStressTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionsStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/JobExceptionsStressTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/JobExceptionsStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/JobNestedExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/JobNestedExceptionsTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/JobNestedExceptionsTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/JobNestedExceptionsTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/ProduceExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/ProduceExceptionsTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryNestedScopesTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryNestedScopesTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedScopesTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryNestedTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryNestedTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/StackTraceRecoveryTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/Stacktraces.kt b/kotlinx-coroutines-core/jvm/test/exceptions/Stacktraces.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/Stacktraces.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/Stacktraces.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/SuppressionTests.kt b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/SuppressionTests.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/WithContextCancellationStressTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/WithContextCancellationStressTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/WithContextCancellationStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/exceptions/WithContextExceptionHandlingTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/WithContextExceptionHandlingTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/exceptions/WithContextExceptionHandlingTest.kt rename to kotlinx-coroutines-core/jvm/test/exceptions/WithContextExceptionHandlingTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-02b.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-03s.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-03s.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-05s.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-05s.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-basic-07.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-basic-07.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-cancel-07.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-07.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-07.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-08.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-08.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-09.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-09.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-channel-10.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-compose-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-compose-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-compose-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-compose-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-compose-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-compose-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-compose-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-compose-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-compose-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-compose-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-compose-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-compose-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-compose-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-compose-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-compose-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-compose-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-07.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-07.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-08.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-08.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-08.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-09.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-09.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-09.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-10.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-10.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-context-11.kt b/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-context-11.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-exceptions-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-exceptions-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-exceptions-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-exceptions-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-exceptions-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-exceptions-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-exceptions-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-exceptions-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-exceptions-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-exceptions-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-exceptions-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-select-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-select-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-select-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-select-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-select-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-select-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-select-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-select-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-select-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-select-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-select-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-select-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-select-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-select-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-select-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-supervision-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-supervision-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-supervision-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-supervision-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-supervision-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-supervision-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-supervision-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-supervision-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-supervision-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-01.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-01.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-01.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-01b.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-01b.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-01b.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-02.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-02.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-02.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-03.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-03.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-03.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-04.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-04.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-04.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-05.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-05.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-05.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-06.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt diff --git a/core/kotlinx-coroutines-core/test/guide/example-sync-07.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/example-sync-07.kt rename to kotlinx-coroutines-core/jvm/test/guide/example-sync-07.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/BasicsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/BasicsGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/BasicsGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/CancellationTimeOutsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/CancellationTimeOutsGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/CancellationTimeOutsGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/CancellationTimeOutsGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/ChannelsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/ChannelsGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/ChannelsGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/ComposingGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/ComposingGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/ComposingGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/DispatcherGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/DispatcherGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/DispatcherGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/ExceptionsGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/ExceptionsGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/ExceptionsGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/GuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/GuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/GuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/GuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/SelectGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/SelectGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/SelectGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/SharedStateGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/SharedStateGuideTest.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/SharedStateGuideTest.kt diff --git a/core/kotlinx-coroutines-core/test/guide/test/TestUtil.kt b/kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/guide/test/TestUtil.kt rename to kotlinx-coroutines-core/jvm/test/guide/test/TestUtil.kt diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListAtomicStressLFTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicStressLFTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListAtomicStressLFTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListAtomicStressLFTest.kt diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListLongStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListLongStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListLongStressTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListLongStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListShortStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListShortStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListShortStressTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListShortStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/LockFreeLinkedListTest.kt diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeTaskQueueStressTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/LockFreeTaskQueueStressTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeTaskQueueTest.kt b/kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/LockFreeTaskQueueTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/LockFreeTaskQueueTest.kt diff --git a/core/kotlinx-coroutines-core/test/internal/ThreadSafeHeapTest.kt b/kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/internal/ThreadSafeHeapTest.kt rename to kotlinx-coroutines-core/jvm/test/internal/ThreadSafeHeapTest.kt diff --git a/core/kotlinx-coroutines-core/test/linearizability/ChannelIsClosedLinearizabilityTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelIsClosedLinearizabilityTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/linearizability/ChannelIsClosedLinearizabilityTest.kt rename to kotlinx-coroutines-core/jvm/test/linearizability/ChannelIsClosedLinearizabilityTest.kt diff --git a/core/kotlinx-coroutines-core/test/linearizability/ChannelLinearizabilityTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/ChannelLinearizabilityTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/linearizability/ChannelLinearizabilityTest.kt rename to kotlinx-coroutines-core/jvm/test/linearizability/ChannelLinearizabilityTest.kt diff --git a/core/kotlinx-coroutines-core/test/linearizability/LinTesting.kt b/kotlinx-coroutines-core/jvm/test/linearizability/LinTesting.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/linearizability/LinTesting.kt rename to kotlinx-coroutines-core/jvm/test/linearizability/LinTesting.kt diff --git a/core/kotlinx-coroutines-core/test/linearizability/LockFreeListLinearizabilityTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLinearizabilityTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/linearizability/LockFreeListLinearizabilityTest.kt rename to kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLinearizabilityTest.kt diff --git a/core/kotlinx-coroutines-core/test/linearizability/LockFreeTaskQueueLinearizabilityTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLinearizabilityTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/linearizability/LockFreeTaskQueueLinearizabilityTest.kt rename to kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLinearizabilityTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherRaceStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherRaceStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherRaceStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherRaceStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/BlockingIOTerminationStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/BlockingIOTerminationStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/BlockingIOTerminationStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/BlockingIOTerminationStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/CoroutineDispatcherTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/CoroutineDispatcherTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerCloseStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerCloseStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerCloseStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerShrinkTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerShrinkTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerShrinkTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerShrinkTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/CoroutineSchedulerTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/LimitingCoroutineDispatcherStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/LimitingCoroutineDispatcherStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/LimitingCoroutineDispatcherStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/LimitingCoroutineDispatcherStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/LimitingDispatcherTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/LimitingDispatcherTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/LimitingDispatcherTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/LimitingDispatcherTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/SchedulerTestBase.kt b/kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/SchedulerTestBase.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/SchedulerTestBase.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/TestTimeSource.kt b/kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/TestTimeSource.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/TestTimeSource.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/WorkQueueStressTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/WorkQueueStressTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/scheduling/WorkQueueTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/scheduling/WorkQueueTest.kt rename to kotlinx-coroutines-core/jvm/test/scheduling/WorkQueueTest.kt diff --git a/core/kotlinx-coroutines-core/test/selects/SelectChannelStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectChannelStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/selects/SelectChannelStressTest.kt rename to kotlinx-coroutines-core/jvm/test/selects/SelectChannelStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/selects/SelectMutexStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectMutexStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/selects/SelectMutexStressTest.kt rename to kotlinx-coroutines-core/jvm/test/selects/SelectMutexStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/selects/SelectPhilosophersStressTest.kt b/kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/selects/SelectPhilosophersStressTest.kt rename to kotlinx-coroutines-core/jvm/test/selects/SelectPhilosophersStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/sync/MutexStressTest.kt b/kotlinx-coroutines-core/jvm/test/sync/MutexStressTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/sync/MutexStressTest.kt rename to kotlinx-coroutines-core/jvm/test/sync/MutexStressTest.kt diff --git a/core/kotlinx-coroutines-core/test/test/TestCoroutineContextTest.kt b/kotlinx-coroutines-core/jvm/test/test/TestCoroutineContextTest.kt similarity index 100% rename from core/kotlinx-coroutines-core/test/test/TestCoroutineContextTest.kt rename to kotlinx-coroutines-core/jvm/test/test/TestCoroutineContextTest.kt diff --git a/native/kotlinx-coroutines-core-native/README.md b/kotlinx-coroutines-core/native/README.md similarity index 100% rename from native/kotlinx-coroutines-core-native/README.md rename to kotlinx-coroutines-core/native/README.md diff --git a/native/kotlinx-coroutines-core-native/src/Builders.kt b/kotlinx-coroutines-core/native/src/Builders.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/Builders.kt rename to kotlinx-coroutines-core/native/src/Builders.kt diff --git a/native/kotlinx-coroutines-core-native/src/CompletionHandler.kt b/kotlinx-coroutines-core/native/src/CompletionHandler.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/CompletionHandler.kt rename to kotlinx-coroutines-core/native/src/CompletionHandler.kt diff --git a/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt b/kotlinx-coroutines-core/native/src/CoroutineContext.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/CoroutineContext.kt rename to kotlinx-coroutines-core/native/src/CoroutineContext.kt diff --git a/native/kotlinx-coroutines-core-native/src/CoroutineExceptionHandlerImpl.kt b/kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/CoroutineExceptionHandlerImpl.kt rename to kotlinx-coroutines-core/native/src/CoroutineExceptionHandlerImpl.kt diff --git a/native/kotlinx-coroutines-core-native/src/Debug.kt b/kotlinx-coroutines-core/native/src/Debug.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/Debug.kt rename to kotlinx-coroutines-core/native/src/Debug.kt diff --git a/native/kotlinx-coroutines-core-native/src/Dispatchers.kt b/kotlinx-coroutines-core/native/src/Dispatchers.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/Dispatchers.kt rename to kotlinx-coroutines-core/native/src/Dispatchers.kt diff --git a/native/kotlinx-coroutines-core-native/src/EventLoop.kt b/kotlinx-coroutines-core/native/src/EventLoop.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/EventLoop.kt rename to kotlinx-coroutines-core/native/src/EventLoop.kt diff --git a/native/kotlinx-coroutines-core-native/src/Exceptions.kt b/kotlinx-coroutines-core/native/src/Exceptions.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/Exceptions.kt rename to kotlinx-coroutines-core/native/src/Exceptions.kt diff --git a/native/kotlinx-coroutines-core-native/src/Runnable.kt b/kotlinx-coroutines-core/native/src/Runnable.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/Runnable.kt rename to kotlinx-coroutines-core/native/src/Runnable.kt diff --git a/native/kotlinx-coroutines-core-native/src/SchedulerTask.kt b/kotlinx-coroutines-core/native/src/SchedulerTask.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/SchedulerTask.kt rename to kotlinx-coroutines-core/native/src/SchedulerTask.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/ArrayCopy.kt b/kotlinx-coroutines-core/native/src/internal/ArrayCopy.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/ArrayCopy.kt rename to kotlinx-coroutines-core/native/src/internal/ArrayCopy.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/Concurrent.kt b/kotlinx-coroutines-core/native/src/internal/Concurrent.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/Concurrent.kt rename to kotlinx-coroutines-core/native/src/internal/Concurrent.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/CopyOnWriteList.kt rename to kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/LinkedList.kt b/kotlinx-coroutines-core/native/src/internal/LinkedList.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/LinkedList.kt rename to kotlinx-coroutines-core/native/src/internal/LinkedList.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/LockFreeMPSCQueue.kt b/kotlinx-coroutines-core/native/src/internal/LockFreeMPSCQueue.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/LockFreeMPSCQueue.kt rename to kotlinx-coroutines-core/native/src/internal/LockFreeMPSCQueue.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/ProbesSupport.kt b/kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/ProbesSupport.kt rename to kotlinx-coroutines-core/native/src/internal/ProbesSupport.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/StackTraceRecovery.kt b/kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/StackTraceRecovery.kt rename to kotlinx-coroutines-core/native/src/internal/StackTraceRecovery.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/Synchronized.kt b/kotlinx-coroutines-core/native/src/internal/Synchronized.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/Synchronized.kt rename to kotlinx-coroutines-core/native/src/internal/Synchronized.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/native/src/internal/ThreadContext.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/ThreadContext.kt rename to kotlinx-coroutines-core/native/src/internal/ThreadContext.kt diff --git a/native/kotlinx-coroutines-core-native/src/internal/ThreadLocal.kt b/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt similarity index 93% rename from native/kotlinx-coroutines-core-native/src/internal/ThreadLocal.kt rename to kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt index 7214bba872..c214a63bb6 100644 --- a/native/kotlinx-coroutines-core-native/src/internal/ThreadLocal.kt +++ b/kotlinx-coroutines-core/native/src/internal/ThreadLocal.kt @@ -3,7 +3,6 @@ */ package kotlinx.coroutines.internal -import kotlin.native.concurrent.* @Suppress("ACTUAL_WITHOUT_EXPECT") internal actual typealias NativeThreadLocal = kotlin.native.concurrent.ThreadLocal diff --git a/native/kotlinx-coroutines-core-native/src/internal/ThreadSafeHeap.kt b/kotlinx-coroutines-core/native/src/internal/ThreadSafeHeap.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/src/internal/ThreadSafeHeap.kt rename to kotlinx-coroutines-core/native/src/internal/ThreadSafeHeap.kt diff --git a/native/kotlinx-coroutines-core-native/test/DelayExceptionTest.kt b/kotlinx-coroutines-core/native/test/DelayExceptionTest.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/test/DelayExceptionTest.kt rename to kotlinx-coroutines-core/native/test/DelayExceptionTest.kt diff --git a/native/kotlinx-coroutines-core-native/test/TestBase.kt b/kotlinx-coroutines-core/native/test/TestBase.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/test/TestBase.kt rename to kotlinx-coroutines-core/native/test/TestBase.kt diff --git a/native/kotlinx-coroutines-core-native/test/internal/LinkedListTest.kt b/kotlinx-coroutines-core/native/test/internal/LinkedListTest.kt similarity index 100% rename from native/kotlinx-coroutines-core-native/test/internal/LinkedListTest.kt rename to kotlinx-coroutines-core/native/test/internal/LinkedListTest.kt diff --git a/core/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md similarity index 100% rename from core/kotlinx-coroutines-debug/README.md rename to kotlinx-coroutines-debug/README.md index b9cc094a66..df5d6c3bee 100644 --- a/core/kotlinx-coroutines-debug/README.md +++ b/kotlinx-coroutines-debug/README.md @@ -110,6 +110,6 @@ Do not use this module in production environment and do not rely on the format o [DebugProbes.install]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/install.html [DebugProbes.dumpCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines.html [DebugProbes.dumpCoroutinesState]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines-state.html -[DebugProbes.printScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-scope.html [DebugProbes.printJob]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-job.html +[DebugProbes.printScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-scope.html diff --git a/core/kotlinx-coroutines-debug/build.gradle b/kotlinx-coroutines-debug/build.gradle similarity index 100% rename from core/kotlinx-coroutines-debug/build.gradle rename to kotlinx-coroutines-debug/build.gradle diff --git a/core/kotlinx-coroutines-debug/src/AgentPremain.kt b/kotlinx-coroutines-debug/src/AgentPremain.kt similarity index 100% rename from core/kotlinx-coroutines-debug/src/AgentPremain.kt rename to kotlinx-coroutines-debug/src/AgentPremain.kt diff --git a/core/kotlinx-coroutines-debug/src/CoroutineState.kt b/kotlinx-coroutines-debug/src/CoroutineState.kt similarity index 100% rename from core/kotlinx-coroutines-debug/src/CoroutineState.kt rename to kotlinx-coroutines-debug/src/CoroutineState.kt diff --git a/core/kotlinx-coroutines-debug/src/DebugProbes.kt b/kotlinx-coroutines-debug/src/DebugProbes.kt similarity index 100% rename from core/kotlinx-coroutines-debug/src/DebugProbes.kt rename to kotlinx-coroutines-debug/src/DebugProbes.kt diff --git a/core/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt similarity index 100% rename from core/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt rename to kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt diff --git a/core/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt b/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt similarity index 100% rename from core/kotlinx-coroutines-debug/src/internal/NoOpProbes.kt rename to kotlinx-coroutines-debug/src/internal/NoOpProbes.kt diff --git a/core/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt rename to kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt diff --git a/core/kotlinx-coroutines-debug/test/DebugProbesTest.kt b/kotlinx-coroutines-debug/test/DebugProbesTest.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/DebugProbesTest.kt rename to kotlinx-coroutines-debug/test/DebugProbesTest.kt diff --git a/core/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt rename to kotlinx-coroutines-debug/test/SanitizedProbesTest.kt diff --git a/core/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt b/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt rename to kotlinx-coroutines-debug/test/ScopedBuildersTest.kt diff --git a/core/kotlinx-coroutines-debug/test/StartModeProbesTest.kt b/kotlinx-coroutines-debug/test/StartModeProbesTest.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/StartModeProbesTest.kt rename to kotlinx-coroutines-debug/test/StartModeProbesTest.kt diff --git a/core/kotlinx-coroutines-debug/test/StracktraceUtils.kt b/kotlinx-coroutines-debug/test/StracktraceUtils.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/StracktraceUtils.kt rename to kotlinx-coroutines-debug/test/StracktraceUtils.kt diff --git a/core/kotlinx-coroutines-debug/test/ToStringTest.kt b/kotlinx-coroutines-debug/test/ToStringTest.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/ToStringTest.kt rename to kotlinx-coroutines-debug/test/ToStringTest.kt diff --git a/core/kotlinx-coroutines-test/README.md b/kotlinx-coroutines-test/README.md similarity index 100% rename from core/kotlinx-coroutines-test/README.md rename to kotlinx-coroutines-test/README.md diff --git a/core/kotlinx-coroutines-test/build.gradle b/kotlinx-coroutines-test/build.gradle similarity index 100% rename from core/kotlinx-coroutines-test/build.gradle rename to kotlinx-coroutines-test/build.gradle diff --git a/core/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro b/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro similarity index 100% rename from core/kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro rename to kotlinx-coroutines-test/resources/META-INF/proguard/coroutines.pro diff --git a/core/kotlinx-coroutines-test/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory b/kotlinx-coroutines-test/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory similarity index 100% rename from core/kotlinx-coroutines-test/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory rename to kotlinx-coroutines-test/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory diff --git a/core/kotlinx-coroutines-test/src/TestDispatchers.kt b/kotlinx-coroutines-test/src/TestDispatchers.kt similarity index 100% rename from core/kotlinx-coroutines-test/src/TestDispatchers.kt rename to kotlinx-coroutines-test/src/TestDispatchers.kt diff --git a/core/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt b/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt similarity index 100% rename from core/kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt rename to kotlinx-coroutines-test/src/internal/MainTestDispatcher.kt diff --git a/core/kotlinx-coroutines-test/test/TestDispatchersTest.kt b/kotlinx-coroutines-test/test/TestDispatchersTest.kt similarity index 100% rename from core/kotlinx-coroutines-test/test/TestDispatchersTest.kt rename to kotlinx-coroutines-test/test/TestDispatchersTest.kt diff --git a/reactive/kotlinx-coroutines-reactor/build.gradle b/reactive/kotlinx-coroutines-reactor/build.gradle index 919ae294b9..b0f2292360 100644 --- a/reactive/kotlinx-coroutines-reactor/build.gradle +++ b/reactive/kotlinx-coroutines-reactor/build.gradle @@ -1,24 +1,14 @@ /* - * 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. */ -plugins { - id 'io.spring.dependency-management' version '1.0.3.RELEASE' -} - -dependencyManagement { - imports { - mavenBom 'io.projectreactor:reactor-bom:Bismuth-RELEASE' - } -} - dependencies { - compile 'io.projectreactor:reactor-core' + compile "io.projectreactor:reactor-core:$reactor_vesion" compile project(':kotlinx-coroutines-reactive') } tasks.withType(dokka.getClass()) { externalDocumentationLink { - url = new URL('https://projectreactor.io/docs/core/release/api/') + url = new URL('https://projectreactor.io/docs/core/3.2.5.RELEASE/api/') } } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index b436be531c..46d3d981dd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,12 +20,11 @@ include('site') module('binary-compatibility-validator') -module('common/kotlinx-coroutines-core-common') +include "kotlinx-coroutines-core" -module('core/kotlinx-coroutines-core') -module('core/kotlinx-coroutines-test') -module('core/kotlinx-coroutines-debug') -module('core/stdlib-stubs') +module('kotlinx-coroutines-test') +module('kotlinx-coroutines-debug') +module('stdlib-stubs') module('integration/kotlinx-coroutines-guava') module('integration/kotlinx-coroutines-jdk8') @@ -42,8 +41,5 @@ module('ui/kotlinx-coroutines-android/android-unit-tests') module('ui/kotlinx-coroutines-javafx') module('ui/kotlinx-coroutines-swing') -module('js/kotlinx-coroutines-core-js') module('js/js-stub') module('js/example-frontend-js') - -module('native/kotlinx-coroutines-core-native') diff --git a/core/stdlib-stubs/README.md b/stdlib-stubs/README.md similarity index 100% rename from core/stdlib-stubs/README.md rename to stdlib-stubs/README.md diff --git a/core/stdlib-stubs/build.gradle b/stdlib-stubs/build.gradle similarity index 100% rename from core/stdlib-stubs/build.gradle rename to stdlib-stubs/build.gradle diff --git a/core/stdlib-stubs/src/Continuation.kt b/stdlib-stubs/src/Continuation.kt similarity index 100% rename from core/stdlib-stubs/src/Continuation.kt rename to stdlib-stubs/src/Continuation.kt diff --git a/core/stdlib-stubs/src/ContinuationInterceptor.kt b/stdlib-stubs/src/ContinuationInterceptor.kt similarity index 100% rename from core/stdlib-stubs/src/ContinuationInterceptor.kt rename to stdlib-stubs/src/ContinuationInterceptor.kt diff --git a/core/stdlib-stubs/src/CoroutineContext.kt b/stdlib-stubs/src/CoroutineContext.kt similarity index 100% rename from core/stdlib-stubs/src/CoroutineContext.kt rename to stdlib-stubs/src/CoroutineContext.kt diff --git a/core/stdlib-stubs/src/Result.kt b/stdlib-stubs/src/Result.kt similarity index 100% rename from core/stdlib-stubs/src/Result.kt rename to stdlib-stubs/src/Result.kt diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle/wrapper/gradle-wrapper.jar b/ui/kotlinx-coroutines-android/animation-app/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 54708 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

_x$+l{{cH8$W#CT diff --git a/ui/kotlinx-coroutines-android/example-app/gradle/wrapper/gradle-wrapper.jar b/ui/kotlinx-coroutines-android/example-app/gradle/wrapper/gradle-wrapper.jar index 13372aef5e24af05341d49695ee84e5f9b594659..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 53636 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ⅅ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 H-+%o-(+5aQ diff --git a/ui/kotlinx-coroutines-android/gradle/wrapper/gradle-wrapper.jar b/ui/kotlinx-coroutines-android/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 54708 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

_x$+l{{cH8$W#CT From c055f025f4fd3d3dc6a4ceecb798091b31f986e9 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 29 Jan 2019 12:41:02 +0300 Subject: [PATCH 06/82] Move debug example to a proper package --- .../test/Example.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {core/kotlinx-coroutines-debug => kotlinx-coroutines-debug}/test/Example.kt (100%) diff --git a/core/kotlinx-coroutines-debug/test/Example.kt b/kotlinx-coroutines-debug/test/Example.kt similarity index 100% rename from core/kotlinx-coroutines-debug/test/Example.kt rename to kotlinx-coroutines-debug/test/Example.kt From 3819379285d6bf1c8d9281c44c2caf59132c1c8d Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 15 Jan 2019 14:18:20 +0300 Subject: [PATCH 07/82] Implement CoroutineStackFrame in SelectBuilderImpl Fixes #931 --- .../common/src/selects/Select.kt | 7 ++- .../test/SanitizedProbesTest.kt | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt index d9cce0d71a..a36aae4198 100644 --- a/kotlinx-coroutines-core/common/src/selects/Select.kt +++ b/kotlinx-coroutines-core/common/src/selects/Select.kt @@ -197,7 +197,12 @@ private val RESUMED: Any = Symbol("RESUMED") internal class SelectBuilderImpl( private val uCont: Continuation // unintercepted delegate continuation ) : LockFreeLinkedListHead(), SelectBuilder, - SelectInstance, Continuation { + SelectInstance, Continuation, CoroutineStackFrame { + override val callerFrame: CoroutineStackFrame? + get() = uCont as? CoroutineStackFrame + + override fun getStackTraceElement(): StackTraceElement? = null + // selection state is "this" (list of nodes) initially and is replaced by idempotent marker (or null) when selected private val _state = atomic(this) diff --git a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt index 925f2f7219..1eb815711a 100644 --- a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt +++ b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt @@ -7,6 +7,7 @@ package definitely.not.kotlinx.coroutines import kotlinx.coroutines.* import kotlinx.coroutines.debug.* +import kotlinx.coroutines.selects.* import org.junit.* import org.junit.Test import java.util.concurrent.* @@ -83,6 +84,48 @@ class SanitizedProbesTest : TestBase() { deferred.cancelAndJoin() } + @Test + fun testSelectBuilder() = runTest { + val selector = launchSelector() + expect(1) + yield() + expect(3) + verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@35fc6dc4, state: RUNNING (Last suspension stacktrace, not an actual stacktrace)\n" + + "\t(Coroutine creation stacktrace)\n" + + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", + + "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@1b68b9a4, state: SUSPENDED\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1\$1\$1.invokeSuspend(SanitizedProbesTest.kt:105)\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1.invokeSuspend(SanitizedProbesTest.kt:143)\n" + + "\t(Coroutine creation stacktrace)\n" + + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" + + "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)\n" + + "\tat kotlinx.coroutines.BuildersKt.launch\$default(Unknown Source)\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.launchSelector(SanitizedProbesTest.kt:100)\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$launchSelector(SanitizedProbesTest.kt:16)\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testSelectBuilder\$1.invokeSuspend(SanitizedProbesTest.kt:89)\n" + + "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" + + "\tat kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)\n" + + "\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt:154)\n" + + "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testSelectBuilder(SanitizedProbesTest.kt:88)") + finish(4) + selector.cancelAndJoin() + } + + private fun CoroutineScope.launchSelector(): Job { + val job = CompletableDeferred(Unit) + return launch { + select { + job.onJoin { + expect(2) + delay(Long.MAX_VALUE) + 1 + } + + } + } + } + private fun CoroutineScope.createActiveDeferred(): Deferred<*> = async { suspendingMethod() assertTrue(true) From f6f603757acbd6e6fd52b9da0c2e1fc895a08dff Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 15 Jan 2019 14:34:34 +0300 Subject: [PATCH 08/82] Recover stacktrace in select clauses --- .../kotlinx-coroutines-core.txt | 4 ++- .../common/src/selects/Select.kt | 6 +++- .../test/exceptions/StackTraceRecoveryTest.kt | 29 ++++++++++++++++++- 3 files changed, 36 insertions(+), 3 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 fc80f3593d..18041f72d0 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -748,12 +748,14 @@ public final class kotlinx/coroutines/selects/SelectBuilder$DefaultImpls { public static fun invoke (Lkotlinx/coroutines/selects/SelectBuilder;Lkotlinx/coroutines/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V } -public final class kotlinx/coroutines/selects/SelectBuilderImpl : kotlinx/coroutines/internal/LockFreeLinkedListHead, kotlin/coroutines/Continuation, kotlinx/coroutines/selects/SelectBuilder, kotlinx/coroutines/selects/SelectInstance { +public final class kotlinx/coroutines/selects/SelectBuilderImpl : kotlinx/coroutines/internal/LockFreeLinkedListHead, kotlin/coroutines/Continuation, kotlin/coroutines/jvm/internal/CoroutineStackFrame, kotlinx/coroutines/selects/SelectBuilder, kotlinx/coroutines/selects/SelectInstance { public fun (Lkotlin/coroutines/Continuation;)V public fun disposeOnSelect (Lkotlinx/coroutines/DisposableHandle;)V + public fun getCallerFrame ()Lkotlin/coroutines/jvm/internal/CoroutineStackFrame; public fun getCompletion ()Lkotlin/coroutines/Continuation; public fun getContext ()Lkotlin/coroutines/CoroutineContext; public final fun getResult ()Ljava/lang/Object; + public fun getStackTraceElement ()Ljava/lang/StackTraceElement; public final fun handleBuilderException (Ljava/lang/Throwable;)V public fun invoke (Lkotlinx/coroutines/selects/SelectClause0;Lkotlin/jvm/functions/Function1;)V public fun invoke (Lkotlinx/coroutines/selects/SelectClause1;Lkotlin/jvm/functions/Function2;)V diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt index a36aae4198..472a5ee037 100644 --- a/kotlinx-coroutines-core/common/src/selects/Select.kt +++ b/kotlinx-coroutines-core/common/src/selects/Select.kt @@ -252,7 +252,11 @@ internal class SelectBuilderImpl( // Resumes in MODE_DIRECT override fun resumeWith(result: Result) { doResume({ result.toState() }) { - uCont.resumeWith(result) + if (result.isFailure) { + uCont.resumeWithStackTrace(result.exceptionOrNull()!!) + } else { + uCont.resumeWith(result) + } } } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt index f96da49e86..8c63c5b770 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt @@ -6,8 +6,8 @@ package kotlinx.coroutines.exceptions import kotlinx.coroutines.* import kotlinx.coroutines.channels.* +import kotlinx.coroutines.selects.* import org.junit.Test -import java.io.* import java.util.concurrent.* import kotlin.test.* @@ -192,4 +192,31 @@ class StackTraceRecoveryTest : TestBase() { innerMethod(deferred, *traces) assertTrue(true) } + + @Test + fun testSelect() = runTest { + expect(1) + val result = kotlin.runCatching { doSelect() } + expect(3) + verifyStackTrace(result.exceptionOrNull()!!, + "kotlinx.coroutines.RecoverableTestException\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$doSelect\$\$inlined\$select\$lambda\$1.invokeSuspend(StackTraceRecoveryTest.kt:211)\n" + + "\t(Coroutine boundary)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testSelect\$1.invokeSuspend(StackTraceRecoveryTest.kt:199)\n" + + "Caused by: kotlinx.coroutines.RecoverableTestException\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$doSelect\$\$inlined\$select\$lambda\$1.invokeSuspend(StackTraceRecoveryTest.kt:211)\n" + + "\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)") + finish(4) + } + + private suspend fun doSelect(): Int { + val job = CompletableDeferred(Unit) + return select { + job.onJoin { + yield() + expect(2) + throw RecoverableTestException() + } + } + } } From 3e4d808200e990e4b5c7e4755b23a5314fdb662a Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 15 Jan 2019 15:18:43 +0300 Subject: [PATCH 09/82] Call initCause during reflective exception copy in runCatching block to avoid DispatchException when initCause throws Fixes #933 --- .../jvm/src/internal/ExceptionsConstuctor.kt | 2 +- .../test/exceptions/StackTraceRecoveryTest.kt | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt index 5695060785..6ba4b07bee 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt @@ -35,7 +35,7 @@ internal fun tryCopyException(exception: E): E? { ctor = { e -> runCatching { constructor.newInstance(e) as E }.getOrNull() } break } else if (parameters.isEmpty()) { - ctor = { e -> runCatching { constructor.newInstance() as E }.getOrNull()?.also { it.initCause(e) } } + ctor = { e -> runCatching { (constructor.newInstance() as E).also { it.initCause(e) } }.getOrNull() } break } } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt index 8c63c5b770..501920a602 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt @@ -188,6 +188,34 @@ class StackTraceRecoveryTest : TestBase() { deferred.join() } + public class TrickyException() : Throwable() { + // To be sure ctor is never invoked + @Suppress("UNUSED", "UNUSED_PARAMETER") + private constructor(message: String, cause: Throwable): this() { + error("Should never be called") + } + + override fun initCause(cause: Throwable?): Throwable { + error("Can't call initCause") + } + } + + @Test + fun testThrowingInitCause() = runTest { + val deferred = async(NonCancellable) { + expect(2) + throw TrickyException() + } + + try { + expect(1) + deferred.await() + } catch (e: TrickyException) { + assertNull(e.cause) + finish(3) + } + } + private suspend fun outerScopedMethod(deferred: Deferred, vararg traces: String) = coroutineScope { innerMethod(deferred, *traces) assertTrue(true) From 4ba30cdd0c8b24fe620d9c5500deeda6fbe62049 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 1 Feb 2019 12:17:00 +0300 Subject: [PATCH 10/82] Stacktrace recovery improvements * Introduce CopyableThrowable to provide a mechanism for flexible exception cloning * Do not reflectively clone exceptions with additional non-static fields --- .../kotlinx-coroutines-core.txt | 4 ++ kotlinx-coroutines-core/jvm/src/Debug.kt | 28 ++++++++- .../jvm/src/internal/ExceptionsConstuctor.kt | 23 ++++++++ .../StackTraceRecoveryCustomExceptionsTest.kt | 57 +++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt 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 18041f72d0..1aa4f7a6c2 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -121,6 +121,10 @@ public final class kotlinx/coroutines/CompletionHandlerException : java/lang/Run public fun (Ljava/lang/String;Ljava/lang/Throwable;)V } +public abstract interface class kotlinx/coroutines/CopyableThrowable { + public abstract fun createCopy ()Ljava/lang/Throwable; +} + public final class kotlinx/coroutines/CoroutineContextKt { public static final fun newCoroutineContext (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext; } diff --git a/kotlinx-coroutines-core/jvm/src/Debug.kt b/kotlinx-coroutines-core/jvm/src/Debug.kt index ec464b2d7b..38a9d05177 100644 --- a/kotlinx-coroutines-core/jvm/src/Debug.kt +++ b/kotlinx-coroutines-core/jvm/src/Debug.kt @@ -4,8 +4,8 @@ package kotlinx.coroutines -import kotlin.coroutines.Continuation import kotlinx.coroutines.internal.* +import kotlin.coroutines.* /** * Name of the property that controls coroutine debugging. See [newCoroutineContext][CoroutineScope.newCoroutineContext]. @@ -26,6 +26,32 @@ public const val DEBUG_PROPERTY_NAME = "kotlinx.coroutines.debug" */ internal const val STACKTRACE_RECOVERY_PROPERTY_NAME = "kotlinx.coroutines.stacktrace.recovery" +/** + * Throwable which can be cloned during stacktrace recovery in a class-specific way. + * For additional information about stacktrace recovery see [STACKTRACE_RECOVERY_PROPERTY_NAME] + * + * Example of usage: + * ``` + * class BadResponseCodeException(val responseCode: Int) : Exception(), CopyableThrowable { + * + * override fun createCopy(): BadResponseCodeException { + * val result = BadResponseCodeException(responseCode) + * result.initCause(this) + * return result + * } + * ``` + */ +@ExperimentalCoroutinesApi +public interface CopyableThrowable where T : Throwable, T : CopyableThrowable { + + /** + * Creates a copy of the current instance. + * For better debuggability, it is recommended to use original exception as [cause][Throwable.cause] of the resulting one. + * Stacktrace of copied exception will be overwritten by stacktrace recovery machinery by [Throwable.setStackTrace] call. + */ + public fun createCopy(): T +} + /** * Automatic debug configuration value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext]. */ diff --git a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt index 6ba4b07bee..beb4d36f98 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt @@ -4,21 +4,35 @@ package kotlinx.coroutines.internal +import kotlinx.coroutines.* +import java.lang.reflect.* import java.util.* import java.util.concurrent.locks.* import kotlin.concurrent.* +private val throwableFields = Throwable::class.java.fieldsCountOrDefault(-1) private val cacheLock = ReentrantReadWriteLock() // Replace it with ClassValue when Java 6 support is over private val exceptionConstructors: WeakHashMap, (Throwable) -> Throwable?> = WeakHashMap() @Suppress("UNCHECKED_CAST") internal fun tryCopyException(exception: E): E? { + if (exception is CopyableThrowable<*>) { + return runCatching { exception.createCopy() as E }.getOrNull() + } + val cachedCtor = cacheLock.read { exceptionConstructors[exception.javaClass] } if (cachedCtor != null) return cachedCtor(exception) as E? + /* + * Skip reflective copy if an exception has additional fields (that are usually populated in user-defined constructors) + */ + if (throwableFields != exception.javaClass.fieldsCountOrDefault(0)) { + cacheLock.write { exceptionConstructors[exception.javaClass] = { null } } + return null + } /* * Try to reflectively find constructor(), constructor(message, cause) or constructor(cause). @@ -43,3 +57,12 @@ internal fun tryCopyException(exception: E): E? { cacheLock.write { exceptionConstructors[exception.javaClass] = (ctor ?: { null }) } return ctor?.invoke(exception) as E? } + +private fun Class<*>.fieldsCountOrDefault(defaultValue: Int) = kotlin.runCatching { fieldsCount() }.getOrDefault(defaultValue) + +private tailrec fun Class<*>.fieldsCount(accumulator: Int = 0): Int { + val fieldsCount = declaredFields.count { !Modifier.isStatic(it.modifiers) } + val totalFields = accumulator + fieldsCount + val superClass = superclass ?: return totalFields + return superClass.fieldsCount(totalFields) +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt new file mode 100644 index 0000000000..0d3781a684 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.exceptions + +import kotlinx.coroutines.* +import org.junit.Test +import kotlin.test.* + +@Suppress("UNREACHABLE_CODE", "UNUSED", "UNUSED_PARAMETER") +class StackTraceRecoveryCustomExceptionsTest : TestBase() { + + internal class NonCopyable(val customData: Int) : Throwable() { + // Bait + public constructor(cause: Throwable) : this(42) + } + + internal class Copyable(val customData: Int) : Throwable(), CopyableThrowable { + // Bait + public constructor(cause: Throwable) : this(42) + + override fun createCopy(): Copyable { + val copy = Copyable(customData) + copy.initCause(this) + return copy + } + } + + @Test + fun testStackTraceNotRecovered() = runTest { + try { + withContext(wrapperDispatcher(coroutineContext)) { + throw NonCopyable(239) + } + expectUnreached() + } catch (e: NonCopyable) { + assertEquals(239, e.customData) + assertNull(e.cause) + } + } + + @Test + fun testStackTraceRecovered() = runTest { + try { + withContext(wrapperDispatcher(coroutineContext)) { + throw Copyable(239) + } + expectUnreached() + } catch (e: Copyable) { + assertEquals(239, e.customData) + val cause = e.cause + assertTrue(cause is Copyable) + assertEquals(239, cause.customData) + } + } +} From 418ba80a7bb0b8661823fbb325b7edac526ab7db Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 1 Feb 2019 14:54:06 +0300 Subject: [PATCH 11/82] Additional documentation section about debug mode and stacktrace recovery. Not included in a guide intentionally --- README.md | 1 + docs/debugging.md | 73 +++++++++++++++++++++++++++++++++++++++++ docs/images/after.png | Bin 0 -> 297058 bytes docs/images/before.png | Bin 0 -> 161429 bytes 4 files changed, 74 insertions(+) create mode 100644 docs/debugging.md create mode 100644 docs/images/after.png create mode 100644 docs/images/before.png diff --git a/README.md b/README.md index 2cfd4475f5..7520e42a63 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ GlobalScope.launch { * [Guide to kotlinx.coroutines by example](docs/coroutines-guide.md) (**read it first**) * [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md) * [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md) + * [Debugging capabilities in kotlinx.coroutines](docs/debugging.md) * [Change log for kotlinx.coroutines](CHANGES.md) * [Coroutines design document (KEEP)](https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md) * [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines) diff --git a/docs/debugging.md b/docs/debugging.md new file mode 100644 index 0000000000..d3010c9dc6 --- /dev/null +++ b/docs/debugging.md @@ -0,0 +1,73 @@ +**Table of contents** + + + +* [Debugging coroutines](#debugging-coroutines) +* [Debug mode](#debug-mode) +* [Stacktrace recovery](#stacktrace-recovery) + * [Stacktrace recovery machinery](#stacktrace-recovery-machinery) +* [Debug agent](#debug-agent) + + + + +## Debugging coroutines +Asynchronous programming is hard and debugging asynchronous programs is even harder. +To improve user experience, `kotlinx.coroutines` comes with additional features for debugging: debug mode, stacktrace recovery +and debug agent. + +## Debug mode +The first debugging feature of `kotlinx.coroutines` is debug mode. +It can be enabled either by setting system property [DEBUG_PROPERTY_NAME] or by running Java with enabled assertions (`-ea` flag). +The latter is helpful to have debug mode enabled by default in unit tests. + +Debug mode attaches a unique [name][CoroutineName] to every launched coroutine, which then can be seen in a regular Java debugger, +a string representation of coroutine and thread name executing named coroutine. +Overhead of this feature is negligible and it can be safely turned on by default to simplify logging and diagnostic. + +## Stacktrace recovery +Stacktrace recovery is another useful feature of debug mode. It is enabled by default in the debug mode, +but can be separately disabled by setting `kotlinx.coroutines.stacktrace.recovery` system property to `false`. + +Stacktrace recovery tries to knit asynchronous exception stacktrace with a stacktrace of the receiver by copying it, providing +not only information where an exception was thrown, but also where it was asynchronously rethrown or caught . + +It is easy to demonstrate with actual stacktraces of the same program that awaits asynchronous operation in `main` function: + +| Without recovery | With recovery | +| - | - | +| ![before](images/before.png "before") | ![after](images/after.png "after") | + +The only downside of this approach is losing referential transparency of the exception. + +### Stacktrace recovery machinery +This section explains the inner mechanism of stacktrace recovery and can be skipped. + +When an exception is rethrown between coroutines (e.g. through `withContext` or `Deferred.await` boundary), stacktrace recovery +machinery tries to create a copy of the original exception (with the original exception as the cause), then rewrite stacktrace +of the copy with coroutine-related stack frames (using [Throwable.setStackTrace](https://docs.oracle.com/javase/9/docs/api/java/lang/Throwable.html#setStackTrace-java.lang.StackTraceElement:A-)) +and then throws resulting exception instead of the original one. + +Exception copy logic is straightforward: + 1) If exception class implements [CopyableThrowable], [CopyableThrowable.createCopy] is used. + 2) If exception class has class-specific fields not inherited from Throwable, the exception is not copied. + 3) Otherwise, one of the public exception's constructor is invoked reflectively with optional an `initCause` call. + +## Debug agent +[kotlinx-coroutines-debug](../kotlinx-coroutines-debug) module provides one of the most powerful debug capabilities in `kotlinx.coroutines`. + +This is a separate module with a JVM agent that keeps track of all alive coroutines, introspect and dump them similar to thread dump command, +additionally enhancing stacktraces with information where coroutine was created. + +The full tutorial of how to use debug agent can be found in a corresponding [readme](../kotlinx-coroutines-debug/README.md). + + + + + +[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 +[CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html +[CopyableThrowable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-copyable-throwable/index.html +[CopyableThrowable.createCopy]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-copyable-throwable/create-copy.html + + diff --git a/docs/images/after.png b/docs/images/after.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce15e8b4e635e033bca77ae40e66ae1f840c1ef GIT binary patch literal 297058 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\%9r~F@xR0pxIlbm#|}R&!7K# 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 z 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 k?8iUU9@mwxaPGn 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%0DlLDMhm2@vI1ZvbZ*FP+F%Eg+ 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 literal 0 HcmV?d00001 From a68376ceea89bc3599203a4c36e81cd177fc37cd Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 1 Feb 2019 18:13:39 +0300 Subject: [PATCH 12/82] Add section about Android in debug agent readme --- docs/debugging.md | 20 ++++++++++++++++++++ kotlinx-coroutines-debug/README.md | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/docs/debugging.md b/docs/debugging.md index d3010c9dc6..3424bca116 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -17,6 +17,7 @@ To improve user experience, `kotlinx.coroutines` comes with additional features and debug agent. ## Debug mode + The first debugging feature of `kotlinx.coroutines` is debug mode. It can be enabled either by setting system property [DEBUG_PROPERTY_NAME] or by running Java with enabled assertions (`-ea` flag). The latter is helpful to have debug mode enabled by default in unit tests. @@ -26,6 +27,7 @@ a string representation of coroutine and thread name executing named coroutine. Overhead of this feature is negligible and it can be safely turned on by default to simplify logging and diagnostic. ## Stacktrace recovery + Stacktrace recovery is another useful feature of debug mode. It is enabled by default in the debug mode, but can be separately disabled by setting `kotlinx.coroutines.stacktrace.recovery` system property to `false`. @@ -41,6 +43,7 @@ It is easy to demonstrate with actual stacktraces of the same program that await The only downside of this approach is losing referential transparency of the exception. ### Stacktrace recovery machinery + This section explains the inner mechanism of stacktrace recovery and can be skipped. When an exception is rethrown between coroutines (e.g. through `withContext` or `Deferred.await` boundary), stacktrace recovery @@ -54,6 +57,7 @@ Exception copy logic is straightforward: 3) Otherwise, one of the public exception's constructor is invoked reflectively with optional an `initCause` call. ## Debug agent + [kotlinx-coroutines-debug](../kotlinx-coroutines-debug) module provides one of the most powerful debug capabilities in `kotlinx.coroutines`. This is a separate module with a JVM agent that keeps track of all alive coroutines, introspect and dump them similar to thread dump command, @@ -61,7 +65,23 @@ additionally enhancing stacktraces with information where coroutine was created. The full tutorial of how to use debug agent can be found in a corresponding [readme](../kotlinx-coroutines-debug/README.md). +### Debug agent and Android + +Unfortunately, Android runtime does not support Instrument API necessary for `kotlinx-coroutines-debug` to function, triggering `java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;`. + +Nevertheless, it will be possible to support debug agent on Android as soon as [GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj) will support androin-gradle 3.3 + diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md index df5d6c3bee..8cd7be19e6 100644 --- a/kotlinx-coroutines-debug/README.md +++ b/kotlinx-coroutines-debug/README.md @@ -100,6 +100,24 @@ Dumping only deferred API is purely experimental and it is not guaranteed that it won't be changed (while it is marked as `@ExperimentalCoroutinesApi`). Do not use this module in production environment and do not rely on the format of the data produced by [DebugProbes]. +### Debug agent and Android + +Unfortunately, Android runtime does not support Instrument API necessary for `kotlinx-coroutines-debug` to function, triggering `java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory;`. + +Nevertheless, it will be possible to support debug agent on Android as soon as [GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj) will support androin-gradle 3.3 + + + [Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html From 4764e98975ab1e11e2039871d47742133eabc743 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 4 Feb 2019 12:39:34 +0300 Subject: [PATCH 13/82] Add documentation about our compatibility policy and experimental annotations Fixes #859 --- COMPATIBILITY.md | 25 ---- README.md | 4 +- docs/compatibility.md | 115 ++++++++++++++++++ docs/debugging.md | 3 +- .../common/src/Annotations.kt | 2 - .../jvm/src/internal/ExceptionsConstuctor.kt | 2 +- 6 files changed, 119 insertions(+), 32 deletions(-) delete mode 100644 COMPATIBILITY.md create mode 100644 docs/compatibility.md diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md deleted file mode 100644 index b7bcf0c4cf..0000000000 --- a/COMPATIBILITY.md +++ /dev/null @@ -1,25 +0,0 @@ -# Compatibility policy for kotlinx.coroutines - -All `kotlinx.coroutines` API comes into five flavors: stable, experimental, obsolete, internal and deprecated. - * **Deprecated** API is marked with `@Deprecated` and will be removed in `1.0.0` release. - * **Internal** API is marked with `@InternalCoroutinesApi`. It is intended to be used only by `kotlinx.coroutines` machinery and can (will) be broken without a warning. If you are using internal API, please tell us what problem you are trying to solve, so we can provide a stable alternative. - * **Experimental** API is marked with `ExperimentalCoroutinesApi`. Such API may have (known) design issues or we are unsure about its semantics. - Roughly speaking, there is a chance that those declarations will be deprecated in the near future or the semantics of their behavior may change in the way that may break some code. In that case, proper migration aid - will be provided for next several releases alongside with a stable alternative. - * **Obsolete** API is marked with `@ObsoleteCoroutinesApi`. This API is known to have some serious issues, so it will be replaced with a better alternative. - In the sense of migration and deprecation, it is equal to experimental. - * **Stable** API is public API without any annotations. This API is proven to be stable and it is not going to change. If at some point it will be discovered that such API has unfixable design flaws, - it will be gradually deprecated with proper replacement and migration aid, but won't be removed for at least a year. - -## Migration to 1.0.0 version with Kotlin 1.3 - -The main difference between Kotlin 1.2 and 1.3 is that coroutines are now -stable public API, and thus `kotlinx.coroutines` is leaving its "experimental" status. For that reason, future releases of `kotlinx.coroutines` will be available only for Kotlin 1.3. -Version `1.0.0` (starting with its release candidate build) will have all its deprecated declarations removed and `kotlinx.coroutines.experimental` package will be renamed to `kotlinx.coroutines` without functional changes. -In order to migrate `kotlinx.coroutines` to `1.0.0`, follow these steps: - -1. Update `kotlinx.coroutines` to `0.30.2` version. -2. Inspect compiler warnings about deprecated API and migrate it to a proposed alternative. Most of deprecated API has a corresponding replacement which can be applied from IDEA with quickfix. -3. Update Kotlin version to `1.3.0` and `kotlinx.coroutines` to version `0.30.2-eap13`. Then just get rid of `experimental` suffix in all imports. -4. Update `kotlinx.coroutines` to version `1.0.0` or to the corresponding release candidate of it). - \ No newline at end of file diff --git a/README.md b/README.md index 7520e42a63..e5cd4a7d07 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,6 @@ Library support for Kotlin coroutines with [multiplatform](#multiplatform) support. This is a companion version for Kotlin `1.3.20` release. -**NOTE**: `0.30.2` was the last release with Kotlin 1.2 and experimental coroutines. -See [COMPATIBILITY.md](COMPATIBILITY.md) for details of migration onto the stable Kotlin 1.3 coroutines. - ```kotlin GlobalScope.launch { delay(1000) @@ -58,6 +55,7 @@ GlobalScope.launch { * [Guide to UI programming with coroutines](ui/coroutines-guide-ui.md) * [Guide to reactive streams with coroutines](reactive/coroutines-guide-reactive.md) * [Debugging capabilities in kotlinx.coroutines](docs/debugging.md) +* [Compatibility policy and experimental annotations](docs/compatibility.md) * [Change log for kotlinx.coroutines](CHANGES.md) * [Coroutines design document (KEEP)](https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md) * [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines) diff --git a/docs/compatibility.md b/docs/compatibility.md new file mode 100644 index 0000000000..3dfe73a40c --- /dev/null +++ b/docs/compatibility.md @@ -0,0 +1,115 @@ + + + + +* [Compatibility](#compatibility) +* [Public API types](#public-api-types) + * [Experimental API](#experimental-api) + * [Obsolete API](#obsolete-api) + * [Internal API](#internal-api) + * [Stable API](#stable-api) + * [Deprecation cycle](#deprecation-cycle) +* [Using annotated API](#using-annotated-api) + * [Programmatically](#programmatically) + * [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. + + +## Public API types +`kotlinx.coroutines` public API comes in five flavours: stable, experimental, obsolete, internal and deprecated. +All public API except stable is marked with the corresponding annotation. + +### Experimental API +Experimental API is marked with [@ExperimentalCoroutinesApi][ExperimentalCoroutinesApi] annotation. +API is marked experimental when its design has potential open questions which may eventually lead to +either semantics changes of the API or its deprecation. + +By default, most of the new API is marked as experimental and becomes stable in one of the next major releases if no new issues arise. +Otherwise, either semantics is fixed without changes in ABI or API goes through deprecation cycle. + +When using experimental API may be dangerous: +* You are writing a library which depends on `kotlinx.coroutines` and want to use experimental coroutines API in a stable library API. +It may lead to undesired consequences when end users of your library update their `kotlinx.coroutines` version where experimental API +has slightly different semantics. +* You want to build core infrastructure of the application around experimental API. + +### Obsolete API +Obsolete API is marked with [@ObsoleteCoroutinesApi][ObsoleteCoroutinesApi] annotation. +Obsolete API is similar to experimental, but already known to have serious design flaws and its potential replacement, +but replacement is not yet implemented. + +The semantics of this API won't be changed, but it will go through a deprecation cycle as soon as the replacement is ready. + +### Internal API +Internal API is marked with [@InternalCoroutinesApi][InternalCoroutinesApi] or is part of `kotlinx.coroutines.internal` package. +This API has no guarantees on its stability, can and will be changed and/or removed in the future releases. +If you can't avoid using internal API, please report it to [issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues/new). + +### Stable API +Stable API is guaranteed to preserve its ABI and documented semantics. If at some point unfixable design flaws will be discovered, +this API will go through a deprecation cycle and remain binary compatible as long as possible. + +### Deprecation cycle +When some API is deprecated, it goes through multiple stages and there is at least one major release between stages. +* Feature is deprecated with compilation warning. Most of the time, proper replacement +(and corresponding `replaceWith` declaration) is provided to automatically migrate deprecated usages with a help of IntelliJ IDEA. +* Deprecation level is increased to `error` or `hidden`. It is no longer possible to compile new code against deprecated API, + though it is still present in the ABI. +* API is completely removed. While we give our best efforts not to do so and have no plans of removing any API, we still are leaving +this option in case of unforeseen problems such as security holes. + +## Using annotated API +All API annotations are [kotlin.Experimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-experimental/index.html). +It is done in order to produce compilation warning about using experimental or obsolete API. +Warnings can be disabled either programmatically for a specific call site or globally for the whole module. + +### Programmatically +For a specific call-site, warning can be disabled by using [UseExperimental](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-use-experimental/index.html) annotation: +```kotlin +@UseExperimental(ExperimentalCoroutinesApi::class) // Disables warning about experimental coroutines API +fun experimentalApiUsage() { + someKotlinxCoroutinesExperimentalMethod() +} +``` + +### Gradle +For the Gradle project, a warning can be disabled by passing a compiler flag in your `build.gradle` file: + +```groovy +tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all { + kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi"] +} + +``` + +### Maven +For the Maven project, a warning can be disabled by passing a compiler flag in your `pom.xml` file: +```xml + + kotlin-maven-plugin + org.jetbrains.kotlin + ... your configuration ... + + + -Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi + + + +``` + + + + +[ExperimentalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-experimental-coroutines-api/index.html +[ObsoleteCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-obsolete-coroutines-api/index.html +[InternalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-internal-coroutines-api/index.html + diff --git a/docs/debugging.md b/docs/debugging.md index 3424bca116..f9260d825c 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -7,6 +7,7 @@ * [Stacktrace recovery](#stacktrace-recovery) * [Stacktrace recovery machinery](#stacktrace-recovery-machinery) * [Debug agent](#debug-agent) + * [Debug agent and Android](#debug-agent-and-android) @@ -32,7 +33,7 @@ Stacktrace recovery is another useful feature of debug mode. It is enabled by de but can be separately disabled by setting `kotlinx.coroutines.stacktrace.recovery` system property to `false`. Stacktrace recovery tries to knit asynchronous exception stacktrace with a stacktrace of the receiver by copying it, providing -not only information where an exception was thrown, but also where it was asynchronously rethrown or caught . +not only information where an exception was thrown, but also where it was asynchronously rethrown or caught. It is easy to demonstrate with actual stacktraces of the same program that awaits asynchronous operation in `main` function: diff --git a/kotlinx-coroutines-core/common/src/Annotations.kt b/kotlinx-coroutines-core/common/src/Annotations.kt index 8d7b7c53e4..2b81146d29 100644 --- a/kotlinx-coroutines-core/common/src/Annotations.kt +++ b/kotlinx-coroutines-core/common/src/Annotations.kt @@ -30,8 +30,6 @@ public annotation class ObsoleteCoroutinesApi * Marks declarations that are **internal** in coroutines API, which means that should not be used outside of * `kotlinx.coroutines`, because their signatures and semantics will be changing between release without any * warnings and without providing any migration aids. - * - * @suppress **This an internal API and should not be used from general code.** */ @Retention(value = AnnotationRetention.BINARY) @Experimental(level = Experimental.Level.ERROR) diff --git a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt index beb4d36f98..5a0d8c43ad 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt @@ -65,4 +65,4 @@ private tailrec fun Class<*>.fieldsCount(accumulator: Int = 0): Int { val totalFields = accumulator + fieldsCount val superClass = superclass ?: return totalFields return superClass.fieldsCount(totalFields) -} \ No newline at end of file +} From 37f1b975cb8fdff56a40b258852c6b2e4dd8b444 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 16 Jan 2019 18:09:36 +0300 Subject: [PATCH 14/82] Fix typo in KDoc --- kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt | 2 +- kotlinx-coroutines-core/common/src/channels/Channel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt index bf5b36c1c9..01afc21262 100644 --- a/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt @@ -10,7 +10,7 @@ import kotlin.jvm.* /** * Channel with array buffer of a fixed [capacity]. - * Sender suspends only when buffer is fully and receiver suspends only when buffer is empty. + * Sender suspends only when buffer is full and receiver suspends only when buffer is empty. * * This channel is created by `Channel(capacity)` factory function invocation. * diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 389cece115..dbec12f09d 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -343,7 +343,7 @@ public interface ChannelIterator { * * * When `capacity` is positive, but less than [UNLIMITED] -- it creates array-based channel with given capacity. * This channel has an array buffer of a fixed `capacity`. - * Sender suspends only when buffer is fully and receiver suspends only when buffer is empty. + * Sender suspends only when buffer is full and receiver suspends only when buffer is empty. */ public interface Channel : SendChannel, ReceiveChannel { /** From 23eb49a54af3b61549fc8ffd4540350e5f5974a1 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 16 Jan 2019 19:25:33 +0300 Subject: [PATCH 15/82] Update documentation for Mutex.withLock to be consistent with Mutex.lock Fixes #940 --- kotlinx-coroutines-core/common/src/sync/Mutex.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index 0180956803..bb759925e8 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -100,7 +100,8 @@ public fun Mutex(locked: Boolean = false): Mutex = /** * Executes the given [action] under this mutex's lock. * - * @param owner Optional owner token for debugging. + * @param owner Optional owner token for debugging. When `owner` is specified (non-null value) and this mutex + * is already locked with the same token (same identity), this function throws [IllegalStateException]. * * @return the return value of the action. */ From d8f005ca84547251e0aa355ae49b0c253a060b4c Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 6 Feb 2019 17:53:39 +0300 Subject: [PATCH 16/82] Fixed jdk16Test --- kotlinx-coroutines-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index fd52c4237e..f0b655d033 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -80,7 +80,7 @@ task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) { classpath = files { jvmTest.classpath } testClassesDirs = files { jvmTest.testClassesDirs } executable = "$System.env.JDK_16/bin/java" - exclude '**/*LinearizabilityTest.*' + exclude '**/*LinearizabilityTest*.*' exclude '**/*LFTest.*' exclude '**/exceptions/**' exclude '**/ExceptionsGuideTest.*' From ee8bbfce4b80f99e16d8097185726ab523d0fd03 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 17 Jan 2019 15:54:39 +0300 Subject: [PATCH 17/82] Start lazy actor when calling close Rationale: While it is possible to atomically transition state machine to "completed", it has multiple caveats: * It breaks intuition that "close" allows actors to process remaining messages and call its body * It introduces one more internal API dependency * It makes behaviour of non-lazy and lazy actors inconsistent Fixes #939 --- .../jvm/src/channels/Actor.kt | 5 +++++ .../jvm/test/channels/ActorLazyTest.kt | 18 ++++++++++++++++++ .../jvm/test/channels/ActorTest.kt | 12 ++++++++++++ 3 files changed, 35 insertions(+) diff --git a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt index bcf25dcd49..cc5a51893d 100644 --- a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt +++ b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt @@ -156,6 +156,11 @@ private class LazyActorCoroutine( return super.offer(element) } + override fun close(cause: Throwable?): Boolean { + start() + return super.close(cause) + } + override val onSend: SelectClause2> get() = this diff --git a/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt index 9a04440695..1ec96ee5ab 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ActorLazyTest.kt @@ -61,4 +61,22 @@ class ActorLazyTest : TestBase() { assertThat(actor.isClosedForSend, IsEqual(true)) finish(6) } + + @Test + fun testCloseFreshActor() = runTest { + val job = launch { + expect(2) + val actor = actor(start = CoroutineStart.LAZY) { + expect(3) + for (i in channel) { } + expect(4) + } + + actor.close() + } + + expect(1) + job.join() + finish(5) + } } \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt index db08ddbbf7..7be7983203 100644 --- a/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt +++ b/kotlinx-coroutines-core/jvm/test/channels/ActorTest.kt @@ -169,4 +169,16 @@ class ActorTest(private val capacity: Int) : TestBase() { parent.join() finish(2) } + + @Test + fun testCloseFreshActor() = runTest { + for (start in CoroutineStart.values()) { + val job = launch { + val actor = actor(start = start) { for (i in channel) {} } + actor.close() + } + + job.join() + } + } } From cd2a8d7d899dce89849116d14d90de97b52add52 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Tue, 12 Feb 2019 15:17:17 +0300 Subject: [PATCH 18/82] Completable job (#971) CompletableJob support added Fixes #607 --- .../kotlinx-coroutines-core.txt | 22 ++++++++- .../common/src/CompletableDeferred.kt | 10 +++- .../common/src/CompletableJob.kt | 35 +++++++++++++ kotlinx-coroutines-core/common/src/Job.kt | 15 +++++- .../common/src/JobSupport.kt | 7 ++- .../common/src/Supervisor.kt | 16 +++--- .../common/test/CompletableJobTest.kt | 49 +++++++++++++++++++ 7 files changed, 140 insertions(+), 14 deletions(-) create mode 100644 kotlinx-coroutines-core/common/src/CompletableJob.kt create mode 100644 kotlinx-coroutines-core/common/test/CompletableJobTest.kt 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 18041f72d0..6e9c3798f1 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -117,6 +117,20 @@ public final class kotlinx/coroutines/CompletableDeferredKt { public static synthetic fun CompletableDeferred$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableDeferred; } +public abstract interface class kotlinx/coroutines/CompletableJob : kotlinx/coroutines/Job { + public abstract fun complete ()Z + public abstract fun completeExceptionally (Ljava/lang/Throwable;)Z +} + +public final class kotlinx/coroutines/CompletableJob$DefaultImpls { + public static synthetic fun cancel (Lkotlinx/coroutines/CompletableJob;)Z + public static fun fold (Lkotlinx/coroutines/CompletableJob;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static fun get (Lkotlinx/coroutines/CompletableJob;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element; + public static fun minusKey (Lkotlinx/coroutines/CompletableJob;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext; + public static fun plus (Lkotlinx/coroutines/CompletableJob;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext; + public static fun plus (Lkotlinx/coroutines/CompletableJob;Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job; +} + public final class kotlinx/coroutines/CompletionHandlerException : java/lang/RuntimeException { public fun (Ljava/lang/String;Ljava/lang/Throwable;)V } @@ -315,7 +329,9 @@ public final class kotlinx/coroutines/Job$Key : kotlin/coroutines/CoroutineConte public final class kotlinx/coroutines/JobKt { public static final fun DisposableHandle (Lkotlin/jvm/functions/Function0;)Lkotlinx/coroutines/DisposableHandle; - public static final fun Job (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job; + public static final fun Job (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob; + public static final synthetic fun Job (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job; + public static synthetic fun Job$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob; public static synthetic fun Job$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/Job; public static final fun cancel (Lkotlin/coroutines/CoroutineContext;)V public static final synthetic fun cancel (Lkotlin/coroutines/CoroutineContext;)Z @@ -422,7 +438,9 @@ public final class kotlinx/coroutines/RunnableKt { } public final class kotlinx/coroutines/SupervisorKt { - public static final fun SupervisorJob (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job; + public static final fun SupervisorJob (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob; + public static final synthetic fun SupervisorJob (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job; + public static synthetic fun SupervisorJob$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob; public static synthetic fun SupervisorJob$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/Job; public static final fun supervisorScope (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt b/kotlinx-coroutines-core/common/src/CompletableDeferred.kt index b7f821ba6d..b280b319be 100644 --- a/kotlinx-coroutines-core/common/src/CompletableDeferred.kt +++ b/kotlinx-coroutines-core/common/src/CompletableDeferred.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. */ @file:Suppress("DEPRECATION_ERROR") @@ -25,6 +25,10 @@ public interface CompletableDeferred : Deferred { * completed as a result of this invocation and `false` otherwise (if it was already completed). * * Repeated invocations of this function have no effect and always produce `false`. + * + * This function transitions this deferred into _completed_ state if it was not completed or cancelled yet. + * However, if this deferred has children, then it transitions into _completing_ state and becomes _complete_ + * once all its children are [complete][isCompleted]. See [Job] for details. */ public fun complete(value: T): Boolean @@ -33,6 +37,10 @@ public interface CompletableDeferred : Deferred { * completed as a result of this invocation and `false` otherwise (if it was already completed). * * Repeated invocations of this function have no effect and always produce `false`. + * + * This function transitions this deferred into _cancelled_ state if it was not completed or cancelled yet. + * However, that if this deferred has children, then it transitions into _cancelling_ state and becomes _cancelled_ + * once all its children are [complete][isCompleted]. See [Job] for details. */ public fun completeExceptionally(exception: Throwable): Boolean } diff --git a/kotlinx-coroutines-core/common/src/CompletableJob.kt b/kotlinx-coroutines-core/common/src/CompletableJob.kt new file mode 100644 index 0000000000..7f959910ce --- /dev/null +++ b/kotlinx-coroutines-core/common/src/CompletableJob.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines + +/** + * A job that can be completed using [complete()] function. + * It is returned by [Job()][Job] and [SupervisorJob()][SupervisorJob] constructor functions. + */ +public interface CompletableJob : Job { + /** + * Completes this job. The result is `true` if this job was completed as a result of this invocation and + * `false` otherwise (if it was already completed). + * + * Repeated invocations of this function have no effect and always produce `false`. + * + * This function transitions this job into _completed- state if it was not completed or cancelled yet. + * However, that if this job has children, then it transitions into _completing_ state and becomes _complete_ + * once all its children are [complete][isCompleted]. See [Job] for details. + */ + public fun complete(): Boolean + + /** + * Completes this job exceptionally with a given [exception]. The result is `true` if this job was + * completed as a result of this invocation and `false` otherwise (if it was already completed). + * + * Repeated invocations of this function have no effect and always produce `false`. + * + * This function transitions this job into _cancelled_ state if it was not completed or cancelled yet. + * However, that if this job has children, then it transitions into _cancelling_ state and becomes _cancelled_ + * once all its children are [complete][isCompleted]. See [Job] for details. + */ + public fun completeExceptionally(exception: Throwable): Boolean +} \ No newline at end of file diff --git a/kotlinx-coroutines-core/common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt index 31fe6e1d55..a428de8595 100644 --- a/kotlinx-coroutines-core/common/src/Job.kt +++ b/kotlinx-coroutines-core/common/src/Job.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. */ @file:JvmMultifileClass @@ -348,10 +348,21 @@ public interface Job : CoroutineContext.Element { * is cancelled when its parent fails or is cancelled. All this job's children are cancelled in this case, too. * The invocation of [cancel][Job.cancel] with exception (other than [CancellationException]) on this job also cancels parent. * + * Conceptually, the resulting job works in the same way as the job created by the `launch { body }` invocation + * (see [launch]), but without any code in the body. It is active until cancelled or completed. Invocation of + * [CompletableJob.complete] or [CompletableJob.completeExceptionally] corresponds to the successful or + * failed completion of the body of the coroutine. + * * @param parent an optional parent job. */ @Suppress("FunctionName") -public fun Job(parent: Job? = null): Job = JobImpl(parent) +public fun Job(parent: Job? = null): CompletableJob = JobImpl(parent) + +/** @suppress Binary compatibility only */ +@Suppress("FunctionName") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@JvmName("Job") +public fun Job0(parent: Job? = null): Job = Job(parent) /** * A handle to an allocated object that can be disposed to make it eligible for garbage collection. diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index 8504f84c6b..e79bd4b6f7 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.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. */ @file:Suppress("DEPRECATION_ERROR") @@ -1182,11 +1182,14 @@ private class Empty(override val isActive: Boolean) : Incomplete { override fun toString(): String = "Empty{${if (isActive) "Active" else "New" }}" } -internal class JobImpl(parent: Job? = null) : JobSupport(true) { +internal open class JobImpl(parent: Job?) : JobSupport(true), CompletableJob { init { initParentJobInternal(parent) } override val cancelsParent: Boolean get() = true override val onCancelComplete get() = true override val handlesException: Boolean get() = false + override fun complete() = makeCompleting(Unit) + override fun completeExceptionally(exception: Throwable): Boolean = + makeCompleting(CompletedExceptionally(exception)) } // -------- invokeOnCompletion nodes diff --git a/kotlinx-coroutines-core/common/src/Supervisor.kt b/kotlinx-coroutines-core/common/src/Supervisor.kt index f150737952..869859f7e7 100644 --- a/kotlinx-coroutines-core/common/src/Supervisor.kt +++ b/kotlinx-coroutines-core/common/src/Supervisor.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. */ @file:Suppress("DEPRECATION_ERROR") @@ -28,7 +28,13 @@ import kotlin.jvm.* * @param parent an optional parent job. */ @Suppress("FunctionName") -public fun SupervisorJob(parent: Job? = null) : Job = SupervisorJobImpl(parent) +public fun SupervisorJob(parent: Job? = null) : CompletableJob = SupervisorJobImpl(parent) + +/** @suppress Binary compatibility only */ +@Suppress("FunctionName") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@JvmName("SupervisorJob") +public fun SupervisorJob0(parent: Job? = null) : Job = SupervisorJob(parent) /** * Creates new [CoroutineScope] with [SupervisorJob] and calls the specified suspend block with this scope. @@ -46,11 +52,7 @@ public suspend fun supervisorScope(block: suspend CoroutineScope.() -> R): coroutine.startUndispatchedOrReturn(coroutine, block) } -private class SupervisorJobImpl(parent: Job?) : JobSupport(true) { - init { initParentJobInternal(parent) } - override val cancelsParent: Boolean get() = true - override val onCancelComplete get() = true - override val handlesException: Boolean get() = false +private class SupervisorJobImpl(parent: Job?) : JobImpl(parent) { override fun childCancelled(cause: Throwable): Boolean = false } diff --git a/kotlinx-coroutines-core/common/test/CompletableJobTest.kt b/kotlinx-coroutines-core/common/test/CompletableJobTest.kt new file mode 100644 index 0000000000..335e5d5672 --- /dev/null +++ b/kotlinx-coroutines-core/common/test/CompletableJobTest.kt @@ -0,0 +1,49 @@ +/* + * 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.test.* + +class CompletableJobTest { + @Test + fun testComplete() { + val job = Job() + assertTrue(job.isActive) + assertFalse(job.isCompleted) + assertTrue(job.complete()) + assertTrue(job.isCompleted) + assertFalse(job.isActive) + assertFalse(job.isCancelled) + assertFalse(job.complete()) + } + + @Test + fun testCompleteWithException() { + val job = Job() + assertTrue(job.isActive) + assertFalse(job.isCompleted) + assertTrue(job.completeExceptionally(TestException())) + assertTrue(job.isCompleted) + assertFalse(job.isActive) + assertTrue(job.isCancelled) + assertFalse(job.completeExceptionally(TestException())) + assertFalse(job.complete()) + } + + @Test + fun testCompleteWithChildren() { + val parent = Job() + val child = Job(parent) + assertTrue(parent.complete()) + assertFalse(parent.complete()) + assertTrue(parent.isActive) + assertFalse(parent.isCompleted) + assertTrue(child.complete()) + assertTrue(child.isCompleted) + assertTrue(parent.isCompleted) + assertFalse(child.isActive) + assertFalse(parent.isActive) + } +} \ No newline at end of file From 5bb8a4ef35ff5aceb94182bba2329f121f04eef8 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 12 Feb 2019 16:16:37 +0300 Subject: [PATCH 19/82] Properly close subscription on exception in Publisher.consumeEach --- .../kotlinx-coroutines-reactive/src/Channel.kt | 4 +--- .../test/IntegrationTest.kt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/reactive/kotlinx-coroutines-reactive/src/Channel.kt b/reactive/kotlinx-coroutines-reactive/src/Channel.kt index 1d8436bc08..66a8bc9adc 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Channel.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Channel.kt @@ -31,9 +31,7 @@ public fun Publisher.openSubscription(request: Int = 0): ReceiveChannel Publisher.consumeEach(action: (T) -> Unit) { - val channel = openSubscription() - for (x in channel) action(x) - channel.cancel() + openSubscription().consumeEach(action) } @Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") diff --git a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt index 6928011f58..a43352aa5f 100644 --- a/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt +++ b/reactive/kotlinx-coroutines-reactive/test/IntegrationTest.kt @@ -74,6 +74,24 @@ class IntegrationTest( assertThat(cnt, IsEqual(1)) } + @Test + fun testFailingConsumer() = runTest { + val pub = publish { + repeat(3) { + expect(it + 1) // expect(1), expect(2) *should* be invoked + send(it) + } + } + + try { + pub.consumeEach { + throw TestException() + } + } catch (e: TestException) { + finish(3) + } + } + @Test fun testNumbers() = runBlocking { val n = 100 * stressTestMultiplier From bf0219425db8c1c51018dd034331612dd6ffd834 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 6 Feb 2019 12:49:02 +0300 Subject: [PATCH 20/82] Updated webpack version for JS examples --- js/example-frontend-js/npm/package.json | 14 +++++++------- js/example-frontend-js/npm/webpack.config.js | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/js/example-frontend-js/npm/package.json b/js/example-frontend-js/npm/package.json index dd952f05d1..7668cefba3 100644 --- a/js/example-frontend-js/npm/package.json +++ b/js/example-frontend-js/npm/package.json @@ -6,14 +6,14 @@ "type": "git", "url": "https://github.com/Kotlin/kotlinx.coroutines.git" }, - "dependencies": { - "webpack": "3.10.0", - "html-webpack-plugin": "2.30.1", - "style-loader": "0.19.1", - "css-loader": "0.28.7" - }, "devDependencies": { - "webpack-dev-server": "2.9.7" + "webpack": "4.29.1", + "webpack-cli": "3.2.3", + "webpack-dev-server": "3.1.14", + "html-webpack-plugin": "3.2.0", + "uglifyjs-webpack-plugin": "2.1.1", + "style-loader": "0.23.1", + "css-loader": "2.1.0" }, "scripts": { "bundle": "webpack", diff --git a/js/example-frontend-js/npm/webpack.config.js b/js/example-frontend-js/npm/webpack.config.js index 294cfe0d6d..2124d875eb 100644 --- a/js/example-frontend-js/npm/webpack.config.js +++ b/js/example-frontend-js/npm/webpack.config.js @@ -12,6 +12,7 @@ const path = require("path"); const dist = path.resolve(__dirname, "dist"); module.exports = { + mode: "production", entry: { main: "main" }, From ee7325efa2201d4678f65aaed42bdaef3e645f65 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 15 Feb 2019 16:52:35 +0300 Subject: [PATCH 21/82] Use Exception(message) constructor for copying if possible The code is also refactored a bit to avoid repetition and long lines Fixes #987 --- .../jvm/src/internal/ExceptionsConstuctor.kt | 59 +++++++++++-------- .../StackTraceRecoveryCustomExceptionsTest.kt | 17 ++++++ 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt index 5a0d8c43ad..53c4d5dea8 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ExceptionsConstuctor.kt @@ -12,52 +12,65 @@ import kotlin.concurrent.* private val throwableFields = Throwable::class.java.fieldsCountOrDefault(-1) private val cacheLock = ReentrantReadWriteLock() +private typealias Ctor = (Throwable) -> Throwable? // Replace it with ClassValue when Java 6 support is over -private val exceptionConstructors: WeakHashMap, (Throwable) -> Throwable?> = WeakHashMap() +private val exceptionCtors: WeakHashMap, Ctor> = WeakHashMap() @Suppress("UNCHECKED_CAST") internal fun tryCopyException(exception: E): E? { + // Fast path for CopyableThrowable if (exception is CopyableThrowable<*>) { return runCatching { exception.createCopy() as E }.getOrNull() } - - val cachedCtor = cacheLock.read { - exceptionConstructors[exception.javaClass] + // Use cached ctor if found + cacheLock.read { exceptionCtors[exception.javaClass] }?.let { cachedCtor -> + return cachedCtor(exception) as E? } - - if (cachedCtor != null) return cachedCtor(exception) as E? /* * Skip reflective copy if an exception has additional fields (that are usually populated in user-defined constructors) */ if (throwableFields != exception.javaClass.fieldsCountOrDefault(0)) { - cacheLock.write { exceptionConstructors[exception.javaClass] = { null } } + cacheLock.write { exceptionCtors[exception.javaClass] = { null } } return null } - /* - * Try to reflectively find constructor(), constructor(message, cause) or constructor(cause). + * Try to reflectively find constructor(), constructor(message, cause), constructor(cause) or constructor(message). * Exceptions are shared among coroutines, so we should copy exception before recovering current stacktrace. */ - var ctor: ((Throwable) -> Throwable?)? = null + var ctor: Ctor? = null val constructors = exception.javaClass.constructors.sortedByDescending { it.parameterTypes.size } for (constructor in constructors) { - val parameters = constructor.parameterTypes - if (parameters.size == 2 && parameters[0] == String::class.java && parameters[1] == Throwable::class.java) { - ctor = { e -> runCatching { constructor.newInstance(e.message, e) as E }.getOrNull() } - break - } else if (parameters.size == 1 && parameters[0] == Throwable::class.java) { - ctor = { e -> runCatching { constructor.newInstance(e) as E }.getOrNull() } - break - } else if (parameters.isEmpty()) { - ctor = { e -> runCatching { (constructor.newInstance() as E).also { it.initCause(e) } }.getOrNull() } - break - } + ctor = createConstructor(constructor) + if (ctor != null) break } - - cacheLock.write { exceptionConstructors[exception.javaClass] = (ctor ?: { null }) } + // Store the resulting ctor to cache + cacheLock.write { exceptionCtors[exception.javaClass] = ctor ?: { null } } return ctor?.invoke(exception) as E? } +private fun createConstructor(constructor: Constructor<*>): Ctor? { + val p = constructor.parameterTypes + return when (p.size) { + 2 -> when { + p[0] == String::class.java && p[1] == Throwable::class.java -> + safeCtor { e -> constructor.newInstance(e.message, e) as Throwable } + else -> null + } + 1 -> when (p[0]) { + Throwable::class.java -> + safeCtor { e -> constructor.newInstance(e) as Throwable } + String::class.java -> + safeCtor { e -> (constructor.newInstance(e.message) as Throwable).also { it.initCause(e) } } + else -> null + } + 0 -> safeCtor { e -> (constructor.newInstance() as Throwable).also { it.initCause(e) } } + else -> null + } +} + +private inline fun safeCtor(crossinline block: (Throwable) -> Throwable): Ctor = + { e -> runCatching { block(e) }.getOrNull() } + private fun Class<*>.fieldsCountOrDefault(defaultValue: Int) = kotlin.runCatching { fieldsCount() }.getOrDefault(defaultValue) private tailrec fun Class<*>.fieldsCount(accumulator: Int = 0): Int { diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt index 0d3781a684..70336659e8 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryCustomExceptionsTest.kt @@ -54,4 +54,21 @@ class StackTraceRecoveryCustomExceptionsTest : TestBase() { assertEquals(239, cause.customData) } } + + internal class WithDefault(message: String = "default") : Exception(message) + + @Test + fun testStackTraceRecoveredWithCustomMessage() = runTest { + try { + withContext(wrapperDispatcher(coroutineContext)) { + throw WithDefault("custom") + } + expectUnreached() + } catch (e: WithDefault) { + assertEquals("custom", e.message) + val cause = e.cause + assertTrue(cause is WithDefault) + assertEquals("custom", cause.message) + } + } } From fd2b3e9e13c82699e1ea364c499120e79d2832cc Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 15 Feb 2019 18:45:18 +0300 Subject: [PATCH 22/82] Fixed test as this test exception is now eligible for copying, too --- integration/kotlinx-coroutines-play-services/test/TaskTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt index 0f42e7369f..15c302bb1f 100644 --- a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt +++ b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt @@ -140,7 +140,7 @@ class TaskTest : TestBase() { } catch (e: Exception) { assertTrue(e is TestException) assertEquals("something went wrong", e.message) - assertSame(e, deferred.getCompletionExceptionOrNull()) + assertSame(e.cause, deferred.getCompletionExceptionOrNull()) // debug mode stack augmentation } } From f5288985694ed4c6f1f19f09503280a38d7a80d7 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 18 Feb 2019 14:46:58 +0300 Subject: [PATCH 23/82] Update documentation --- docs/debugging.md | 26 +++++++++------- .../test/RecoveryExample.kt | 31 +++++++++++++++++++ 2 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 kotlinx-coroutines-debug/test/RecoveryExample.kt diff --git a/docs/debugging.md b/docs/debugging.md index f9260d825c..1067a37063 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -13,8 +13,8 @@ ## Debugging coroutines -Asynchronous programming is hard and debugging asynchronous programs is even harder. -To improve user experience, `kotlinx.coroutines` comes with additional features for debugging: debug mode, stacktrace recovery +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. ## Debug mode @@ -23,8 +23,9 @@ The first debugging feature of `kotlinx.coroutines` is debug mode. It can be enabled either by setting system property [DEBUG_PROPERTY_NAME] or by running Java with enabled assertions (`-ea` flag). The latter is helpful to have debug mode enabled by default in unit tests. -Debug mode attaches a unique [name][CoroutineName] to every launched coroutine, which then can be seen in a regular Java debugger, -a string representation of coroutine and thread name executing named coroutine. +Debug mode attaches a unique [name][CoroutineName] to every launched coroutine. +Coroutine name can be seen in a regular Java debugger, +in a string representation of the coroutine or in the thread name executing named coroutine. Overhead of this feature is negligible and it can be safely turned on by default to simplify logging and diagnostic. ## Stacktrace recovery @@ -32,10 +33,11 @@ Overhead of this feature is negligible and it can be safely turned on by default Stacktrace recovery is another useful feature of debug mode. It is enabled by default in the debug mode, but can be separately disabled by setting `kotlinx.coroutines.stacktrace.recovery` system property to `false`. -Stacktrace recovery tries to knit asynchronous exception stacktrace with a stacktrace of the receiver by copying it, providing +Stacktrace recovery tries to stitch asynchronous exception stacktrace with a stacktrace of the receiver by copying it, providing not only information where an exception was thrown, but also where it was asynchronously rethrown or caught. -It is easy to demonstrate with actual stacktraces of the same program that awaits asynchronous operation in `main` function: +It is easy to demonstrate with actual stacktraces of the same program that awaits asynchronous operation in `main` function +(runnable code is [here](../kotlinx-coroutines-debug/test/RecoveryExample.kt)): | Without recovery | With recovery | | - | - | @@ -50,21 +52,21 @@ This section explains the inner mechanism of stacktrace recovery and can be skip When an exception is rethrown between coroutines (e.g. through `withContext` or `Deferred.await` boundary), stacktrace recovery machinery tries to create a copy of the original exception (with the original exception as the cause), then rewrite stacktrace of the copy with coroutine-related stack frames (using [Throwable.setStackTrace](https://docs.oracle.com/javase/9/docs/api/java/lang/Throwable.html#setStackTrace-java.lang.StackTraceElement:A-)) -and then throws resulting exception instead of the original one. +and then throws the resulting exception instead of the original one. Exception copy logic is straightforward: - 1) If exception class implements [CopyableThrowable], [CopyableThrowable.createCopy] is used. - 2) If exception class has class-specific fields not inherited from Throwable, the exception is not copied. - 3) Otherwise, one of the public exception's constructor is invoked reflectively with optional an `initCause` call. + 1) If the exception class implements [CopyableThrowable], [CopyableThrowable.createCopy] is used. + 2) If the exception class has class-specific fields not inherited from Throwable, the exception is not copied. + 3) Otherwise, one of the public exception's constructor is invoked reflectively with an optional `initCause` call. ## Debug agent [kotlinx-coroutines-debug](../kotlinx-coroutines-debug) module provides one of the most powerful debug capabilities in `kotlinx.coroutines`. -This is a separate module with a JVM agent that keeps track of all alive coroutines, introspect and dump them similar to thread dump command, +This is a separate module with a JVM agent that keeps track of all alive coroutines, introspects and dumps them similar to thread dump command, additionally enhancing stacktraces with information where coroutine was created. -The full tutorial of how to use debug agent can be found in a corresponding [readme](../kotlinx-coroutines-debug/README.md). +The full tutorial of how to use debug agent can be found in the corresponding [readme](../kotlinx-coroutines-debug/README.md). ### Debug agent and Android diff --git a/kotlinx-coroutines-debug/test/RecoveryExample.kt b/kotlinx-coroutines-debug/test/RecoveryExample.kt new file mode 100644 index 0000000000..2280dd1694 --- /dev/null +++ b/kotlinx-coroutines-debug/test/RecoveryExample.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +@file:Suppress("PackageDirectoryMismatch") +package example + +import kotlinx.coroutines.* + +object PublicApiImplementation : CoroutineScope by CoroutineScope(CoroutineName("Example")) { + + private fun doWork(): Int { + error("Internal invariant failed") + } + + private fun asynchronousWork(): Int { + return doWork() + 1 + } + + public suspend fun awaitAsynchronousWorkInMainThread() { + val task = async(Dispatchers.Default) { + asynchronousWork() + } + + task.await() + } +} + +suspend fun main() { + // Try to switch debug mode on and off to see the difference + PublicApiImplementation.awaitAsynchronousWorkInMainThread() +} From 85c7f4d8cd5ed080d79e98f80e91c922c707ad86 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 19 Feb 2019 15:55:24 +0300 Subject: [PATCH 24/82] Fix typo in IllegalArgumentException message Fixes #995 --- reactive/kotlinx-coroutines-reactive/src/Await.kt | 2 +- reactive/kotlinx-coroutines-rx2/src/RxAwait.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reactive/kotlinx-coroutines-reactive/src/Await.kt b/reactive/kotlinx-coroutines-reactive/src/Await.kt index d5a968f703..d12a6280eb 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Await.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Await.kt @@ -117,7 +117,7 @@ private suspend fun Publisher.awaitOne( if (mode == Mode.SINGLE && seenValue) { subscription.cancel() if (cont.isActive) - cont.resumeWithException(IllegalArgumentException("More that one onNext value for $mode")) + cont.resumeWithException(IllegalArgumentException("More than one onNext value for $mode")) } else { value = t seenValue = true diff --git a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt index a8ee76a353..ce1040e911 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt @@ -187,7 +187,7 @@ private suspend fun ObservableSource.awaitOne( Mode.LAST, Mode.SINGLE -> { if (mode == Mode.SINGLE && seenValue) { if (cont.isActive) - cont.resumeWithException(IllegalArgumentException("More that one onNext value for $mode")) + cont.resumeWithException(IllegalArgumentException("More than one onNext value for $mode")) subscription.dispose() } else { value = t From 3b3be2c2483a4816bd460510ed939c84dc2d7393 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 19 Feb 2019 18:45:49 +0300 Subject: [PATCH 25/82] Remove merge leftover --- native/README.md | 62 ------------------------------------------------ 1 file changed, 62 deletions(-) delete mode 100644 native/README.md diff --git a/native/README.md b/native/README.md deleted file mode 100644 index 031b4336e1..0000000000 --- a/native/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Coroutines core for Kotlin/Native - -This directory contains modules that provide core coroutines support on Kotlin/Native. - -## Using in your projects - -Use [`org.jetbrains.kotlinx:kotlinx-coroutines-core-native:`](kotlinx-coroutines-core-native/README.md) -module in your Gradle/Maven dependencies. -Only single-threaded code (JS-style) is currently supported. - -Kotlin/Native libraries would only work under Gradle version 4.7 (**exactly**) -and you should use `kotlin-platform-native` plugin. - -First of all, you'll need to enable Gradle metadata in your -`settings.gradle` file: - -```groovy -enableFeaturePreview('GRADLE_METADATA') -``` - -Then, you'll need to apply the corresponding plugin and add appropriate dependencies in your -`build.gradle` file: - -```groovy -buildscript { - repositories { - jcenter() - maven { url 'https://plugins.gradle.org/m2/' } - maven { url 'https://dl.bintray.com/jetbrains/kotlin-native-dependencies' } - } - - dependencies { - classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version" - } - -} - -apply plugin: 'kotlin-platform-native' - -repositories { - jcenter() -} - -dependencies { - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.1.1' -} - -sourceSets { - main { - component { - targets = ["ios_arm64", "ios_arm32", "ios_x64", "macos_x64", "linux_x64", "mingw_x64"] - outputKinds = [EXECUTABLE] - } - } -} -``` - -Since Kotlin/Native does not generally provide binary compatibility between versions, -you should use the same version of Kotlin/Native compiler as was used to build `kotlinx.coroutines`. -Add an appropriate `kotlin_native_version` to your `gradle.properties` file. -See [gradle.properties](../gradle.properties). - From 703a286e8b55d353b4ebc84320710562d627c96b Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 19 Feb 2019 19:01:48 +0300 Subject: [PATCH 26/82] Check that worker thread belongs to the same scheduler in dispatchers.shutdown Fixes #990 --- .../jvm/src/scheduling/CoroutineScheduler.kt | 8 ++-- .../test/scheduling/SharingWorkerClassTest.kt | 46 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt index 18a91ad930..59c8250936 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt @@ -299,7 +299,7 @@ internal class CoroutineScheduler( // atomically set termination flag which is checked when workers are added or removed if (!_isTerminated.compareAndSet(0, 1)) return // make sure we are not waiting for the current thread - val currentWorker = Thread.currentThread() as? Worker + val currentWorker = currentWorker() // Capture # of created workers that cannot change anymore (mind the synchronized block!) val created = synchronized(workers) { createdWorkers } // Shutdown all workers with the only exception of the current thread @@ -481,9 +481,7 @@ internal class CoroutineScheduler( * Returns [ADDED], or [NOT_ADDED], or [ADDED_REQUIRES_HELP]. */ private fun submitToLocalQueue(task: Task, fair: Boolean): Int { - val worker = Thread.currentThread() as? Worker - ?: return NOT_ADDED - if (worker.scheduler !== this) return NOT_ADDED // different scheduler's worker (!!!) + val worker = currentWorker() ?: return NOT_ADDED /* * This worker could have been already terminated from this thread by close/shutdown and it should not @@ -533,6 +531,8 @@ internal class CoroutineScheduler( return ADDED_REQUIRES_HELP } + private fun currentWorker(): Worker? = (Thread.currentThread() as? Worker)?.takeIf { it.scheduler == this } + /** * Returns a string identifying the state of this scheduler for nicer debugging. * Note that this method is not atomic and represents rough state of pool. diff --git a/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt b/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt new file mode 100644 index 0000000000..6a66da9f5c --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/scheduling/SharingWorkerClassTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.scheduling + +import kotlinx.coroutines.* +import org.junit.Test +import kotlin.test.* + +class SharingWorkerClassTest : SchedulerTestBase() { + private val threadLocal = ThreadLocal() + + @Test + fun testSharedThread() = runTest { + val dispatcher = ExperimentalCoroutineDispatcher(1, schedulerName = "first") + val dispatcher2 = ExperimentalCoroutineDispatcher(1, schedulerName = "second") + + try { + withContext(dispatcher) { + assertNull(threadLocal.get()) + threadLocal.set(239) + withContext(dispatcher2) { + assertNull(threadLocal.get()) + threadLocal.set(42) + } + + assertEquals(239, threadLocal.get()) + } + } finally { + dispatcher.close() + dispatcher2.close() + } + } + + @Test(timeout = 5000L) + fun testProgress() = runTest { + // See #990 + val cores = Runtime.getRuntime().availableProcessors() + repeat(cores + 1) { + CoroutineScope(Dispatchers.Default).launch { + ExperimentalCoroutineDispatcher(1).close() + }.join() + } + } +} From 688aca460c89bb8025817a3627ec53eeb7052604 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 20 Feb 2019 11:31:30 +0300 Subject: [PATCH 27/82] Update to AtomicFU version 0.12.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7d2270e43e..af62a5b387 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ kotlin_native_version=1.3.20 # Dependencies junit_version=4.12 -atomicFU_version=0.12.1 +atomicFU_version=0.12.2 html_version=0.6.8 lincheck_version=2.0 dokka_version=0.9.16-rdev-2-mpp-hacks From f18878f632dd28ad8ff847eb4f95e9ed50f373bb Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 20 Feb 2019 11:43:23 +0300 Subject: [PATCH 28/82] Obtain real stacktrace of running coroutines in debug agent * Capture thread of coroutine when it's transited to running state * During dump retrieve the stacktrace of captured thread for running coroutines and merge it with metadata-based stacktrace Fixes #997 --- .../src/CoroutineState.kt | 12 +- .../src/internal/DebugProbesImpl.kt | 73 ++++++++- .../test/RunningThreadStackMergeTest.kt | 150 ++++++++++++++++++ .../test/SanitizedProbesTest.kt | 8 +- .../test/ScopedBuildersTest.kt | 7 +- .../test/StracktraceUtils.kt | 6 +- 6 files changed, 242 insertions(+), 14 deletions(-) create mode 100644 kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt diff --git a/kotlinx-coroutines-debug/src/CoroutineState.kt b/kotlinx-coroutines-debug/src/CoroutineState.kt index 3441de8319..9d4489d4be 100644 --- a/kotlinx-coroutines-debug/src/CoroutineState.kt +++ b/kotlinx-coroutines-debug/src/CoroutineState.kt @@ -39,6 +39,9 @@ public data class CoroutineState internal constructor( private var _state: State = State.CREATED + @JvmField + internal var lastObservedThread: Thread? = null + private var lastObservedFrame: CoroutineStackFrame? = null // Copy constructor @@ -66,9 +69,15 @@ public data class CoroutineState internal constructor( } internal fun updateState(state: State, frame: Continuation<*>) { - if (_state == state && lastObservedFrame != null) return + // Propagate only duplicating transitions to running for KT-29997 + if (_state == state && state == State.SUSPENDED && lastObservedFrame != null) return _state = state lastObservedFrame = frame as? CoroutineStackFrame + if (state == State.RUNNING) { + lastObservedThread = Thread.currentThread() + } else { + lastObservedThread = null + } } /** @@ -83,7 +92,6 @@ public data class CoroutineState internal constructor( frame.getStackTraceElement()?.let { result.add(sanitize(it)) } frame = frame.callerFrame } - return result } } diff --git a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt index 5c1aec1c7b..5c2c594f64 100644 --- a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt @@ -117,22 +117,89 @@ internal object DebugProbesImpl { .asSequence() .sortedBy { it.value.sequenceNumber } .forEach { (key, value) -> - val state = if (value.state == State.RUNNING) + val observedStackTrace = value.lastObservedStackTrace() + val enhancedStackTrace = enhanceStackTraceWithThreadDump(value, observedStackTrace) + val state = if (value.state == State.RUNNING && enhancedStackTrace === observedStackTrace) "${value.state} (Last suspension stacktrace, not an actual stacktrace)" else value.state.toString() append("\n\nCoroutine $key, state: $state") - val observedStackTrace = value.lastObservedStackTrace() if (observedStackTrace.isEmpty()) { append("\n\tat ${artificialFrame(ARTIFICIAL_FRAME_MESSAGE)}") printStackTrace(value.creationStackTrace) } else { - printStackTrace(value.lastObservedStackTrace()) + printStackTrace(enhancedStackTrace) } } } + /** + * Tries to enhance [coroutineTrace] (obtained by call to [CoroutineState.lastObservedStackTrace]) with + * thread dump of [CoroutineState.lastObservedThread]. + * + * Returns [coroutineTrace] if enhancement was unsuccessful or the enhancement result. + */ + private fun enhanceStackTraceWithThreadDump( + state: CoroutineState, + coroutineTrace: List + ): List { + val thread = state.lastObservedThread + if (state.state != State.RUNNING || thread == null) return coroutineTrace + // Avoid security manager issues + val actualTrace = runCatching { thread.stackTrace }.getOrNull() + ?: return coroutineTrace + + /* + * Here goes heuristic that tries to merge two stacktraces: real one + * (that has at least one but usually not so many suspend function frames) + * and coroutine one that has only suspend function frames. + * + * Heuristic: + * 1) Dump lastObservedThread + * 2) Find the next frame after BaseContinuationImpl.resumeWith (continuation machinery). + * Invariant: this method is called under the lock, so such method **should** be present + * in continuation stacktrace. + * + * 3) Find target method in continuation stacktrace (metadata-based) + * 4) Prepend dumped stacktrace (trimmed by target frame) to continuation stacktrace + * + * Heuristic may fail on recursion and overloads, but it will be automatically improved + * with KT-29997 + */ + val indexOfResumeWith = actualTrace.indexOfFirst { + it.className == "kotlin.coroutines.jvm.internal.BaseContinuationImpl" && + it.methodName == "resumeWith" && + it.fileName == "ContinuationImpl.kt" + } + + // We haven't found "BaseContinuationImpl.resumeWith" resume call in stacktrace + // This is some inconsistency in machinery, do not fail, fallback + val continuationFrame = actualTrace.getOrNull(indexOfResumeWith - 1) + ?: return coroutineTrace + + val continuationStartFrame = coroutineTrace.indexOfFirst { + it.fileName == continuationFrame.fileName && + it.className == continuationFrame.className && + it.methodName == continuationFrame.methodName + } + 1 + + if (continuationStartFrame == 0) return coroutineTrace + + val expectedSize = indexOfResumeWith + coroutineTrace.size - continuationStartFrame + val result = ArrayList(expectedSize) + + for (index in 0 until indexOfResumeWith) { + result += actualTrace[index] + } + + for (index in continuationStartFrame until coroutineTrace.size) { + result += coroutineTrace[index] + } + + return result + } + private fun StringBuilder.printStackTrace(frames: List) { frames.forEach { frame -> append("\n\tat $frame") diff --git a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt new file mode 100644 index 0000000000..b5e53bf3ec --- /dev/null +++ b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt @@ -0,0 +1,150 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +package kotlinx.coroutines.debug + +import kotlinx.coroutines.* +import org.junit.* +import org.junit.Test +import java.util.concurrent.* +import kotlin.test.* + +class RunningThreadStackMergeTest : TestBase() { + + private val testMainBlocker = CountDownLatch(1) // Test body blocks on it + private val coroutineBlocker = CyclicBarrier(2) // Launched coroutine blocks on it + + @Before + fun setUp() { + before() + DebugProbes.install() + } + + @After + fun tearDown() { + try { + DebugProbes.uninstall() + } finally { + onCompletion() + } + } + + @Test + fun testStackMergeWithContext() = runTest { + launchCoroutine() + awaitCoroutineStarted() + + verifyDump( + "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@62230679", // <- this one is ignored + "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@50284dc4, state: RUNNING\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" + + "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" + + "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:86)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.access\$nonSuspendingFun(RunningThreadStackMergeTest.kt:12)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$suspendingFunction\$2.invokeSuspend(RunningThreadStackMergeTest.kt:77)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunction(RunningThreadStackMergeTest.kt:75)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchCoroutine\$1.invokeSuspend(RunningThreadStackMergeTest.kt:68)\n" + + "\t(Coroutine creation stacktrace)\n" + + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", + ignoredCoroutine = "BlockingCoroutine" + ) + coroutineBlocker.await() + } + + private fun awaitCoroutineStarted() { + testMainBlocker.await() + while (coroutineBlocker.numberWaiting != 1) { + Thread.sleep(10) + } + } + + private fun CoroutineScope.launchCoroutine() { + launch(Dispatchers.Default) { + suspendingFunction() + assertTrue(true) + } + } + + private suspend fun suspendingFunction() { + // Typical use-case + withContext(Dispatchers.IO) { + yield() + nonSuspendingFun() + } + + assertTrue(true) + } + + private fun nonSuspendingFun() { + testMainBlocker.countDown() + coroutineBlocker.await() + } + + @Test + fun testStackMergeEscapeSuspendMethod() = runTest { + launchEscapingCoroutine() + awaitCoroutineStarted() + verifyDump( + "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@62230679", // <- this one is ignored + "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@3aea3c67, state: RUNNING\n" + + "\tat sun.misc.Unsafe.park(Native Method)\n" + + "\tat java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)\n" + + "\tat java.util.concurrent.locks.AbstractQueuedSynchronizer\$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)\n" + + "\tat java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234)\n" + + "\tat java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.nonSuspendingFun(RunningThreadStackMergeTest.kt:83)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.access\$nonSuspendingFun(RunningThreadStackMergeTest.kt:12)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$suspendingFunctionWithContext\$2.invokeSuspend(RunningThreadStackMergeTest.kt:124)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest.suspendingFunctionWithContext(RunningThreadStackMergeTest.kt:122)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$launchEscapingCoroutine\$1.invokeSuspend(RunningThreadStackMergeTest.kt:116)\n" + + "\t(Coroutine creation stacktrace)\n" + + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", + ignoredCoroutine = "BlockingCoroutine" + ) + coroutineBlocker.await() + } + + @Test + fun testRunBlocking() = runBlocking { + verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@4bcd176c, state: RUNNING\n" + + "\tat java.lang.Thread.getStackTrace(Thread.java:1552)\n" + + "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.enhanceStackTraceWithThreadDump(DebugProbesImpl.kt:147)\n" + + "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutines(DebugProbesImpl.kt:122)\n" + + "\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutines(DebugProbesImpl.kt:109)\n" + + "\tat kotlinx.coroutines.debug.DebugProbes.dumpCoroutines(DebugProbes.kt:122)\n" + + "\tat kotlinx.coroutines.debug.StracktraceUtilsKt.verifyDump(StracktraceUtils.kt)\n" + + "\tat kotlinx.coroutines.debug.StracktraceUtilsKt.verifyDump\$default(StracktraceUtils.kt)\n" + + "\tat kotlinx.coroutines.debug.RunningThreadStackMergeTest\$testRunBlocking\$1.invokeSuspend(RunningThreadStackMergeTest.kt:112)\n" + + "\t(Coroutine creation stacktrace)\n" + + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n") + } + + private fun CoroutineScope.launchEscapingCoroutine() { + launch(Dispatchers.Default) { + suspendingFunctionWithContext() + assertTrue(true) + } + } + + private suspend fun suspendingFunctionWithContext() { + withContext(Dispatchers.IO) { + actualSuspensionPoint() + nonSuspendingFun() + } + + assertTrue(true) + } + + private suspend fun actualSuspensionPoint() { + nestedSuspensionPoint() + assertTrue(true) + } + + private suspend fun nestedSuspensionPoint() { + yield() + assertTrue(true) + } +} diff --git a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt index 1eb815711a..4d35d02c50 100644 --- a/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt +++ b/kotlinx-coroutines-debug/test/SanitizedProbesTest.kt @@ -59,8 +59,8 @@ class SanitizedProbesTest : TestBase() { val deferred = createActiveDeferred() yield() verifyDump( - "Coroutine \"coroutine#3\":BlockingCoroutine{Active}@7d68ef40, state: RUNNING (Last suspension stacktrace, not an actual stacktrace)\n" + - "\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testCoroutinesDump\$1.invokeSuspend(SanitizedProbesTest.kt:58)\n" + + "Coroutine \"coroutine#3\":BlockingCoroutine{Active}@7d68ef40, state: RUNNING\n" + + "\tat java.lang.Thread.getStackTrace(Thread.java)\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" + @@ -90,7 +90,8 @@ class SanitizedProbesTest : TestBase() { expect(1) yield() expect(3) - verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@35fc6dc4, state: RUNNING (Last suspension stacktrace, not an actual stacktrace)\n" + + verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@35fc6dc4, state: RUNNING\n" + + "\tat java.lang.Thread.getStackTrace(Thread.java:1552)\n" + // Skip the rest "\t(Coroutine creation stacktrace)\n" + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)", @@ -121,7 +122,6 @@ class SanitizedProbesTest : TestBase() { delay(Long.MAX_VALUE) 1 } - } } } diff --git a/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt b/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt index d0657d7a5b..25b46339ad 100644 --- a/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt +++ b/kotlinx-coroutines-debug/test/ScopedBuildersTest.kt @@ -31,10 +31,9 @@ class ScopedBuildersTest : TestBase() { yield() yield() verifyDump( - "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@16612a51, state: RUNNING (Last suspension stacktrace, not an actual stacktrace)\n" + - "\tat kotlinx.coroutines.debug.ScopedBuildersTest\$testNestedScopes\$1.invokeSuspend(ScopedBuildersTest.kt:32)\n" + + "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@16612a51, state: RUNNING\n" + "\t(Coroutine creation stacktrace)\n" + - "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n", + "\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n", "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@6b53e23f, state: SUSPENDED\n" + "\tat kotlinx.coroutines.debug.ScopedBuildersTest\$doWithContext\$2.invokeSuspend(ScopedBuildersTest.kt:49)\n" + @@ -61,4 +60,4 @@ class ScopedBuildersTest : TestBase() { } expectUnreached() } -} \ No newline at end of file +} diff --git a/kotlinx-coroutines-debug/test/StracktraceUtils.kt b/kotlinx-coroutines-debug/test/StracktraceUtils.kt index baa48b038d..62dcd78d45 100644 --- a/kotlinx-coroutines-debug/test/StracktraceUtils.kt +++ b/kotlinx-coroutines-debug/test/StracktraceUtils.kt @@ -55,7 +55,7 @@ public fun toStackTrace(t: Throwable): String { public fun String.count(substring: String): Int = split(substring).size - 1 -public fun verifyDump(vararg traces: String) { +public fun verifyDump(vararg traces: String, ignoredCoroutine: String? = null) { val baos = ByteArrayOutputStream() DebugProbes.dumpCoroutines(PrintStream(baos)) val trace = baos.toString().split("\n\n") @@ -66,6 +66,10 @@ public fun verifyDump(vararg traces: String) { } // Drop "Coroutine dump" line trace.withIndex().drop(1).forEach { (index, value) -> + if (ignoredCoroutine != null && value.contains(ignoredCoroutine)) { + return@forEach + } + val expected = traces[index - 1].applyBackspace().split("\n\t(Coroutine creation stacktrace)\n", limit = 2) val actual = value.applyBackspace().split("\n\t(Coroutine creation stacktrace)\n", limit = 2) assertEquals(expected.size, actual.size) From 919284b159fec82ef2b6f4da9af5f88248e0713a Mon Sep 17 00:00:00 2001 From: Louis CAD Date: Tue, 19 Feb 2019 16:17:56 +0100 Subject: [PATCH 29/82] Update named arguments referenced issue The issue previously reference was marked as fixed for one of the two problems it was about, and a new one has been created for the remaining issue that is relevant here. --- kotlinx-coroutines-core/common/test/WithContextTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/test/WithContextTest.kt b/kotlinx-coroutines-core/common/test/WithContextTest.kt index b13d9b7bf2..c0460027e0 100644 --- a/kotlinx-coroutines-core/common/test/WithContextTest.kt +++ b/kotlinx-coroutines-core/common/test/WithContextTest.kt @@ -3,7 +3,7 @@ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913 +@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-22237 package kotlinx.coroutines From 3785348e32e7180efe86862bc84da14d3631a98d Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 20 Feb 2019 13:31:38 +0300 Subject: [PATCH 30/82] Reknit after fixing indentation in code samples --- kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt | 2 +- kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 07c0e97d9e..81e75a816f 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt @@ -20,7 +20,7 @@ fun main() = runBlocking { suspend fun concurrentSum(): Int = coroutineScope { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } - one.await() + two.await() + one.await() + two.await() } suspend fun doSomethingUsefulOne(): Int { 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 6fc92a2be1..63468421a9 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-06.kt @@ -28,5 +28,5 @@ suspend fun failedConcurrentSum(): Int = coroutineScope { println("Second child throws an exception") throw ArithmeticException() } - one.await() + two.await() + one.await() + two.await() } From 2bdd4605e797a88019565938cf4a4daca92593a5 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 20 Feb 2019 17:00:57 +0300 Subject: [PATCH 31/82] CoroutinesTimeout debug rule for JUnit 4 (#991) Fixes #938 --- README.md | 1 + .../kotlinx-coroutines-debug.txt | 12 ++ .../jvm/test/guide/example-compose-05.kt | 2 +- kotlinx-coroutines-debug/README.md | 34 ++++++ kotlinx-coroutines-debug/build.gradle | 1 + .../src/junit4/CoroutinesTimeout.kt | 60 ++++++++++ .../src/junit4/CoroutinesTimeoutStatement.kt | 89 +++++++++++++++ .../test/CoroutinesDumpTest.kt | 9 +- .../test/TestRuleExample.kt | 42 +++++++ .../test/junit4/CoroutinesTimeoutTest.kt | 56 ++++++++++ .../test/junit4/TestFailureValidation.kt | 104 ++++++++++++++++++ 11 files changed, 405 insertions(+), 5 deletions(-) create mode 100644 kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt create mode 100644 kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt create mode 100644 kotlinx-coroutines-debug/test/TestRuleExample.kt create mode 100644 kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt create mode 100644 kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt diff --git a/README.md b/README.md index e5cd4a7d07..66742d6912 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ GlobalScope.launch { * `Dispatchers.setMain` to override `Dispatchers.Main` in tests. * [debug](kotlinx-coroutines-debug/README.md) — debug utilities for coroutines. * `DebugProbes` API to probe, keep track of, print and dump active coroutines. + * `CoroutinesTimeout` test rule to automatically dump coroutines on test timeout. * [reactive](reactive/README.md) — modules that provide builders and iteration support for various reactive streams libraries: * Reactive Streams, RxJava 2.x, and Project Reactor. * [ui](ui/README.md) — modules that provide coroutine dispatchers for various single-threaded UI libraries: diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt index 3b05e69abc..96a35c7f83 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt @@ -38,3 +38,15 @@ public final class kotlinx/coroutines/debug/State : java/lang/Enum { public static fun values ()[Lkotlinx/coroutines/debug/State; } +public final class kotlinx/coroutines/debug/junit4/CoroutinesTimeout : org/junit/rules/TestRule { + public static final field Companion Lkotlinx/coroutines/debug/junit4/CoroutinesTimeout$Companion; + public fun (JZ)V + public synthetic fun (JZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun apply (Lorg/junit/runners/model/Statement;Lorg/junit/runner/Description;)Lorg/junit/runners/model/Statement; +} + +public final class kotlinx/coroutines/debug/junit4/CoroutinesTimeout$Companion { + public final fun seconds (IZ)Lkotlinx/coroutines/debug/junit4/CoroutinesTimeout; + public static synthetic fun seconds$default (Lkotlinx/coroutines/debug/junit4/CoroutinesTimeout$Companion;IZILjava/lang/Object;)Lkotlinx/coroutines/debug/junit4/CoroutinesTimeout; +} + 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 81e75a816f..3e73d2c6e6 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-compose-05.kt @@ -14,7 +14,7 @@ fun main() = runBlocking { println("The answer is ${concurrentSum()}") } println("Completed in $time ms") -//sampleEnd +//sampleEnd } suspend fun concurrentSum(): Int = coroutineScope { diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md index 8cd7be19e6..0dc413cd7d 100644 --- a/kotlinx-coroutines-debug/README.md +++ b/kotlinx-coroutines-debug/README.md @@ -22,6 +22,38 @@ dependencies { } ``` +### Using in unit tests + +For JUnit4 debug module provides special test rule, [CoroutinesTimeout], for installing debug probes +and to dump coroutines on timeout to simplify tests debugging. + +Its usage is better demonstrated by the example (runnable code is [here](test/TestRuleExample.kt)): + +```kotlin +class TestRuleExample { + @Rule + @JvmField + public val timeout = CoroutinesTimeout.seconds(1) + + private suspend fun someFunctionDeepInTheStack() { + withContext(Dispatchers.IO) { + delay(Long.MAX_VALUE) // Hang method + } + } + + @Test + fun hangingTest() = runBlocking { + val job = launch { + someFunctionDeepInTheStack() + } + job.join() // Join will hang + } +} +``` + +After 1 second, test will fail with `TestTimeoutException` and all coroutines (`runBlocking` and `launch`) and their +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. @@ -130,4 +162,6 @@ java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/Mana [DebugProbes.dumpCoroutinesState]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines-state.html [DebugProbes.printJob]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-job.html [DebugProbes.printScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-scope.html + +[CoroutinesTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug.junit4/-coroutines-timeout/index.html diff --git a/kotlinx-coroutines-debug/build.gradle b/kotlinx-coroutines-debug/build.gradle index d54b2b67df..e96cc6c634 100644 --- a/kotlinx-coroutines-debug/build.gradle +++ b/kotlinx-coroutines-debug/build.gradle @@ -5,6 +5,7 @@ apply plugin: "com.github.johnrengelman.shadow" dependencies { + compileOnly "junit:junit:$junit_version" compile "net.bytebuddy:byte-buddy:$byte_buddy_version" compile "net.bytebuddy:byte-buddy-agent:$byte_buddy_version" } diff --git a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt new file mode 100644 index 0000000000..c69becb24c --- /dev/null +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeout.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.debug.junit4 + +import kotlinx.coroutines.debug.* +import org.junit.rules.* +import org.junit.runner.* +import org.junit.runners.model.* +import java.util.concurrent.* + +/** + * Coroutines timeout rule for JUnit4 that is applied to all methods in the class. + * This rule is very similar to [Timeout] rule: it runs tests in a separate thread, + * fails tests after the given timeout and interrupts test thread. + * + * Additionally, this rule installs [DebugProbes] and dumps all coroutines at the moment of the timeout. + * It may cancel coroutines on timeout if [cancelOnTimeout] set to `true`. + * + * Example of usage: + * ``` + * class HangingTest { + * + * @Rule + * @JvmField + * val timeout = CoroutinesTimeout.seconds(5) + * + * @Test + * fun testThatHangs() = runBlocking { + * ... + * delay(Long.MAX_VALUE) // somewhere deep in the stack + * ... + * } + * } + * ``` + */ +public class CoroutinesTimeout( + private val testTimeoutMs: Long, + private val cancelOnTimeout: Boolean = false +) : TestRule { + + init { + require(testTimeoutMs > 0) { "Expected positive test timeout, but had $testTimeoutMs" } + } + + companion object { + /** + * Creates [CoroutinesTimeout] rule with the given timeout in seconds. + */ + public fun seconds(seconds: Int, cancelOnTimeout: Boolean = false): CoroutinesTimeout = + CoroutinesTimeout(TimeUnit.SECONDS.toMillis(seconds.toLong()), cancelOnTimeout) + } + + /** + * @suppress suppress from Dokka + */ + override fun apply(base: Statement, description: Description): Statement = + CoroutinesTimeoutStatement(base, description, testTimeoutMs, cancelOnTimeout) +} diff --git a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt new file mode 100644 index 0000000000..fd74fa96ec --- /dev/null +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.debug.junit4 + +import kotlinx.coroutines.debug.* +import org.junit.runner.* +import org.junit.runners.model.* +import java.util.concurrent.* + +internal class CoroutinesTimeoutStatement( + testStatement: Statement, + private val testDescription: Description, + private val testTimeoutMs: Long, + private val cancelOnTimeout: Boolean = false +) : Statement() { + + private val testStartedLatch = CountDownLatch(1) + + private val testResult = FutureTask { + testStartedLatch.countDown() + testStatement.evaluate() + } + + /* + * We are using hand-rolled thread instead of single thread executor + * in order to be able to safely interrupt thread in the end of a test + */ + private val testThread = Thread(testResult, "Timeout test thread").apply { isDaemon = true } + + override fun evaluate() { + DebugProbes.install() + testThread.start() + // Await until test is started to take only test execution time into account + testStartedLatch.await() + try { + testResult.get(testTimeoutMs, TimeUnit.MILLISECONDS) + return + } catch (e: TimeoutException) { + handleTimeout(testDescription) + } catch (e: ExecutionException) { + throw e.cause ?: e + } finally { + DebugProbes.uninstall() + } + } + + private fun handleTimeout(description: Description) { + val units = + if (testTimeoutMs % 1000 == 0L) + "${testTimeoutMs / 1000} seconds" + else "$testTimeoutMs milliseconds" + + val message = "Test ${description.methodName} timed out after $units" + System.err.println("\n$message\n") + System.err.flush() + + DebugProbes.dumpCoroutines() + System.out.flush() // Synchronize serr/sout + + /* + * Order is important: + * 1) Create exception with a stacktrace of hang test + * 2) Cancel all coroutines via debug agent API (changing system state!) + * 3) Throw created exception + */ + val exception = createTimeoutException(message, testThread) + cancelIfNecessary() + // If timed out test throws an exception, we can't do much except ignoring it + throw exception + } + + private fun cancelIfNecessary() { + if (cancelOnTimeout) { + DebugProbes.dumpCoroutinesState().forEach { + it.jobOrNull?.cancel() + } + } + } + + private fun createTimeoutException(message: String, thread: Thread): Exception { + val stackTrace = thread.stackTrace + val exception = TestTimedOutException(testTimeoutMs, TimeUnit.MILLISECONDS) + exception.stackTrace = stackTrace + thread.interrupt() + return exception + } +} diff --git a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt index 8a4f4e6962..dd4dc79b80 100644 --- a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt +++ b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt @@ -81,6 +81,7 @@ class CoroutinesDumpTest : TestBase() { fun testRunningCoroutineWithSuspensionPoint() = synchronized(monitor) { val deferred = GlobalScope.async { activeMethod(shouldSuspend = true) + yield() // tail-call } awaitCoroutineStarted() @@ -143,11 +144,11 @@ class CoroutinesDumpTest : TestBase() { private suspend fun activeMethod(shouldSuspend: Boolean) { nestedActiveMethod(shouldSuspend) - delay(1) + assertTrue(true) // tail-call } private suspend fun nestedActiveMethod(shouldSuspend: Boolean) { - if (shouldSuspend) delay(1) + if (shouldSuspend) yield() notifyTest() while (coroutineContext[Job]!!.isActive) { Thread.sleep(100) @@ -156,11 +157,11 @@ class CoroutinesDumpTest : TestBase() { private suspend fun sleepingOuterMethod() { sleepingNestedMethod() - delay(1) + yield() } private suspend fun sleepingNestedMethod() { - delay(1) + yield() notifyTest() delay(Long.MAX_VALUE) } diff --git a/kotlinx-coroutines-debug/test/TestRuleExample.kt b/kotlinx-coroutines-debug/test/TestRuleExample.kt new file mode 100644 index 0000000000..b5d1c262bf --- /dev/null +++ b/kotlinx-coroutines-debug/test/TestRuleExample.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +import kotlinx.coroutines.* +import kotlinx.coroutines.debug.junit4.* +import org.junit.* + +@Ignore // do not run it on CI +class TestRuleExample { + + @JvmField + @Rule + public val timeout = CoroutinesTimeout.seconds(1) + + private suspend fun someFunctionDeepInTheStack() { + withContext(Dispatchers.IO) { + delay(Long.MAX_VALUE) + println("This line is never executed") + } + + println("This line is never executed as well") + } + + @Test + fun hangingTest() = runBlocking { + val job = launch { + someFunctionDeepInTheStack() + } + + println("Doing some work...") + job.join() + } + + @Test + fun successfulTest() = runBlocking { + launch { + delay(10) + }.join() + } + +} diff --git a/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt new file mode 100644 index 0000000000..8d50c723cc --- /dev/null +++ b/kotlinx-coroutines-debug/test/junit4/CoroutinesTimeoutTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.debug.junit4 + +import junit4.* +import kotlinx.coroutines.* +import org.junit.* +import org.junit.runners.model.* + +class CoroutinesTimeoutTest : TestBase() { + + @Rule + @JvmField + public val validation = TestFailureValidation( + 1000, false, + TestResultSpec("throwingTest", error = RuntimeException::class.java), + TestResultSpec("successfulTest"), + TestResultSpec( + "hangingTest", expectedOutParts = listOf( + "Coroutines dump", + "Test hangingTest timed out after 1 seconds", + "BlockingCoroutine{Active}", + "runBlocking", + "at kotlinx.coroutines.debug.junit4.CoroutinesTimeoutTest.suspendForever", + "at kotlinx.coroutines.debug.junit4.CoroutinesTimeoutTest\$hangingTest\$1.invokeSuspend"), + notExpectedOutParts = listOf("delay", "throwingTest"), + error = TestTimedOutException::class.java) + ) + + @Test + fun hangingTest() = runBlocking { + suspendForever() + expectUnreached() + } + + private suspend fun suspendForever() { + delay(Long.MAX_VALUE) + expectUnreached() + } + + @Test + fun throwingTest() = runBlocking { + throw RuntimeException() + } + + @Test + fun successfulTest() = runBlocking { + val job = launch { + yield() + } + + job.join() + } +} diff --git a/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt b/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt new file mode 100644 index 0000000000..9084926993 --- /dev/null +++ b/kotlinx-coroutines-debug/test/junit4/TestFailureValidation.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package junit4 + +import kotlinx.coroutines.debug.* +import kotlinx.coroutines.debug.junit4.* +import org.junit.rules.* +import org.junit.runner.* +import org.junit.runners.model.* +import java.io.* +import kotlin.test.* + +internal fun TestFailureValidation(timeoutMs: Long, cancelOnTimeout: Boolean, vararg specs: TestResultSpec): RuleChain = + RuleChain + .outerRule(TestFailureValidation(specs.associateBy { it.testName })) + .around( + CoroutinesTimeout( + timeoutMs, + cancelOnTimeout + ) + ) + +/** + * Rule that captures test result, serr and sout and validates it against provided [testsSpec] + */ +internal class TestFailureValidation(private val testsSpec: Map) : TestRule { + + companion object { + init { + DebugProbes.sanitizeStackTraces = false + } + } + override fun apply(base: Statement, description: Description): Statement { + return TestFailureStatement(base, description) + } + + inner class TestFailureStatement(private val test: Statement, private val description: Description) : Statement() { + private lateinit var sout: PrintStream + private lateinit var serr: PrintStream + private val capturedOut = ByteArrayOutputStream() + + override fun evaluate() { + try { + replaceOut() + test.evaluate() + } catch (e: Throwable) { + validateFailure(e) + return + } finally { + resetOut() + } + + validateSuccess() // To avoid falling into catch + } + + private fun validateSuccess() { + val spec = testsSpec[description.methodName] ?: error("Test spec not found: ${description.methodName}") + require(spec.error == null) { "Expected exception of type ${spec.error}, but test successfully passed" } + + val captured = capturedOut.toString() + assertFalse(captured.contains("Coroutines dump")) + assertTrue(captured.isEmpty(), captured) + } + + private fun validateFailure(e: Throwable) { + val spec = testsSpec[description.methodName] ?: error("Test spec not found: ${description.methodName}") + if (spec.error == null || !spec.error.isInstance(e)) { + throw IllegalStateException("Unexpected failure, expected ${spec.error}, had ${e::class}", e) + } + + if (e !is TestTimedOutException) return + + val captured = capturedOut.toString() + assertTrue(captured.contains("Coroutines dump")) + for (part in spec.expectedOutParts) { + assertTrue(captured.contains(part), "Expected $part to be part of the\n$captured") + } + + for (part in spec.notExpectedOutParts) { + assertFalse(captured.contains(part), "Expected $part not to be part of the\n$captured") + } + } + + private fun replaceOut() { + sout = System.out + serr = System.err + + System.setOut(PrintStream(capturedOut)) + System.setErr(PrintStream(capturedOut)) + } + + private fun resetOut() { + System.setOut(sout) + System.setErr(serr) + } + } +} + +data class TestResultSpec( + val testName: String, val expectedOutParts: List = listOf(), val notExpectedOutParts: + List = listOf(), val error: Class? = null +) From 8d506b3757777664e007b1287ce3c4cb943f4ae5 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 20 Feb 2019 18:31:02 +0300 Subject: [PATCH 32/82] Make SupervisorCoroutine implement ScopeCoroutine * Implement ScopeCoroutine in SupervisorCoroutine * Do not indent scoped coroutines in debug strings Fixes #915 Fixes #916 --- .../common/src/AbstractCoroutine.kt | 3 +- .../common/src/Supervisor.kt | 18 ++----- .../test/exceptions/StackTraceRecoveryTest.kt | 6 ++- .../src/internal/DebugProbesImpl.kt | 24 ++++++---- kotlinx-coroutines-debug/test/ToStringTest.kt | 47 ++++++++++++++++++- 5 files changed, 72 insertions(+), 26 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt index 7d0e555e11..9454bdb797 100644 --- a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt @@ -37,7 +37,6 @@ public abstract class AbstractCoroutine( /** * Context of the parent coroutine. */ - @JvmField protected val parentContext: CoroutineContext, active: Boolean = true @@ -53,7 +52,7 @@ public abstract class AbstractCoroutine( */ public override val coroutineContext: CoroutineContext get() = context - override val isActive: Boolean get() = super.isActive + override val isActive: Boolean get() = super.isActive /** * Initializes parent job from the `parentContext` of this coroutine that was passed to it during construction. diff --git a/kotlinx-coroutines-core/common/src/Supervisor.kt b/kotlinx-coroutines-core/common/src/Supervisor.kt index 869859f7e7..d7443b6129 100644 --- a/kotlinx-coroutines-core/common/src/Supervisor.kt +++ b/kotlinx-coroutines-core/common/src/Supervisor.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines +import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* import kotlin.coroutines.* import kotlin.coroutines.intrinsics.* @@ -56,18 +57,9 @@ private class SupervisorJobImpl(parent: Job?) : JobImpl(parent) { override fun childCancelled(cause: Throwable): Boolean = false } -private class SupervisorCoroutine( - parentContext: CoroutineContext, - @JvmField val uCont: Continuation -) : AbstractCoroutine(parentContext, true) { - override val defaultResumeMode: Int get() = MODE_DIRECT +private class SupervisorCoroutine( + context: CoroutineContext, + uCont: Continuation +) : ScopeCoroutine(context, uCont) { override fun childCancelled(cause: Throwable): Boolean = false - - @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { - if (state is CompletedExceptionally) - uCont.resumeUninterceptedWithExceptionMode(state.cause, mode) - else - uCont.resumeUninterceptedMode(state as R, mode) - } } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt index 501920a602..18fed01a2f 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryTest.kt @@ -180,6 +180,7 @@ class StackTraceRecoveryTest : TestBase() { "\t(Coroutine boundary)\n" + "\tat kotlinx.coroutines.DeferredCoroutine.await\$suspendImpl(Builders.common.kt:99)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest.innerMethod(StackTraceRecoveryTest.kt:158)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$outerScopedMethod\$2\$1.invokeSuspend(StackTraceRecoveryTest.kt:193)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$outerScopedMethod\$2.invokeSuspend(StackTraceRecoveryTest.kt:151)\n" + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryTest\$testCoroutineScope\$1.invokeSuspend(StackTraceRecoveryTest.kt:141)\n", "Caused by: kotlinx.coroutines.RecoverableTestException\n" + @@ -217,7 +218,10 @@ class StackTraceRecoveryTest : TestBase() { } private suspend fun outerScopedMethod(deferred: Deferred, vararg traces: String) = coroutineScope { - innerMethod(deferred, *traces) + supervisorScope { + innerMethod(deferred, *traces) + assertTrue(true) + } assertTrue(true) } diff --git a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt index 5c2c594f64..c97515eefb 100644 --- a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt @@ -76,24 +76,32 @@ internal object DebugProbesImpl { private fun Job.build(map: Map, builder: StringBuilder, indent: String) { val state = map[this] - builder.append(indent) - @Suppress("DEPRECATION_ERROR") - val str = if (this !is JobSupport) toString() else toDebugString() - if (state == null) { + val newIndent: String + if (state == null) { // Append coroutine without stacktrace + // Do not print scoped coroutines and do not increase indentation level @Suppress("INVISIBLE_REFERENCE") - if (this !is kotlinx.coroutines.internal.ScopeCoroutine<*>) { // Do not print scoped coroutines - builder.append("$str\n") + if (this !is kotlinx.coroutines.internal.ScopeCoroutine<*>) { + builder.append("$indent$debugString\n") + newIndent = indent + "\t" + } else { + newIndent = indent } } else { + // Append coroutine with its last stacktrace element val element = state.lastObservedStackTrace().firstOrNull() val contState = state.state - builder.append("$str, continuation is $contState at line $element\n") + builder.append("$indent$debugString, continuation is $contState at line $element\n") + newIndent = indent + "\t" } + // Append children with new indent for (child in children) { - child.build(map, builder, indent + "\t") + child.build(map, builder, newIndent) } } + @Suppress("DEPRECATION_ERROR") // JobSupport + private val Job.debugString: String get() = if (this is JobSupport) toDebugString() else toString() + @Synchronized public fun dumpCoroutinesState(): List { check(isInstalled) { "Debug probes are not installed" } diff --git a/kotlinx-coroutines-debug/test/ToStringTest.kt b/kotlinx-coroutines-debug/test/ToStringTest.kt index d311ae98cb..0a9e84efad 100644 --- a/kotlinx-coroutines-debug/test/ToStringTest.kt +++ b/kotlinx-coroutines-debug/test/ToStringTest.kt @@ -29,6 +29,50 @@ class ToStringTest : TestBase() { } } + + private suspend fun CoroutineScope.launchNestedScopes(): Job { + return launch { + expect(1) + coroutineScope { + expect(2) + launchDelayed() + + supervisorScope { + expect(3) + launchDelayed() + } + } + } + } + + private fun CoroutineScope.launchDelayed(): Job { + return launch { + delay(Long.MAX_VALUE) + } + } + + @Test + fun testPrintHierarchyWithScopes() = runBlocking { + val tab = '\t' + val expectedString = """ + "coroutine":StandaloneCoroutine{Active}, continuation is SUSPENDED at line ToStringTest${'$'}launchNestedScopes$2$1.invokeSuspend(ToStringTest.kt) + $tab"coroutine":StandaloneCoroutine{Active}, continuation is SUSPENDED at line ToStringTest${'$'}launchDelayed$1.invokeSuspend(ToStringTest.kt) + $tab"coroutine":StandaloneCoroutine{Active}, continuation is SUSPENDED at line ToStringTest${'$'}launchDelayed$1.invokeSuspend(ToStringTest.kt) + """.trimIndent() + + val job = launchNestedScopes() + try { + repeat(5) { yield() } + val expected = expectedString.trimStackTrace().trimPackage() + expect(4) + assertEquals(expected, DebugProbes.jobToString(job).trimEnd().trimStackTrace().trimPackage()) + assertEquals(expected, DebugProbes.scopeToString(CoroutineScope(job)).trimEnd().trimStackTrace().trimPackage()) + } finally { + finish(5) + job.cancelAndJoin() + } + } + @Test fun testCompletingHierarchy() = runBlocking { val tab = '\t' @@ -62,8 +106,7 @@ class ToStringTest : TestBase() { assertEquals(expected, DebugProbes.jobToString(root).trimEnd().trimStackTrace().trimPackage()) assertEquals(expected, DebugProbes.scopeToString(CoroutineScope(root)).trimEnd().trimStackTrace().trimPackage()) - root.cancel() - root.join() + root.cancelAndJoin() finish(7) } From 0cab2fad725cec0b6f0bbfa3580d005cb7b9f703 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 22 Feb 2019 12:02:08 +0300 Subject: [PATCH 33/82] Rollback temporary teamcity repo --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 01b2ec1392..72ea1514fa 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,6 @@ buildscript { } repositories { jcenter() - maven { url "https://teamcity.jetbrains.com/guestAuth/app/rest/builds/id:1907319/artifacts/content/maven" } maven { url "https://kotlin.bintray.com/kotlinx" } maven { url "https://kotlin.bintray.com/kotlin-dev" } maven { url "https://kotlin.bintray.com/kotlin-eap" } @@ -79,7 +78,6 @@ allprojects { google() } jcenter() - maven { url "https://teamcity.jetbrains.com/guestAuth/app/rest/builds/id:1907319/artifacts/content/maven" } maven { url "https://kotlin.bintray.com/kotlin-dev" } maven { url "https://kotlin.bintray.com/kotlin-eap" } maven { url "https://kotlin.bintray.com/kotlinx" } From 63d1d1bbf65c3afc76c986fda923126023d8730d Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 22 Feb 2019 14:40:38 +0300 Subject: [PATCH 34/82] Use https in documentation and builds --- CHANGES.md | 6 +- README.md | 6 +- RELEASE.md | 4 +- benchmarks/build.gradle | 2 +- docs/coroutines-guide.md | 2 +- gradle/dokka.gradle | 2 +- gradle/maven-central.gradle | 4 +- js/example-frontend-js/README.md | 2 +- .../common/src/internal/Atomic.kt | 2 +- kotlinx-coroutines-core/js/npm/README.md | 2 +- .../jvm/src/internal/LockFreeLinkedList.kt | 2 +- reactive/README.md | 2 +- reactive/coroutines-guide-reactive.md | 56 +++++++++---------- .../kotlinx-coroutines-reactive/README.md | 4 +- .../kotlinx-coroutines-reactive/build.gradle | 2 +- reactive/kotlinx-coroutines-reactor/README.md | 2 +- reactive/kotlinx-coroutines-rx2/README.md | 2 +- reactive/kotlinx-coroutines-rx2/build.gradle | 2 +- site/README.md | 2 +- site/docs/index.md | 2 +- 20 files changed, 54 insertions(+), 54 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 43045c35c7..0f76a3a3d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -184,7 +184,7 @@ Visible consequences of include more robust exception handling for large corouti * Introduced IO dispatcher to offload blocking I/O-intensive tasks (see #79). * Introduced `ExecutorCoroutineDispatcher` instead of `CloseableCoroutineDispatcher` (see #385). * Built with Kotlin 1.2.61 and Kotlin/Native 0.8.2. -* JAR files for `kotlinx-coroutines` are now [JEP 238](http://openjdk.java.net/jeps/238) multi-release JAR files. +* JAR files for `kotlinx-coroutines` are now [JEP 238](https://openjdk.java.net/jeps/238) multi-release JAR files. * On JDK9+ `VarHandle` is used for atomic operations instead of `Atomic*FieldUpdater` for better performance. * See [AtomicFu](https://github.com/Kotlin/kotlinx.atomicfu/blob/master/README.md) project for details. * Reversed addition of `BlockingChecker` extension point to control where `runBlocking` can be used (see #227). @@ -221,7 +221,7 @@ Visible consequences of include more robust exception handling for large corouti * Includes multiple fixes to documentation contributed by @paolop, @SahilLone, @rocketraman, @bdavisx, @mtopolnik, @Groostav. * Experimental coroutines scheduler preview (JVM only): * Written from scratch and optimized for communicating coroutines. - * Performs significantly better than ForkJoinPool on coroutine benchmarks and for connected applications with [ktor](http://ktor.io). + * Performs significantly better than ForkJoinPool on coroutine benchmarks and for connected applications with [ktor](https://ktor.io). * Supports automatic creating of new threads for blocking operations running on the same thread pool (with an eye on solving #79), but there is no stable public API for it just yet. * For preview, run JVM with `-Dkotlinx.coroutines.scheduler` option. In this case `DefaultDispatcher` is set to new experimental scheduler instead of FJP-based `CommonPool`. * Submit your feedback to issue #261. @@ -514,7 +514,7 @@ Visible consequences of include more robust exception handling for large corouti * Fixed bug in internal class LockFreeLinkedList that resulted in ISE under stress in extremely rare circumstances. * Integrations: * [quasar](integration/kotlinx-coroutines-quasar): Introduced integration with suspendable JVM functions - that are instrumented with [Parallel Universe Quasar](http://docs.paralleluniverse.co/quasar/) + that are instrumented with [Parallel Universe Quasar](https://docs.paralleluniverse.co/quasar/) (thanks to the help of @pron). * [reactor](reactive/kotlinx-coroutines-reactor): Replaced deprecated `setCancellation` with `onDipose` and updated to Aluminium-SR3 release (courtesy of @yxf07, see #96) diff --git a/README.md b/README.md index 66742d6912..d2a3b2d18a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # kotlinx.coroutines -[![official JetBrains project](http://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)](http://www.apache.org/licenses/LICENSE-2.0) +[![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.1.1) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.1.1) Library support for Kotlin coroutines with [multiplatform](#multiplatform) support. @@ -59,7 +59,7 @@ GlobalScope.launch { * [Compatibility policy and experimental annotations](docs/compatibility.md) * [Change log for kotlinx.coroutines](CHANGES.md) * [Coroutines design document (KEEP)](https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md) -* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines) +* [Full kotlinx.coroutines API reference](https://kotlin.github.io/kotlinx.coroutines) ## Using in your projects diff --git a/RELEASE.md b/RELEASE.md index 3ab6c94de3..3ef2f7cff8 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -49,7 +49,7 @@ To release new `` of `kotlinx-coroutines`: * Wait until "Build" configuration for committed `master` branch passes tests. * Run "Deploy (Configure, RUN THIS ONE)" configuration with the corresponding new version. -2. In [GitHub](http://github.com/kotlin/kotlinx.coroutines) interface: +2. In [GitHub](https://github.com/kotlin/kotlinx.coroutines) interface: * Create new release named as ``. * Cut & paste lines from [`CHANGES.md`](CHANGES.md) into description. @@ -61,7 +61,7 @@ To release new `` of `kotlinx-coroutines`: * Wait until newly published version becomes the most recent. * Sync to Maven Central. -5. Announce new release in [Slack](http://kotlinlang.slack.com) +5. Announce new release in [Slack](https://kotlinlang.slack.com) 6. Switch into `develop` branch:
`git checkout develop` diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index 416bbe6b1a..a82ce226d8 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -7,7 +7,7 @@ apply plugin: "com.github.johnrengelman.shadow" apply plugin: "me.champeau.gradle.jmh" repositories { - maven { url "http://repo.typesafe.com/typesafe/releases/" } + maven { url "https://repo.typesafe.com/typesafe/releases/" } } jmh.jmhVersion = '1.21' diff --git a/docs/coroutines-guide.md b/docs/coroutines-guide.md index 8756246007..06bbcdbcff 100644 --- a/docs/coroutines-guide.md +++ b/docs/coroutines-guide.md @@ -29,4 +29,4 @@ In order to use coroutines as well as follow the examples in this guide, you nee * [Guide to UI programming with coroutines](../ui/coroutines-guide-ui.md) * [Guide to reactive streams with coroutines](../reactive/coroutines-guide-reactive.md) * [Coroutines design document (KEEP)](https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md) -* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines) +* [Full kotlinx.coroutines API reference](https://kotlin.github.io/kotlinx.coroutines) diff --git a/gradle/dokka.gradle b/gradle/dokka.gradle index 279f77ae45..051bc1c99a 100644 --- a/gradle/dokka.gradle +++ b/gradle/dokka.gradle @@ -9,7 +9,7 @@ def makeLinkMapping(dokka, projectDir) { dokka.linkMapping { def relPath = rootProject.projectDir.toPath().relativize(projectDir.toPath()) dir = "$projectDir/src" - url = "http://github.com/kotlin/kotlinx.coroutines/tree/master/$relPath/src" + url = "https://github.com/kotlin/kotlinx.coroutines/tree/master/$relPath/src" suffix = "#L" } } diff --git a/gradle/maven-central.gradle b/gradle/maven-central.gradle index 03602e9be5..4f9df6ab75 100644 --- a/gradle/maven-central.gradle +++ b/gradle/maven-central.gradle @@ -8,7 +8,7 @@ def pomConfig = { licenses { license { name "The Apache Software License, Version 2.0" - url "http://www.apache.org/licenses/LICENSE-2.0.txt" + url "https://www.apache.org/licenses/LICENSE-2.0.txt" distribution "repo" } } @@ -17,7 +17,7 @@ def pomConfig = { id "JetBrains" name "JetBrains Team" organization "JetBrains" - organizationUrl "http://www.jetbrains.com" + organizationUrl "https://www.jetbrains.com" } } diff --git a/js/example-frontend-js/README.md b/js/example-frontend-js/README.md index 51e8d360e6..4e534e427a 100644 --- a/js/example-frontend-js/README.md +++ b/js/example-frontend-js/README.md @@ -15,4 +15,4 @@ gradlew :example-frontend-js:start ``` Built and deployed application is available at the library documentation site -[here](http://kotlin.github.io/kotlinx.coroutines/example-frontend-js/index.html). +[here](https://kotlin.github.io/kotlinx.coroutines/example-frontend-js/index.html). diff --git a/kotlinx-coroutines-core/common/src/internal/Atomic.kt b/kotlinx-coroutines-core/common/src/internal/Atomic.kt index 61a7b730e1..b589db2834 100644 --- a/kotlinx-coroutines-core/common/src/internal/Atomic.kt +++ b/kotlinx-coroutines-core/common/src/internal/Atomic.kt @@ -26,7 +26,7 @@ private val NO_DECISION: Any = Symbol("NO_DECISION") /** * Descriptor for multi-word atomic operation. * Based on paper - * ["A Practical Multi-Word Compare-and-Swap Operation"](http://www.cl.cam.ac.uk/research/srgnetos/papers/2002-casn.pdf) + * ["A Practical Multi-Word Compare-and-Swap Operation"](https://www.cl.cam.ac.uk/research/srg/netos/papers/2002-casn.pdf) * by Timothy L. Harris, Keir Fraser and Ian A. Pratt. * * Note: parts of atomic operation must be globally ordered. Otherwise, this implementation will produce diff --git a/kotlinx-coroutines-core/js/npm/README.md b/kotlinx-coroutines-core/js/npm/README.md index c048ea285c..23ee049a77 100644 --- a/kotlinx-coroutines-core/js/npm/README.md +++ b/kotlinx-coroutines-core/js/npm/README.md @@ -13,4 +13,4 @@ launch { ## Documentation * [Guide to kotlinx.coroutines by example on JVM](https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md) (**read it first**) -* [Full kotlinx.coroutines API reference](http://kotlin.github.io/kotlinx.coroutines) +* [Full kotlinx.coroutines API reference](https://kotlin.github.io/kotlinx.coroutines) diff --git a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt index 5c8446f65b..7d765b9701 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/LockFreeLinkedList.kt @@ -41,7 +41,7 @@ public actual typealias AbstractAtomicDesc = LockFreeLinkedListNode.AbstractAtom /** * 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"](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.140.4693&rep=rep1&type=pdf) + * ["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. * * Important notes: diff --git a/reactive/README.md b/reactive/README.md index 08ff862df1..8679a2b078 100644 --- a/reactive/README.md +++ b/reactive/README.md @@ -5,6 +5,6 @@ Module name below corresponds to the artifact name in Maven/Gradle. ## Modules -* [kotlinx-coroutines-reactive](kotlinx-coroutines-reactive/README.md) -- utilities for [Reactive Streams](http://www.reactive-streams.org) +* [kotlinx-coroutines-reactive](kotlinx-coroutines-reactive/README.md) -- utilities for [Reactive Streams](https://www.reactive-streams.org) * [kotlinx-coroutines-reactor](kotlinx-coroutines-reactor/README.md) -- utilities for [Reactor](https://projectreactor.io) * [kotlinx-coroutines-rx2](kotlinx-coroutines-rx2/README.md) -- utilities for [RxJava 2.x](https://github.com/ReactiveX/RxJava) diff --git a/reactive/coroutines-guide-reactive.md b/reactive/coroutines-guide-reactive.md index 8935d4a74b..b9114da9bf 100644 --- a/reactive/coroutines-guide-reactive.md +++ b/reactive/coroutines-guide-reactive.md @@ -28,11 +28,11 @@ a better introduction into the world of coroutines. There are several modules in `kotlinx.coroutines` project that are related to reactive streams: -* [kotlinx-coroutines-reactive](kotlinx-coroutines-reactive) -- utilities for [Reactive Streams](http://www.reactive-streams.org) +* [kotlinx-coroutines-reactive](kotlinx-coroutines-reactive) -- utilities for [Reactive Streams](https://www.reactive-streams.org) * [kotlinx-coroutines-reactor](kotlinx-coroutines-reactor) -- utilities for [Reactor](https://projectreactor.io) * [kotlinx-coroutines-rx2](kotlinx-coroutines-rx2) -- utilities for [RxJava 2.x](https://github.com/ReactiveX/RxJava) -This guide is mostly based on [Reactive Streams](http://www.reactive-streams.org) specification and uses +This guide is mostly based on [Reactive Streams](https://www.reactive-streams.org) specification and uses its `Publisher` interface with some examples based on [RxJava 2.x](https://github.com/ReactiveX/RxJava), which implements reactive streams specification. @@ -75,8 +75,8 @@ This section outlines key differences between reactive streams and coroutine-bas The [Channel] is somewhat similar concept to the following reactive stream classes: * Reactive stream [Publisher](https://github.com/reactive-streams/reactive-streams-jvm/blob/master/api/src/main/java/org/reactivestreams/Publisher.java); -* Rx Java 1.x [Observable](http://reactivex.io/RxJava/javadoc/rx/Observable.html); -* Rx Java 2.x [Flowable](http://reactivex.io/RxJava/2.x/javadoc/), which implements `Publisher`. +* Rx Java 1.x [Observable](https://reactivex.io/RxJava/javadoc/rx/Observable.html); +* Rx Java 2.x [Flowable](https://reactivex.io/RxJava/2.x/javadoc/), which implements `Publisher`. They all describe an asynchronous stream of elements (aka items in Rx), either infinite or finite, and all of them support backpressure. @@ -140,7 +140,7 @@ from it again cannot receive anything. Let us rewrite this code using [publish] coroutine builder from `kotlinx-coroutines-reactive` module instead of [produce] from `kotlinx-coroutines-core` module. The code stays the same, but where `source` used to have [ReceiveChannel] type, it now has reactive streams -[Publisher](http://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Publisher.html) +[Publisher](https://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Publisher.html) type. Here we've used Rx -[subscribe](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html#subscribe(io.reactivex.functions.Consumer)) +[subscribe](https://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html#subscribe(io.reactivex.functions.Consumer)) operator that does not have its own scheduler and operates on the same thread that the publisher -- on a default shared pool of threads in this example. ### Rx observeOn In Rx you use special operators to modify the threading context for operations in the chain. You -can find some [good guides](http://tomstechnicalblog.blogspot.ru/2016/02/rxjava-understanding-observeon-and.html) +can find some [good guides](https://tomstechnicalblog.blogspot.ru/2016/02/rxjava-understanding-observeon-and.html) about them, if you are not familiar. For example, there is -[observeOn](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html#observeOn(io.reactivex.Scheduler)) +[observeOn](https://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html#observeOn(io.reactivex.Scheduler)) operator. Let us modify the previous example to observe using `Schedulers.computation()`: *
[Exception handling](docs/exception-handling.md#exception-handling) diff --git a/docs/coroutine-context-and-dispatchers.md b/docs/coroutine-context-and-dispatchers.md index c1eca31354..20e0558d70 100644 --- a/docs/coroutine-context-and-dispatchers.md +++ b/docs/coroutine-context-and-dispatchers.md @@ -30,7 +30,7 @@ class DispatchersGuideTest { * [Parental responsibilities](#parental-responsibilities) * [Naming coroutines for debugging](#naming-coroutines-for-debugging) * [Combining context elements](#combining-context-elements) - * [Cancellation via explicit job](#cancellation-via-explicit-job) + * [Getting it together](#getting-it-together) * [Thread-local data](#thread-local-data) @@ -487,48 +487,43 @@ I'm working in thread DefaultDispatcher-worker-1 @test#2 -### Cancellation via explicit job +### Getting it together Let us put our knowledge about contexts, children and jobs together. Assume that our application has an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application and launch various coroutines in the context of an Android activity to perform asynchronous operations to fetch and update data, do animations, etc. All of these coroutines must be cancelled when activity is destroyed -to avoid memory leaks. - -We manage a lifecycle of our coroutines by creating an instance of [Job] that is tied to -the lifecycle of our activity. A job instance is created using [Job()] factory function when -activity is created and it is cancelled when an activity is destroyed like this: +to avoid memory leaks. We, of course, can manipulate contexts and jobs manually to tie activity's +and coroutines lifecycles, but `kotlinx.coroutines` provides an abstraction that encapsulates that: [CoroutineScope]. +You should be already familiar with coroutine scope as all coroutine builders are declared as extensions on it. +We manage a lifecycle of our coroutines by creating an instance of [CoroutineScope] that is tied to +the lifecycle of our activity. `CoroutineScope` instance can be created by [CoroutineScope()] or [MainScope()] +factory functions. The former creates a general-purpose scope, while the latter creates scope for UI applications and uses +[Dispatchers.Main] as default dispatcher:

```kotlin -class Activity : CoroutineScope { - lateinit var job: Job - - fun create() { - job = Job() - } - +class Activity { + private val mainScope = MainScope() + fun destroy() { - job.cancel() + mainScope.cancel() } // to be continued ... ```
-We also implement [CoroutineScope] interface in this `Actvity` class. We only need to provide an override -for its [CoroutineScope.coroutineContext] property to specify the context for coroutines launched in its -scope. We combine the desired dispatcher (we used [Dispatchers.Default] in this example) and a job: +We can implement [CoroutineScope] interface in this `Actvity` class. The best way to do it is +to use delegation with default factory functions. +We also can combine the desired dispatcher (we used [Dispatchers.Default] in this example) with the scope:
```kotlin - // class Activity continues - override val coroutineContext: CoroutineContext - get() = Dispatchers.Default + job - // to be continued ... + class Activity : CoroutineScope by CoroutineScope(Dispatchers.Default) ```
@@ -566,23 +561,13 @@ onto the screen anymore if we wait: import kotlin.coroutines.* import kotlinx.coroutines.* -class Activity : CoroutineScope { - lateinit var job: Job - - fun create() { - job = Job() - } +class Activity : CoroutineScope by CoroutineScope(Dispatchers.Default) { fun destroy() { - job.cancel() + cancel() // Extension on CoroutineScope } // to be continued ... - // class Activity continues - override val coroutineContext: CoroutineContext - get() = Dispatchers.Default + job - // to be continued ... - // class Activity continues fun doSomething() { // launch ten coroutines for a demo, each working for a different time @@ -598,7 +583,6 @@ class Activity : CoroutineScope { fun main() = runBlocking { //sampleStart val activity = Activity() - activity.create() // create an activity activity.doSomething() // run test function println("Launched coroutines") delay(500L) // delay for half a second @@ -712,7 +696,9 @@ that should be implemented. [CoroutineScope.coroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/coroutine-context.html [Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html [CoroutineName]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html -[Job()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job.html +[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope.html +[MainScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html +[Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html [asContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/as-context-element.html [ThreadContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/index.html 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 61b66c4a39..5a7b3d5831 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-10.kt @@ -8,23 +8,13 @@ package kotlinx.coroutines.guide.context10 import kotlin.coroutines.* import kotlinx.coroutines.* -class Activity : CoroutineScope { - lateinit var job: Job - - fun create() { - job = Job() - } +class Activity : CoroutineScope by CoroutineScope(Dispatchers.Default) { fun destroy() { - job.cancel() + cancel() // Extension on CoroutineScope } // to be continued ... - // class Activity continues - override val coroutineContext: CoroutineContext - get() = Dispatchers.Default + job - // to be continued ... - // class Activity continues fun doSomething() { // launch ten coroutines for a demo, each working for a different time @@ -40,7 +30,6 @@ class Activity : CoroutineScope { fun main() = runBlocking { //sampleStart val activity = Activity() - activity.create() // create an activity activity.doSomething() // run test function println("Launched coroutines") delay(500L) // delay for half a second From e9123ca4873a8c2f688e0da78d038df73dd50025 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 1 Mar 2019 15:40:16 +0300 Subject: [PATCH 59/82] Improve CoroutineScope documentation: mention job convention, get rid of lateinit example, discourage manual implementation of the scope --- coroutines-guide.md | 2 +- docs/coroutine-context-and-dispatchers.md | 9 +++-- .../common/src/CoroutineScope.kt | 40 +++++++++---------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/coroutines-guide.md b/coroutines-guide.md index 362f8354ce..ad06cc100b 100644 --- a/coroutines-guide.md +++ b/coroutines-guide.md @@ -38,7 +38,7 @@ The main coroutines guide has moved to the [docs folder](docs/coroutines-guide.m * [Parental responsibilities](docs/coroutine-context-and-dispatchers.md#parental-responsibilities) * [Naming coroutines for debugging](docs/coroutine-context-and-dispatchers.md#naming-coroutines-for-debugging) * [Combining context elements](docs/coroutine-context-and-dispatchers.md#combining-context-elements) - * [Getting it together](docs/coroutine-context-and-dispatchers.md#getting-it-together) + * [Coroutine scope](docs/coroutine-context-and-dispatchers.md#coroutine-scope) * [Thread-local data](docs/coroutine-context-and-dispatchers.md#thread-local-data) * [Exception handling](docs/exception-handling.md#exception-handling) diff --git a/docs/coroutine-context-and-dispatchers.md b/docs/coroutine-context-and-dispatchers.md index 20e0558d70..00b0db9549 100644 --- a/docs/coroutine-context-and-dispatchers.md +++ b/docs/coroutine-context-and-dispatchers.md @@ -30,7 +30,7 @@ class DispatchersGuideTest { * [Parental responsibilities](#parental-responsibilities) * [Naming coroutines for debugging](#naming-coroutines-for-debugging) * [Combining context elements](#combining-context-elements) - * [Getting it together](#getting-it-together) + * [Coroutine scope](#coroutine-scope) * [Thread-local data](#thread-local-data) @@ -487,7 +487,7 @@ I'm working in thread DefaultDispatcher-worker-1 @test#2 -### Getting it together +### Coroutine scope Let us put our knowledge about contexts, children and jobs together. Assume that our application has an object with a lifecycle, but that object is not a coroutine. For example, we are writing an Android application @@ -516,14 +516,15 @@ class Activity { -We can implement [CoroutineScope] interface in this `Actvity` class. The best way to do it is +Alternatively, we can implement [CoroutineScope] interface in this `Actvity` class. The best way to do it is to use delegation with default factory functions. We also can combine the desired dispatcher (we used [Dispatchers.Default] in this example) with the scope:
```kotlin - class Activity : CoroutineScope by CoroutineScope(Dispatchers.Default) + class Activity : CoroutineScope by CoroutineScope(Dispatchers.Default) { + // to be continued ... ```
diff --git a/kotlinx-coroutines-core/common/src/CoroutineScope.kt b/kotlinx-coroutines-core/common/src/CoroutineScope.kt index 26bb46e52f..19c0b3a560 100644 --- a/kotlinx-coroutines-core/common/src/CoroutineScope.kt +++ b/kotlinx-coroutines-core/common/src/CoroutineScope.kt @@ -6,39 +6,34 @@ package kotlinx.coroutines import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* -import kotlin.coroutines.intrinsics.* import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* /** * Defines a scope for new coroutines. Every coroutine builder * is an extension on [CoroutineScope] and inherits its [coroutineContext][CoroutineScope.coroutineContext] * to automatically propagate both context elements and cancellation. * + * The best ways to obtain a standalone instance of the scope are [CoroutineScope()] and [MainScope()] factory functions. + * Additional context elements can be appended to the scope using [plus][CoroutineScope.plus] operator. + * + * Manual implementation of this interface is not recommended, implementation by delegation should be preferred instead. + * By convention, [context of the scope][CoroutineScope.coroutineContext] should contain an instance of a [job][Job] to enforce structured concurrency. + * * Every coroutine builder (like [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc) * and every scoping function (like [coroutineScope], [withContext], etc) provides _its own_ scope * with its own [Job] instance into the inner block of code it runs. - * By convention, they all wait for all the coroutines inside - * their block to complete before completing themselves, thus enforcing the - * discipline of **structured concurrency**. + * By convention, they all wait for all the coroutines inside their block to complete before completing themselves, + * thus enforcing the discipline of **structured concurrency**. * - * [CoroutineScope] should be implemented on entities with well-defined lifecycle that are responsible + * [CoroutineScope] should be implemented (or used as a field) on entities with a well-defined lifecycle that are responsible * for launching children coroutines. Example of such entity on Android is Activity. * Usage of this interface may look like this: * * ``` - * class MyActivity : AppCompatActivity(), CoroutineScope { - * lateinit var job: Job - * override val coroutineContext: CoroutineContext - * get() = Dispatchers.Main + job - * - * override fun onCreate(savedInstanceState: Bundle?) { - * super.onCreate(savedInstanceState) - * job = Job() - * } - * + * class MyActivity : AppCompatActivity(), CoroutineScope by MainScope() { * override fun onDestroy() { - * super.onDestroy() - * job.cancel() // Cancel job on activity destroy. After destroy all children jobs will be cancelled automatically + * cancel() // cancel is extension on CoroutineScope * } * * /* @@ -46,10 +41,7 @@ import kotlin.coroutines.* * * in this method throws an exception, then all nested coroutines are cancelled. * */ * fun showSomeData() = launch { // <- extension on current activity, launched in the main thread - * val data = withContext(Dispatchers.IO) { - * // Provides withContext scope that is child of he outer launch scope - * // blocking I/O operation - * } + * // ... here we can use suspending functions or coroutine builders with other dispatchers * draw(data) // draw in the main thread * } * } @@ -57,7 +49,11 @@ import kotlin.coroutines.* */ public interface CoroutineScope { /** - * Context of this scope. + * The context of this scope. + * Context is encapsulated by the scope and used for implementation of coroutine builders that are extensions on the scope. + * Accessing this property in general code is not recommended for any purposes except accessing [Job] instance for advanced usages. + * + * By convention, should contain an instance of a [job][Job] to enforce structured concurrency. */ public val coroutineContext: CoroutineContext } From cc42d75408504febbb95088e8630a4cff05bdcc6 Mon Sep 17 00:00:00 2001 From: Francesco Vasco Date: Sat, 23 Feb 2019 15:13:09 +0100 Subject: [PATCH 60/82] Check `toMillis` overflow in operators with `Duration` Fix #868 --- .../kotlinx-coroutines-jdk8/src/time/Time.kt | 27 ++++++-- .../test/time/TimeTest.kt | 63 +++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt diff --git a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt index 1270f8e601..edf0c767fa 100644 --- a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt +++ b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt @@ -6,28 +6,45 @@ package kotlinx.coroutines.time import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.selects.SelectBuilder import java.time.Duration -import java.util.concurrent.TimeUnit +import java.time.temporal.ChronoUnit /** * "java.time" adapter method for [kotlinx.coroutines.delay] */ public suspend fun delay(duration: Duration) = - kotlinx.coroutines.delay(duration.toMillis()) + kotlinx.coroutines.delay(duration.toMillisDelay()) /** * "java.time" adapter method for [SelectBuilder.onTimeout] */ public fun SelectBuilder.onTimeout(duration: Duration, block: suspend () -> R) = - onTimeout(duration.toMillis(), block) + onTimeout(duration.toMillisDelay(), block) /** * "java.time" adapter method for [kotlinx.coroutines.withTimeout] */ public suspend fun withTimeout(duration: Duration, block: suspend CoroutineScope.() -> T): T = - kotlinx.coroutines.withTimeout(duration.toMillis(), block) + kotlinx.coroutines.withTimeout(duration.toMillisDelay(), block) /** * "java.time" adapter method for [kotlinx.coroutines.withTimeoutOrNull] */ public suspend fun withTimeoutOrNull(duration: Duration, block: suspend CoroutineScope.() -> T): T? = - kotlinx.coroutines.withTimeoutOrNull(duration.toMillis(), block) \ No newline at end of file + kotlinx.coroutines.withTimeoutOrNull(duration.toMillisDelay(), block) + +/** + * Convert the [Duration] to millisecond delay. + * + * @return strictly positive duration is coerced to 1..[Long.MAX_VALUE] ms, `0` otherwise. + */ +private fun Duration.toMillisDelay(): Long = + if (this <= ChronoUnit.MILLIS.duration) { + if (this <= Duration.ZERO) 0 + else 1 + } else { + // values of Duration.ofMillis(Long.MAX_VALUE) + val maxSeconds = 9223372036854775 + val maxNanos = 807000000 + if (seconds < maxSeconds || seconds == maxSeconds && nano < maxNanos) toMillis() + else Long.MAX_VALUE + } diff --git a/integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt b/integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt new file mode 100644 index 0000000000..10e8d32ffc --- /dev/null +++ b/integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.time + +import kotlinx.coroutines.* +import org.hamcrest.core.* +import org.junit.* +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Job +import kotlinx.coroutines.selects.select +import java.time.temporal.ChronoUnit + +class TimeTest : TestBase() { + + private val durations = ChronoUnit.values().map { it.duration } + + @Test + fun testDelay() { + runTest { + for (duration in durations) { + delay(duration.negated()) + + launch(start = CoroutineStart.UNDISPATCHED) { + delay(duration) + } + .cancel() + } + } + } + + @Test + fun testOnTimeout() { + runTest { + for (duration in durations) { + select { + onTimeout(duration) {} + onTimeout(duration.negated()) {} + } + } + } + } + + @Test + fun testWithTimeout() { + runTest { + for (duration in durations) { + withTimeout(duration) {} + } + } + } + + @Test + fun testWithTimeoutOrNull() { + runTest { + for (duration in durations) { + withTimeoutOrNull(duration) {} + } + } + } + +} From 34eaa5c0d2da77c4da241ed280c1f4ffcc2b019e Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 6 Mar 2019 13:08:14 +0300 Subject: [PATCH 61/82] Add coercion rationale, improve test coverage --- .../kotlinx-coroutines-jdk8/src/time/Time.kt | 57 +++++++++------- .../test/time/DurationOverflowTest.kt | 68 +++++++++++++++++++ .../test/time/TimeTest.kt | 63 ----------------- .../test/time/WithTimeoutTest.kt | 68 +++++++++++++++++++ 4 files changed, 168 insertions(+), 88 deletions(-) create mode 100644 integration/kotlinx-coroutines-jdk8/test/time/DurationOverflowTest.kt delete mode 100644 integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt create mode 100644 integration/kotlinx-coroutines-jdk8/test/time/WithTimeoutTest.kt diff --git a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt index edf0c767fa..f0d94150a9 100644 --- a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt +++ b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt @@ -3,48 +3,55 @@ */ package kotlinx.coroutines.time -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.selects.SelectBuilder -import java.time.Duration -import java.time.temporal.ChronoUnit +import kotlinx.coroutines.* +import kotlinx.coroutines.selects.* +import java.time.* +import java.time.temporal.* /** - * "java.time" adapter method for [kotlinx.coroutines.delay] + * "java.time" adapter method for [kotlinx.coroutines.delay]. */ public suspend fun delay(duration: Duration) = - kotlinx.coroutines.delay(duration.toMillisDelay()) + kotlinx.coroutines.delay(duration.coerceToMillis()) /** - * "java.time" adapter method for [SelectBuilder.onTimeout] + * "java.time" adapter method for [SelectBuilder.onTimeout]. */ public fun SelectBuilder.onTimeout(duration: Duration, block: suspend () -> R) = - onTimeout(duration.toMillisDelay(), block) + onTimeout(duration.coerceToMillis(), block) /** - * "java.time" adapter method for [kotlinx.coroutines.withTimeout] + * "java.time" adapter method for [kotlinx.coroutines.withTimeout]. */ public suspend fun withTimeout(duration: Duration, block: suspend CoroutineScope.() -> T): T = - kotlinx.coroutines.withTimeout(duration.toMillisDelay(), block) + kotlinx.coroutines.withTimeout(duration.coerceToMillis(), block) /** - * "java.time" adapter method for [kotlinx.coroutines.withTimeoutOrNull] + * "java.time" adapter method for [kotlinx.coroutines.withTimeoutOrNull]. */ public suspend fun withTimeoutOrNull(duration: Duration, block: suspend CoroutineScope.() -> T): T? = - kotlinx.coroutines.withTimeoutOrNull(duration.toMillisDelay(), block) + kotlinx.coroutines.withTimeoutOrNull(duration.coerceToMillis(), block) /** - * Convert the [Duration] to millisecond delay. + * Coerces the given [Duration] to a millisecond delay. + * Negative values are coerced to zero, values that cannot + * be represented in milliseconds as long ("infinite" duration) are coerced to [Long.MAX_VALUE] + * and durations lesser than a millisecond are coerced to 1 millisecond. * - * @return strictly positive duration is coerced to 1..[Long.MAX_VALUE] ms, `0` otherwise. + * The rationale of coercion: + * 1) Too large durations typically indicate infinity and Long.MAX_VALUE is the + * best approximation of infinity we can provide. + * 2) Coercing too small durations to 1 instead of 0 is crucial for two patterns: + * - Programming with deadlines and delays + * - Non-suspending fast-paths (e.g. `withTimeout(1 nanosecond) { 42 }` should not throw) */ -private fun Duration.toMillisDelay(): Long = - if (this <= ChronoUnit.MILLIS.duration) { - if (this <= Duration.ZERO) 0 - else 1 - } else { - // values of Duration.ofMillis(Long.MAX_VALUE) - val maxSeconds = 9223372036854775 - val maxNanos = 807000000 - if (seconds < maxSeconds || seconds == maxSeconds && nano < maxNanos) toMillis() - else Long.MAX_VALUE - } +private fun Duration.coerceToMillis(): Long { + if (isNegative) return 0 + if (this <= ChronoUnit.MILLIS.duration) return 1 + + // Maximum scalar values of Duration.ofMillis(Long.MAX_VALUE) + val maxSeconds = 9223372036854775 + val maxNanos = 807000000 + return if (seconds < maxSeconds || seconds == maxSeconds && nano < maxNanos) toMillis() + else Long.MAX_VALUE +} diff --git a/integration/kotlinx-coroutines-jdk8/test/time/DurationOverflowTest.kt b/integration/kotlinx-coroutines-jdk8/test/time/DurationOverflowTest.kt new file mode 100644 index 0000000000..a9b275250f --- /dev/null +++ b/integration/kotlinx-coroutines-jdk8/test/time/DurationOverflowTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.time + +import kotlinx.coroutines.* +import kotlinx.coroutines.selects.* +import org.junit.Test +import java.time.* +import java.time.temporal.* +import kotlin.test.* + +class DurationOverflowTest : TestBase() { + + private val durations = ChronoUnit.values().map { it.duration } + + @Test + fun testDelay() = runTest { + var counter = 0 + for (duration in durations) { + expect(++counter) + delay(duration.negated()) // Instant bail out from negative values + launch(start = CoroutineStart.UNDISPATCHED) { + expect(++counter) + delay(duration) + }.cancelAndJoin() + expect(++counter) + } + + finish(++counter) + } + + @Test + fun testOnTimeout() = runTest { + for (duration in durations) { + // Does not crash on overflows + select { + onTimeout(duration) {} + onTimeout(duration.negated()) {} + } + } + } + + @Test + fun testWithTimeout() = runTest { + for (duration in durations) { + withTimeout(duration) {} + } + } + + @Test + fun testWithTimeoutOrNull() = runTest { + for (duration in durations) { + withTimeoutOrNull(duration) {} + } + } + + @Test + fun testWithTimeoutOrNullNegativeDuration() = runTest { + val result = withTimeoutOrNull(Duration.ofSeconds(1).negated()) { + 1 + } + + assertNull(result) + } + +} diff --git a/integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt b/integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt deleted file mode 100644 index 10e8d32ffc..0000000000 --- a/integration/kotlinx-coroutines-jdk8/test/time/TimeTest.kt +++ /dev/null @@ -1,63 +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.time - -import kotlinx.coroutines.* -import org.hamcrest.core.* -import org.junit.* -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Job -import kotlinx.coroutines.selects.select -import java.time.temporal.ChronoUnit - -class TimeTest : TestBase() { - - private val durations = ChronoUnit.values().map { it.duration } - - @Test - fun testDelay() { - runTest { - for (duration in durations) { - delay(duration.negated()) - - launch(start = CoroutineStart.UNDISPATCHED) { - delay(duration) - } - .cancel() - } - } - } - - @Test - fun testOnTimeout() { - runTest { - for (duration in durations) { - select { - onTimeout(duration) {} - onTimeout(duration.negated()) {} - } - } - } - } - - @Test - fun testWithTimeout() { - runTest { - for (duration in durations) { - withTimeout(duration) {} - } - } - } - - @Test - fun testWithTimeoutOrNull() { - runTest { - for (duration in durations) { - withTimeoutOrNull(duration) {} - } - } - } - -} diff --git a/integration/kotlinx-coroutines-jdk8/test/time/WithTimeoutTest.kt b/integration/kotlinx-coroutines-jdk8/test/time/WithTimeoutTest.kt new file mode 100644 index 0000000000..d33eaac124 --- /dev/null +++ b/integration/kotlinx-coroutines-jdk8/test/time/WithTimeoutTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.time + +import kotlinx.coroutines.* +import org.junit.Test +import java.time.* +import kotlin.test.* + +class WithTimeoutTest : TestBase() { + + @Test + fun testWithTimeout() = runTest { + expect(1) + val result = withTimeout(Duration.ofMillis(10_000)) { + expect(2) + delay(Duration.ofNanos(1)) + expect(3) + 42 + } + + assertEquals(42, result) + finish(4) + } + + @Test + fun testWithTimeoutOrNull() = runTest { + expect(1) + val result = withTimeoutOrNull(Duration.ofMillis(10_000)) { + expect(2) + delay(Duration.ofNanos(1)) + expect(3) + 42 + } + + assertEquals(42, result) + finish(4) + } + + @Test + fun testWithTimeoutOrNullExceeded() = runTest { + expect(1) + val result = withTimeoutOrNull(Duration.ofMillis(3)) { + expect(2) + delay(Duration.ofSeconds(Long.MAX_VALUE)) + expectUnreached() + } + + assertNull(result) + finish(3) + } + + @Test + fun testWithTimeoutExceeded() = runTest { + expect(1) + try { + withTimeout(Duration.ofMillis(3)) { + expect(2) + delay(Duration.ofSeconds(Long.MAX_VALUE)) + expectUnreached() + } + } catch (e: TimeoutCancellationException) { + finish(3) + } + } +} \ No newline at end of file From 73b456b998ef3e61742f9a5af3b6ca2b529708d8 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 6 Mar 2019 17:18:27 +0300 Subject: [PATCH 62/82] Added clarification on deprecation version in code, better CE messages --- .../src/future/Future.kt | 2 +- kotlinx-coroutines-core/common/src/Job.kt | 18 +++++++++--------- .../common/src/JobSupport.kt | 4 ++-- .../common/src/NonCancellable.kt | 2 +- .../common/src/Supervisor.kt | 2 +- .../common/src/channels/AbstractChannel.kt | 2 +- .../src/channels/ArrayBroadcastChannel.kt | 2 +- .../common/src/channels/Broadcast.kt | 2 +- .../common/src/channels/Channel.kt | 4 ++-- .../common/src/channels/ChannelCoroutine.kt | 2 +- .../common/src/channels/Channels.common.kt | 2 +- .../src/channels/ConflatedBroadcastChannel.kt | 2 +- .../common/test/channels/TestChannelKind.kt | 2 +- kotlinx-coroutines-core/js/src/Exceptions.kt | 6 +++++- .../native/src/Exceptions.kt | 6 +++++- 15 files changed, 33 insertions(+), 25 deletions(-) diff --git a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt index 3064032588..e890b025ee 100644 --- a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt +++ b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt @@ -73,7 +73,7 @@ public fun Deferred.asCompletableFuture(): CompletableFuture { val future = CompletableFuture() future.whenComplete { _, exception -> cancel(exception?.let { - it as? CancellationException ?: CancellationException("Future failed", it) + it as? CancellationException ?: CancellationException("CompletableFuture was completed exceptionally", it) }) } invokeOnCompletion { diff --git a/kotlinx-coroutines-core/common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt index 61b55470a2..f33e1715a5 100644 --- a/kotlinx-coroutines-core/common/src/Job.kt +++ b/kotlinx-coroutines-core/common/src/Job.kt @@ -166,13 +166,13 @@ public interface Job : CoroutineContext.Element { /** * @suppress This method implements old version of JVM ABI. Use [cancel]. */ - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun cancel() = cancel(null) /** * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel]. */ - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun cancel(cause: Throwable? = null): Boolean // ------------ parent-child ------------ @@ -358,7 +358,7 @@ public fun Job(parent: Job? = null): CompletableJob = JobImpl(parent) /** @suppress Binary compatibility only */ @Suppress("FunctionName") -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") @JvmName("Job") public fun Job0(parent: Job? = null): Job = Job(parent) @@ -488,13 +488,13 @@ public fun Job.cancelChildren(cause: CancellationException? = null) { /** * @suppress This method implements old version of JVM ABI. Use [cancel]. */ -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun Job.cancelChildren() = cancelChildren(null) /** * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [Job.cancelChildren]. */ -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun Job.cancelChildren(cause: Throwable? = null) { children.forEach { (it as? JobSupport)?.cancelInternal(cause) } } @@ -531,13 +531,13 @@ public fun CoroutineContext.cancel(cause: CancellationException? = null) { /** * @suppress This method implements old version of JVM ABI. Use [CoroutineContext.cancel]. */ -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun CoroutineContext.cancel() = cancel(null) /** * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancel]. */ -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun CoroutineContext.cancel(cause: Throwable? = null): Boolean = @Suppress("DEPRECATION") (this[Job] as? JobSupport)?.cancelInternal(cause) ?: false @@ -554,13 +554,13 @@ public fun CoroutineContext.cancelChildren(cause: CancellationException? = null) /** * @suppress This method implements old version of JVM ABI. Use [CoroutineContext.cancelChildren]. */ -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun CoroutineContext.cancelChildren() = cancelChildren(null) /** * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancelChildren]. */ -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun CoroutineContext.cancelChildren(cause: Throwable? = null) { this[Job]?.children?.forEach { (it as? JobSupport)?.cancelInternal(cause) } } diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index c974b67e81..43034ae2a8 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -573,12 +573,12 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren // HIDDEN in Job interface. Invoked only by legacy compiled code. // external cancel with (optional) cause, never invoked implicitly from internal machinery - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Added since 1.2.0 for binary compatibility with versions <= 1.1.x") public override fun cancel(cause: Throwable?): Boolean = cancelInternal(cause) // It is overridden in channel-linked implementation - // Note: Boolean result is used only in DEPRECATED functions + // Note: Boolean result is used only in HIDDEN DEPRECATED functions that were public in versions <= 1.1.x public open fun cancelInternal(cause: Throwable?): Boolean = cancelImpl(cause) && handlesException diff --git a/kotlinx-coroutines-core/common/src/NonCancellable.kt b/kotlinx-coroutines-core/common/src/NonCancellable.kt index 7e52dbd2de..3a4faeed8e 100644 --- a/kotlinx-coroutines-core/common/src/NonCancellable.kt +++ b/kotlinx-coroutines-core/common/src/NonCancellable.kt @@ -98,7 +98,7 @@ public object NonCancellable : AbstractCoroutineContextElement(Job), Job { * Always returns `false`. * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel]. */ - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") override fun cancel(cause: Throwable?): Boolean = false // never handles exceptions /** diff --git a/kotlinx-coroutines-core/common/src/Supervisor.kt b/kotlinx-coroutines-core/common/src/Supervisor.kt index d7443b6129..dd88e232f2 100644 --- a/kotlinx-coroutines-core/common/src/Supervisor.kt +++ b/kotlinx-coroutines-core/common/src/Supervisor.kt @@ -33,7 +33,7 @@ public fun SupervisorJob(parent: Job? = null) : CompletableJob = SupervisorJobIm /** @suppress Binary compatibility only */ @Suppress("FunctionName") -@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility") +@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") @JvmName("SupervisorJob") public fun SupervisorJob0(parent: Job? = null) : Job = SupervisorJob(parent) diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt index 456aa62deb..0835243e30 100644 --- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt @@ -655,7 +655,7 @@ internal abstract class AbstractChannel : AbstractSendChannel(), Channel( return true } - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") override fun cancel(cause: Throwable?): Boolean = cancelInternal(cause) diff --git a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt index ddb4787757..d2f7fe6447 100644 --- a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt +++ b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt @@ -95,7 +95,7 @@ private open class BroadcastCoroutine( override val channel: SendChannel get() = this - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") final override fun cancel(cause: Throwable?): Boolean = cancelInternal(cause) diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 73af389c26..351bd49e79 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -257,13 +257,13 @@ public interface ReceiveChannel { /** * @suppress This method implements old version of JVM ABI. Use [cancel]. */ - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun cancel() = cancel(null) /** * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel]. */ - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public fun cancel(cause: Throwable? = null): Boolean } diff --git a/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt index 6df82eef82..9382600af8 100644 --- a/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/channels/ChannelCoroutine.kt @@ -19,7 +19,7 @@ internal open class ChannelCoroutine( cancelInternal(null) } - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") final override fun cancel(cause: Throwable?): Boolean = cancelInternal(cause) diff --git a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt index 8e80dd9697..17c19ff1d3 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channels.common.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channels.common.kt @@ -67,7 +67,7 @@ public fun ReceiveChannel<*>.consumes(): CompletionHandler = { cause: Throwable? @PublishedApi internal fun ReceiveChannel<*>.cancelConsumed(cause: Throwable?) { cancel(cause?.let { - it as? CancellationException ?: CancellationException("Consumed", it) + it as? CancellationException ?: CancellationException("Channel was consumed, consumer had failed", it) }) } diff --git a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt index 3f23a02efc..a4f8a852fe 100644 --- a/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/ConflatedBroadcastChannel.kt @@ -204,7 +204,7 @@ public class ConflatedBroadcastChannel() : BroadcastChannel { /** * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel]. */ - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") public override fun cancel(cause: Throwable?): Boolean = close(cause) /** diff --git a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt index ada0297382..465699e27c 100644 --- a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt +++ b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt @@ -64,7 +64,7 @@ private class ChannelViaBroadcast( override fun cancel(cause: CancellationException?) = sub.cancel(cause) // implementing hidden method anyway, so can cast to an internal class - @Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only") + @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") override fun cancel(cause: Throwable?): Boolean = (sub as AbstractChannel).cancelInternal(cause) override val onReceive: SelectClause1 diff --git a/kotlinx-coroutines-core/js/src/Exceptions.kt b/kotlinx-coroutines-core/js/src/Exceptions.kt index 8e9cc64d6f..84e9e453cf 100644 --- a/kotlinx-coroutines-core/js/src/Exceptions.kt +++ b/kotlinx-coroutines-core/js/src/Exceptions.kt @@ -55,7 +55,11 @@ internal fun IllegalStateException(message: String, cause: Throwable?) = IllegalStateException(message.withCause(cause)) private fun String?.withCause(cause: Throwable?) = - if (cause == null) this else "$this; caused by $cause" + when { + cause == null -> this + this == null -> "caused by $cause" + else -> "$this; caused by $cause" + } @Suppress("NOTHING_TO_INLINE") internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) { /* empty */ } diff --git a/kotlinx-coroutines-core/native/src/Exceptions.kt b/kotlinx-coroutines-core/native/src/Exceptions.kt index be01147133..372e2cfbea 100644 --- a/kotlinx-coroutines-core/native/src/Exceptions.kt +++ b/kotlinx-coroutines-core/native/src/Exceptions.kt @@ -55,7 +55,11 @@ internal fun IllegalStateException(message: String, cause: Throwable?) = IllegalStateException(message.withCause(cause)) private fun String?.withCause(cause: Throwable?) = - if (cause == null) this else "$this; caused by $cause" + when { + cause == null -> this + this == null -> "caused by $cause" + else -> "$this; caused by $cause" + } @Suppress("NOTHING_TO_INLINE") internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) { /* empty */ } From c7cfc3905fe6eee4122d0e944ae2e98bd4bef2e9 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 6 Mar 2019 17:54:13 +0300 Subject: [PATCH 63/82] Added test for stack-trace recovery in JobCancellationException Fixes #950 --- .../StackTraceRecoveryNestedChannelsTest.kt | 29 +++++++++++++++++++ .../jvm/test/exceptions/Stacktraces.kt | 29 ++++++++++--------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt index f4f2f3a494..748f0c1697 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/StackTraceRecoveryNestedChannelsTest.kt @@ -133,4 +133,33 @@ class StackTraceRecoveryNestedChannelsTest : TestBase() { finish(3) deferred.await() } + + // See https://github.com/Kotlin/kotlinx.coroutines/issues/950 + @Test + fun testCancelledOffer() = runTest { + expect(1) + val job = Job() + val actor = actor(job, Channel.UNLIMITED) { + consumeEach { + expectUnreached() // is cancelled before offer + } + } + job.cancel() + try { + actor.offer(1) + } catch (e: Exception) { + verifyStackTrace(e, + "kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelling}@3af42ad0\n" + + "\t(Coroutine boundary)\n" + + "\tat kotlinx.coroutines.channels.AbstractSendChannel.offer(AbstractChannel.kt:186)\n" + + "\tat kotlinx.coroutines.channels.ChannelCoroutine.offer(ChannelCoroutine.kt)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedChannelsTest\$testCancelledOffer\$1.invokeSuspend(StackTraceRecoveryNestedChannelsTest.kt:150)\n" + + "Caused by: kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelling}@3af42ad0\n", + // ... java.lang.* stuff and JobSupport.* snipped here ... + "\tat kotlinx.coroutines.Job\$DefaultImpls.cancel\$default(Job.kt:164)\n" + + "\tat kotlinx.coroutines.exceptions.StackTraceRecoveryNestedChannelsTest\$testCancelledOffer\$1.invokeSuspend(StackTraceRecoveryNestedChannelsTest.kt:148)" + ) + finish(2) + } + } } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/Stacktraces.kt b/kotlinx-coroutines-core/jvm/test/exceptions/Stacktraces.kt index 51e71d5138..15884332b4 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/Stacktraces.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/Stacktraces.kt @@ -5,13 +5,15 @@ import kotlin.test.* public fun verifyStackTrace(e: Throwable, vararg traces: String) { val stacktrace = toStackTrace(e) + val normalizedActual = stacktrace.normalizeStackTrace() traces.forEach { - assertTrue( - stacktrace.trimStackTrace().contains(it.trimStackTrace()), - "\nExpected trace element:\n$it\n\nActual stacktrace:\n$stacktrace" - ) + val normalizedExpected = it.normalizeStackTrace() + if (!normalizedActual.contains(normalizedExpected)) { + // A more readable error message would be produced by assertEquals + assertEquals(normalizedExpected, normalizedActual, "Actual trace does not contain expected one") + } } - + // Check "Caused by" counts val causes = stacktrace.count("Caused by") assertNotEquals(0, causes) assertEquals(traces.map { it.count("Caused by") }.sum(), causes) @@ -23,14 +25,16 @@ public fun toStackTrace(t: Throwable): String { return sw.toString() } -public fun String.trimStackTrace(): String { - return applyBackspace(trimIndent().replace(Regex(":[0-9]+"), "") - .replace("kotlinx_coroutines_core_main", "") // yay source sets - .replace("kotlinx_coroutines_core", "")) -} +public fun String.normalizeStackTrace(): String = + applyBackspace() + .replace(Regex(":[0-9]+"), "") // remove line numbers + .replace("kotlinx_coroutines_core_main", "") // yay source sets + .replace("kotlinx_coroutines_core", "") + .replace(Regex("@[0-9a-f]+"), "") // remove hex addresses in debug toStrings + .lines().joinToString("\n") // normalize line separators -public fun applyBackspace(line: String): String { - val array = line.toCharArray() +public fun String.applyBackspace(): String { + val array = toCharArray() val stack = CharArray(array.size) var stackSize = -1 for (c in array) { @@ -40,7 +44,6 @@ public fun applyBackspace(line: String): String { --stackSize } } - return String(stack, 0, stackSize) } From d202ed9462ab5e940c1cf95065865ac974970ce3 Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Wed, 6 Mar 2019 18:59:48 +0300 Subject: [PATCH 64/82] Restore all state in TestBase even when test fails And also make sure only the first detected error gets reported --- kotlinx-coroutines-core/jvm/test/TestBase.kt | 41 +++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/kotlinx-coroutines-core/jvm/test/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt index d16d9723fb..db5c53ae80 100644 --- a/kotlinx-coroutines-core/jvm/test/TestBase.kt +++ b/kotlinx-coroutines-core/jvm/test/TestBase.kt @@ -62,13 +62,20 @@ public actual open class TestBase actual constructor() { */ @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun error(message: Any, cause: Throwable? = null): Nothing { - val exception = IllegalStateException(message.toString(), cause) + throw makeError(message, cause) + } + + private fun makeError(message: Any, cause: Throwable? = null): IllegalStateException = + IllegalStateException(message.toString(), cause).also { + setError(it) + } + + private fun setError(exception: Throwable) { error.compareAndSet(null, exception) - throw exception } private fun printError(message: String, cause: Throwable) { - error.compareAndSet(null, cause) + setError(cause) println("$message: $cause") cause.printStackTrace(System.out) println("--- Detected at ---") @@ -118,21 +125,35 @@ public actual open class TestBase actual constructor() { initPoolsBeforeTest() threadsBefore = currentThreads() originalUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler() - Thread.setDefaultUncaughtExceptionHandler({ t, e -> - println("Uncaught exception in thread $t: $e") + Thread.setDefaultUncaughtExceptionHandler { t, e -> + println("Exception in thread $t: $e") // The same message as in default handler e.printStackTrace() uncaughtExceptions.add(e) - }) + } } @After fun onCompletion() { - error.get()?.let { throw it } - check(actionIndex.get() == 0 || finished.get()) { "Expecting that 'finish(...)' was invoked, but it was not" } + // onCompletion should not throw exceptions before it finishes all cleanup, so that other tests always + // start in a clear, restored state + if (actionIndex.get() != 0 && !finished.get()) { + makeError("Expecting that 'finish(...)' was invoked, but it was not") + } + // Shutdown all thread pools shutdownPoolsAfterTest() - checkTestThreads(threadsBefore) + // Check that that are now leftover threads + runCatching { + checkTestThreads(threadsBefore) + }.onFailure { + setError(it) + } + // Restore original uncaught exception handler Thread.setDefaultUncaughtExceptionHandler(originalUncaughtExceptionHandler) - assertTrue(uncaughtExceptions.isEmpty(), "Expected no uncaught exceptions, but got $uncaughtExceptions") + if (uncaughtExceptions.isNotEmpty()) { + makeError("Expected no uncaught exceptions, but got $uncaughtExceptions") + } + // The very last action -- throw error if any was detected + error.get()?.let { throw it } } fun initPoolsBeforeTest() { From a38e7d5a25f1bdd78d445bca755c22565fda9841 Mon Sep 17 00:00:00 2001 From: SatoShun Date: Mon, 11 Mar 2019 00:11:21 +0000 Subject: [PATCH 65/82] Remove unnecessary semicolon --- kotlinx-coroutines-core/common/test/AwaitTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/common/test/AwaitTest.kt b/kotlinx-coroutines-core/common/test/AwaitTest.kt index b86c7852f9..b3ca729a33 100644 --- a/kotlinx-coroutines-core/common/test/AwaitTest.kt +++ b/kotlinx-coroutines-core/common/test/AwaitTest.kt @@ -37,11 +37,11 @@ class AwaitTest : TestBase() { fun testAwaitAllLazy() = runTest { expect(1) val d = async(start = CoroutineStart.LAZY) { - expect(2); + expect(2) 1 } val d2 = async(start = CoroutineStart.LAZY) { - expect(3); + expect(3) 2 } assertEquals(listOf(1, 2), awaitAll(d, d2)) From 0c8789d880d69c9ac2e0d276ccbb8380d404960c Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 7 Mar 2019 15:07:41 +0300 Subject: [PATCH 66/82] Handle fatal exceptions in continuation machinery using handleViaException instead of rethrowing it to provide faster feedback loop Fixes #808 Fixes #773 --- .../common/src/Dispatched.kt | 45 +++++- .../jvm/src/ThreadContextElement.kt | 4 +- .../test/FailingCoroutinesMachineryTest.kt | 135 ++++++++++++++++++ 3 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt diff --git a/kotlinx-coroutines-core/common/src/Dispatched.kt b/kotlinx-coroutines-core/common/src/Dispatched.kt index eb6e02f375..05825f87ad 100644 --- a/kotlinx-coroutines-core/common/src/Dispatched.kt +++ b/kotlinx-coroutines-core/common/src/Dispatched.kt @@ -51,7 +51,7 @@ private fun DispatchedTask<*>.resumeUnconfined() { } } -private inline fun runUnconfinedEventLoop( +private inline fun DispatchedTask<*>.runUnconfinedEventLoop( eventLoop: EventLoop, block: () -> Unit ) { @@ -64,10 +64,10 @@ private inline fun runUnconfinedEventLoop( } } catch (e: Throwable) { /* - * This exception doesn't happen normally, only if user either submitted throwing runnable - * or if we have a bug in implementation. Throw an exception that better explains the problem. + * This exception doesn't happen normally, only if we have a bug in implementation. + * Report it as a fatal exception. */ - throw DispatchException("Unexpected exception in unconfined event loop", e) + handleFatalException(e, null) } finally { eventLoop.decrementUseCount(unconfined = true) } @@ -216,6 +216,7 @@ internal abstract class DispatchedTask( public final override fun run() { val taskContext = this.taskContext + var exception: Throwable? = null try { val delegate = delegate as DispatchedContinuation val continuation = delegate.continuation @@ -234,11 +235,43 @@ internal abstract class DispatchedTask( } } } catch (e: Throwable) { - throw DispatchException("Unexpected exception running $this", e) + // This instead of runCatching to have nicer stacktrace and debug experience + exception = e } finally { - taskContext.afterTask() + val result = runCatching { taskContext.afterTask() } + handleFatalException(exception, result.exceptionOrNull()) } } + + /** + * Machinery that handles fatal exceptions in kotlinx.coroutines. + * There are two kinds of fatal exceptions: + * + * 1) Exceptions from kotlinx.coroutines code. Such exceptions indicate that either + * the library or the compiler has a bug that breaks internal invariants. + * They usually have specific workarounds, but require careful study of the cause and should + * be reported to the maintainers and fixed on the library's side anyway. + * + * 2) Exceptions from [ThreadContextElement.updateThreadContext] and [ThreadContextElement.restoreThreadContext]. + * While a user code can trigger such exception by providing an improper implementation of [ThreadContextElement], + * we can't ignore it because it may leave coroutine in the inconsistent state. + * If you encounter such exception, you can either disable this context element or wrap it into + * another context element that catches all exceptions and handles it in the application specific manner. + * + * Fatal exception handling can be intercepted with [CoroutineExceptionHandler] element in the context of + * a failed coroutine, but such exceptions should be reported anyway. + */ + internal fun handleFatalException(exception: Throwable?, finallyException: Throwable?) { + if (exception === null && finallyException === null) return + if (exception !== null && finallyException !== null) { + exception.addSuppressedThrowable(finallyException) + } + + val cause = exception ?: finallyException + val reason = DispatchException("Fatal exception in coroutines machinery for $this. " + + "Please read KDoc to 'handleFatalException' method and report this incident to maintainers", cause!!) + handleExceptionViaHandler(this.delegate.context, reason) + } } internal fun DispatchedContinuation.yieldUndispatched(): Boolean = diff --git a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt index f83ced2caa..c68ee45cd5 100644 --- a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt +++ b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt @@ -56,7 +56,7 @@ public interface ThreadContextElement : CoroutineContext.Element { * when the context of the coroutine this element. * The result of this function is the old value of the thread-local state that will be passed to [restoreThreadContext]. * This method should handle its own exceptions and do not rethrow it. Thrown exceptions will leave coroutine which - * context is updated in an undefined state. + * context is updated in an undefined state and may crash an application. * * @param context the coroutine context. */ @@ -69,7 +69,7 @@ public interface ThreadContextElement : CoroutineContext.Element { * The value of [oldState] is the result of the previous invocation of [updateThreadContext] and it should * be restored in the thread-local state by this function. * This method should handle its own exceptions and do not rethrow it. Thrown exceptions will leave coroutine which - * context is updated in an undefined state. + * context is updated in an undefined state and may crash an application. * * @param context the coroutine context. * @param oldState the value returned by the previous invocation of [updateThreadContext]. diff --git a/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt b/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt new file mode 100644 index 0000000000..2ca1cbfb07 --- /dev/null +++ b/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt @@ -0,0 +1,135 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines + +import org.junit.* +import org.junit.Test +import org.junit.runner.* +import org.junit.runners.* +import java.util.concurrent.* +import kotlin.coroutines.* +import kotlin.test.* + +@RunWith(Parameterized::class) +class FailingCoroutinesMachineryTest( + private val element: CoroutineContext.Element, + private val dispatcher: CoroutineDispatcher +) : TestBase() { + + private var caught: Throwable? = null + private val latch = CountDownLatch(1) + private var exceptionHandler = CoroutineExceptionHandler { _, t -> caught = t;latch.countDown() } + private val lazyOuterDispatcher = lazy { newFixedThreadPoolContext(1, "") } + + private object FailingUpdate : ThreadContextElement { + private object Key : CoroutineContext.Key + + override val key: CoroutineContext.Key<*> get() = Key + + override fun restoreThreadContext(context: CoroutineContext, oldState: Unit) { + } + + override fun updateThreadContext(context: CoroutineContext) { + throw TestException("Prevent a coroutine from starting right here for some reason") + } + + override fun toString() = "FailingUpdate" + } + + private object FailingRestore : ThreadContextElement { + private object Key : CoroutineContext.Key + + override val key: CoroutineContext.Key<*> get() = Key + + override fun restoreThreadContext(context: CoroutineContext, oldState: Unit) { + throw TestException("Prevent a coroutine from starting right here for some reason") + } + + override fun updateThreadContext(context: CoroutineContext) { + } + + override fun toString() = "FailingRestore" + } + + private object ThrowingDispatcher : CoroutineDispatcher() { + override fun dispatch(context: CoroutineContext, block: Runnable) { + throw TestException() + } + + override fun toString() = "ThrowingDispatcher" + } + + private object ThrowingDispatcher2 : CoroutineDispatcher() { + override fun dispatch(context: CoroutineContext, block: Runnable) { + block.run() + } + + override fun isDispatchNeeded(context: CoroutineContext): Boolean { + throw TestException() + } + + override fun toString() = "ThrowingDispatcher2" + } + + @After + fun tearDown() { + runCatching { (dispatcher as? ExecutorCoroutineDispatcher)?.close() } + if (lazyOuterDispatcher.isInitialized()) lazyOuterDispatcher.value.close() + } + + companion object { + @JvmStatic + @Parameterized.Parameters(name = "Element: {0}, dispatcher: {1}") + fun dispatchers(): List> { + val elements = listOf(FailingRestore, FailingUpdate) + val dispatchers = listOf( + Dispatchers.Unconfined, + Dispatchers.Default, + Executors.newFixedThreadPool(1).asCoroutineDispatcher(), + Executors.newScheduledThreadPool(1).asCoroutineDispatcher(), + ThrowingDispatcher, ThrowingDispatcher2 + ) + + return elements.flatMap { element -> + dispatchers.map { dispatcher -> + arrayOf(element, dispatcher) + } + } + } + } + + @Test + fun testElement() = runTest { + launch(NonCancellable + dispatcher + exceptionHandler + element) {} + checkException() + } + + @Test + fun testNestedElement() = runTest { + launch(NonCancellable + dispatcher + exceptionHandler) { + launch(element) { } + } + checkException() + } + + @Test + fun testNestedDispatcherAndElement() = runTest { + launch(lazyOuterDispatcher.value + NonCancellable + exceptionHandler) { + launch(element + dispatcher) { } + } + checkException() + } + + private fun checkException() { + latch.await(2, TimeUnit.SECONDS) + val e = caught + assertNotNull(e) + // First condition -- failure in context element + val firstCondition = e is DispatchException && e.cause is TestException + // Second condition -- failure from isDispatchNeeded (#880) + val secondCondition = e is TestException + assertTrue(firstCondition xor secondCondition) + } +} From 132c1e3f029610208607dcac4d55ed05f62d0642 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 7 Mar 2019 15:15:40 +0300 Subject: [PATCH 67/82] Rename DispatchException to CoroutinesInternalError and make it an Error to better reflect its semantics --- kotlinx-coroutines-core/common/src/Dispatched.kt | 2 +- kotlinx-coroutines-core/common/src/Exceptions.common.kt | 3 +-- kotlinx-coroutines-core/js/src/Exceptions.kt | 2 +- kotlinx-coroutines-core/jvm/src/Exceptions.kt | 2 +- .../jvm/test/FailingCoroutinesMachineryTest.kt | 2 +- kotlinx-coroutines-core/native/src/Exceptions.kt | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/Dispatched.kt b/kotlinx-coroutines-core/common/src/Dispatched.kt index 05825f87ad..2612322109 100644 --- a/kotlinx-coroutines-core/common/src/Dispatched.kt +++ b/kotlinx-coroutines-core/common/src/Dispatched.kt @@ -268,7 +268,7 @@ internal abstract class DispatchedTask( } val cause = exception ?: finallyException - val reason = DispatchException("Fatal exception in coroutines machinery for $this. " + + val reason = CoroutinesInternalError("Fatal exception in coroutines machinery for $this. " + "Please read KDoc to 'handleFatalException' method and report this incident to maintainers", cause!!) handleExceptionViaHandler(this.delegate.context, reason) } diff --git a/kotlinx-coroutines-core/common/src/Exceptions.common.kt b/kotlinx-coroutines-core/common/src/Exceptions.common.kt index e02089327b..e8c2f5e1db 100644 --- a/kotlinx-coroutines-core/common/src/Exceptions.common.kt +++ b/kotlinx-coroutines-core/common/src/Exceptions.common.kt @@ -23,9 +23,8 @@ internal expect class JobCancellationException( internal val job: Job } -internal expect class DispatchException(message: String, cause: Throwable) : RuntimeException +internal expect class CoroutinesInternalError(message: String, cause: Throwable) : Error internal expect fun Throwable.addSuppressedThrowable(other: Throwable) - // For use in tests internal expect val RECOVER_STACK_TRACES: Boolean \ No newline at end of file diff --git a/kotlinx-coroutines-core/js/src/Exceptions.kt b/kotlinx-coroutines-core/js/src/Exceptions.kt index 84e9e453cf..83a0cdaf90 100644 --- a/kotlinx-coroutines-core/js/src/Exceptions.kt +++ b/kotlinx-coroutines-core/js/src/Exceptions.kt @@ -48,7 +48,7 @@ internal actual class JobCancellationException public actual constructor( (message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0) } -internal actual class DispatchException actual constructor(message: String, cause: Throwable) : RuntimeException(message.withCause(cause)) +internal actual class CoroutinesInternalError actual constructor(message: String, cause: Throwable) : Error(message.withCause(cause)) @Suppress("FunctionName") internal fun IllegalStateException(message: String, cause: Throwable?) = diff --git a/kotlinx-coroutines-core/jvm/src/Exceptions.kt b/kotlinx-coroutines-core/jvm/src/Exceptions.kt index f6cc75b7b3..4e734987aa 100644 --- a/kotlinx-coroutines-core/jvm/src/Exceptions.kt +++ b/kotlinx-coroutines-core/jvm/src/Exceptions.kt @@ -81,7 +81,7 @@ internal actual class JobCancellationException public actual constructor( (message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0) } -internal actual class DispatchException actual constructor(message: String, cause: Throwable) : RuntimeException(message, cause) +internal actual class CoroutinesInternalError actual constructor(message: String, cause: Throwable) : Error(message, cause) @Suppress("NOTHING_TO_INLINE") internal actual inline fun Throwable.addSuppressedThrowable(other: Throwable) = diff --git a/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt b/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt index 2ca1cbfb07..9bf8ffad85 100644 --- a/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt +++ b/kotlinx-coroutines-core/jvm/test/FailingCoroutinesMachineryTest.kt @@ -127,7 +127,7 @@ class FailingCoroutinesMachineryTest( val e = caught assertNotNull(e) // First condition -- failure in context element - val firstCondition = e is DispatchException && e.cause is TestException + val firstCondition = e is CoroutinesInternalError && e.cause is TestException // Second condition -- failure from isDispatchNeeded (#880) val secondCondition = e is TestException assertTrue(firstCondition xor secondCondition) diff --git a/kotlinx-coroutines-core/native/src/Exceptions.kt b/kotlinx-coroutines-core/native/src/Exceptions.kt index 372e2cfbea..29c3ce5135 100644 --- a/kotlinx-coroutines-core/native/src/Exceptions.kt +++ b/kotlinx-coroutines-core/native/src/Exceptions.kt @@ -48,7 +48,7 @@ internal actual class JobCancellationException public actual constructor( (message!!.hashCode() * 31 + job.hashCode()) * 31 + (cause?.hashCode() ?: 0) } -internal actual class DispatchException actual constructor(message: String, cause: Throwable) : RuntimeException(message.withCause(cause)) +internal actual class CoroutinesInternalError actual constructor(message: String, cause: Throwable) : Error(message.withCause(cause)) @Suppress("FunctionName") internal fun IllegalStateException(message: String, cause: Throwable?) = From 4651b57c4be36b9914a54cd8c6aa8f71d3ac34dc Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 13 Mar 2019 14:29:19 +0300 Subject: [PATCH 68/82] Merge with cancellation rework --- kotlinx-coroutines-core/common/src/Dispatched.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/Dispatched.kt b/kotlinx-coroutines-core/common/src/Dispatched.kt index 2612322109..f656b22b84 100644 --- a/kotlinx-coroutines-core/common/src/Dispatched.kt +++ b/kotlinx-coroutines-core/common/src/Dispatched.kt @@ -270,7 +270,7 @@ internal abstract class DispatchedTask( val cause = exception ?: finallyException val reason = CoroutinesInternalError("Fatal exception in coroutines machinery for $this. " + "Please read KDoc to 'handleFatalException' method and report this incident to maintainers", cause!!) - handleExceptionViaHandler(this.delegate.context, reason) + handleCoroutineException(this.delegate.context, reason) } } From 91c49e11e3633c1bdfc0c79de49cff44fe06485e Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 13 Mar 2019 15:19:49 +0300 Subject: [PATCH 69/82] Update Kotlin to 1.3.21 --- README.md | 8 ++++---- gradle.properties | 3 +-- .../animation-app/gradle.properties | 2 +- .../example-app/gradle.properties | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d2a3b2d18a..029cc5b486 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.1.1) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.1.1) Library support for Kotlin coroutines with [multiplatform](#multiplatform) support. -This is a companion version for Kotlin `1.3.20` release. +This is a companion version for Kotlin `1.3.21` release. ```kotlin GlobalScope.launch { @@ -83,7 +83,7 @@ And make sure that you use the latest Kotlin version: ```xml - 1.3.20 + 1.3.21 ``` @@ -101,7 +101,7 @@ And make sure that you use the latest Kotlin version: ```groovy buildscript { - ext.kotlin_version = '1.3.20' + ext.kotlin_version = '1.3.21' } ``` @@ -127,7 +127,7 @@ And make sure that you use the latest Kotlin version: ```groovy plugins { - kotlin("jvm") version "1.3.20" + kotlin("jvm") version "1.3.21" } ``` diff --git a/gradle.properties b/gradle.properties index af62a5b387..33b6e97936 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,7 @@ # Kotlin version=1.1.1-SNAPSHOT group=org.jetbrains.kotlinx -kotlin_version=1.3.20 -kotlin_native_version=1.3.20 +kotlin_version=1.3.21 # Dependencies junit_version=4.12 diff --git a/ui/kotlinx-coroutines-android/animation-app/gradle.properties b/ui/kotlinx-coroutines-android/animation-app/gradle.properties index c2dde35a14..da95499227 100644 --- a/ui/kotlinx-coroutines-android/animation-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/animation-app/gradle.properties @@ -18,6 +18,6 @@ org.gradle.jvmargs=-Xmx1536m kotlin.coroutines=enable -kotlin_version=1.3.20 +kotlin_version=1.3.21 coroutines_version=1.1.1 diff --git a/ui/kotlinx-coroutines-android/example-app/gradle.properties b/ui/kotlinx-coroutines-android/example-app/gradle.properties index c2dde35a14..da95499227 100644 --- a/ui/kotlinx-coroutines-android/example-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/example-app/gradle.properties @@ -18,6 +18,6 @@ org.gradle.jvmargs=-Xmx1536m kotlin.coroutines=enable -kotlin_version=1.3.20 +kotlin_version=1.3.21 coroutines_version=1.1.1 From 8273a757ddd60087646f6f5aa4edb64f969c49cd Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 15 Mar 2019 19:24:41 +0300 Subject: [PATCH 70/82] Properly import resource folders in MPP --- kotlinx-coroutines-core/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index f0b655d033..e963466ceb 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -19,6 +19,11 @@ kotlin { def srcDir = name.endsWith('Main') ? 'src' : 'test' def platform = name[0..-5] kotlin.srcDir "$platform/$srcDir" + if (name == "jvmMain") { + resources.srcDirs = ["$platform/resources"] + } else if (name == "jvmTest") { + resources.srcDirs = ["$platform/test-resources"] + } languageSettings { progressiveMode = true experimentalAnnotations.each { useExperimentalAnnotation(it) } From ac136d630d35677cbe5163edc7ff0489db380fbf Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 15 Mar 2019 22:55:57 +0300 Subject: [PATCH 71/82] Rollback to insecure http for reactivex.io (broken certificate) --- reactive/kotlinx-coroutines-rx2/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactive/kotlinx-coroutines-rx2/build.gradle b/reactive/kotlinx-coroutines-rx2/build.gradle index abb1391590..bf623a27e3 100644 --- a/reactive/kotlinx-coroutines-rx2/build.gradle +++ b/reactive/kotlinx-coroutines-rx2/build.gradle @@ -9,6 +9,6 @@ dependencies { tasks.withType(dokka.getClass()) { externalDocumentationLink { - url = new URL('https://reactivex.io/RxJava/javadoc/') + url = new URL('http://reactivex.io/RxJava/javadoc/') } } \ No newline at end of file From b6f5b2cc625c5dba9f32202ebc4f1a45896270e4 Mon Sep 17 00:00:00 2001 From: Nikita Koval Date: Mon, 18 Mar 2019 23:00:12 +0300 Subject: [PATCH 72/82] Deprecate `SendChannel.isFull` and `ReceiveChannel.isEmpty` properties Fixes #1053 --- .../common/src/channels/AbstractChannel.kt | 12 ++++++---- .../common/src/channels/Channel.kt | 23 ++++++++++--------- .../common/test/channels/ArrayChannelTest.kt | 14 ++++------- .../test/channels/RendezvousChannelTest.kt | 8 +++---- .../common/test/channels/TestChannelKind.kt | 1 + 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt index 0835243e30..38f7c3bf16 100644 --- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt +++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt @@ -167,7 +167,8 @@ internal abstract class AbstractSendChannel : SendChannel { // ------ SendChannel ------ public final override val isClosedForSend: Boolean get() = closedForSend != null - public final override val isFull: Boolean get() = queue.nextNode !is ReceiveOrClosed<*> && isBufferFull + public final override val isFull: Boolean get() = full + private val full: Boolean get() = queue.nextNode !is ReceiveOrClosed<*> && isBufferFull // TODO rename to `isFull` public final override suspend fun send(element: E) { // fast path -- try offer non-blocking @@ -402,7 +403,7 @@ internal abstract class AbstractSendChannel : SendChannel { private fun registerSelectSend(select: SelectInstance, element: E, block: suspend (SendChannel) -> R) { while (true) { if (select.isSelected) return - if (isFull) { + if (full) { val enqueueOp = TryEnqueueSendDesc(element, select, block) val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ?: return when { @@ -561,7 +562,8 @@ internal abstract class AbstractChannel : AbstractSendChannel(), Channel : AbstractSendChannel(), Channel registerSelectReceive(select: SelectInstance, block: suspend (E) -> R) { while (true) { if (select.isSelected) return - if (isEmpty) { + if (empty) { val enqueueOp = TryEnqueueReceiveDesc(select, block as (suspend (E?) -> R), nullOnClose = false) val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ?: return when { @@ -782,7 +784,7 @@ internal abstract class AbstractChannel : AbstractSendChannel(), Channel registerSelectReceiveOrNull(select: SelectInstance, block: suspend (E?) -> R) { while (true) { if (select.isSelected) return - if (isEmpty) { + if (empty) { val enqueueOp = TryEnqueueReceiveDesc(select, block, nullOnClose = true) val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ?: return when { diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 351bd49e79..286196dc7b 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -30,14 +30,15 @@ public interface SendChannel { * Returns `true` if the channel is full (out of capacity) and the [send] attempt will suspend. * This function returns `false` for [isClosedForSend] channel. * - * **Note: This is an experimental api.** This property may change its semantics and/or name in the future. + * @suppress **Will be removed in next releases, no replacement.** */ @ExperimentalCoroutinesApi + @Deprecated(level = DeprecationLevel.ERROR, message = "Will be removed in next releases without replacement") public val isFull: Boolean /** - * Adds [element] into to this channel, suspending the caller while this channel [isFull], - * or throws exception if the channel [isClosedForSend] (see [close] for details). + * Adds [element] into to this channel, suspending the caller while the buffer of this channel is full + * or if it does not exist, or throws exception if the channel [isClosedForSend] (see [close] for details). * * Note, that closing a channel _after_ this function had suspended does not cause this suspended send invocation * to abort, because closing a channel is conceptually like sending a special "close token" over this channel. @@ -151,13 +152,14 @@ public interface ReceiveChannel { * Returns `true` if the channel is empty (contains no elements) and the [receive] attempt will suspend. * This function returns `false` for [isClosedForReceive] channel. * - * **Note: This is an experimental api.** This property may change its semantics and/or name in the future. + * @suppress **Will be removed in next releases, no replacement.** */ @ExperimentalCoroutinesApi + @Deprecated(level = DeprecationLevel.ERROR, message = "Will be removed in next releases without replacement") public val isEmpty: Boolean /** - * Retrieves and removes the element from this channel suspending the caller while this channel [isEmpty] + * Retrieves and removes the element from this channel suspending the caller while this channel is empty, * or throws [ClosedReceiveChannelException] if the channel [isClosedForReceive]. * If the channel was closed because of the exception, it is called a _failed_ channel and this function * throws the original [close][SendChannel.close] cause exception. @@ -188,7 +190,7 @@ public interface ReceiveChannel { public val onReceive: SelectClause1 /** - * Retrieves and removes the element from this channel suspending the caller while this channel [isEmpty] + * Retrieves and removes the element from this channel suspending the caller while this channel is empty, * or returns `null` if the channel is [closed][isClosedForReceive] without cause * or throws the original [close][SendChannel.close] cause exception if the channel has _failed_. * @@ -227,7 +229,7 @@ public interface ReceiveChannel { public val onReceiveOrNull: SelectClause1 /** - * Retrieves and removes the element from this channel, or returns `null` if this channel [isEmpty] + * Retrieves and removes the element from this channel, or returns `null` if this channel is empty * or is [isClosedForReceive] without cause. * It throws the original [close][SendChannel.close] cause exception if the channel has _failed_. */ @@ -273,9 +275,8 @@ public interface ReceiveChannel { */ public interface ChannelIterator { /** - * Returns `true` if the channel has more elements suspending the caller while this channel - * [isEmpty][ReceiveChannel.isEmpty] or returns `false` if the channel - * [isClosedForReceive][ReceiveChannel.isClosedForReceive] without cause. + * Returns `true` if the channel has more elements, suspending the caller while this channel is empty, + * or returns `false` if the channel [isClosedForReceive][ReceiveChannel.isClosedForReceive] without cause. * It throws the original [close][SendChannel.close] cause exception if the channel has _failed_. * * This function retrieves and removes the element from this channel for the subsequent invocation @@ -297,7 +298,7 @@ public interface ChannelIterator { /** * Retrieves and removes the element from this channel suspending the caller while this channel - * [isEmpty][ReceiveChannel.isEmpty] or throws [ClosedReceiveChannelException] if the channel + * is empty or throws [ClosedReceiveChannelException] if the channel * [isClosedForReceive][ReceiveChannel.isClosedForReceive] without cause. * It throws the original [close][SendChannel.close] cause exception if the channel has _failed_. * diff --git a/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt index 56a1c5a541..308f8f3c2a 100644 --- a/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/ArrayChannelTest.kt @@ -11,12 +11,10 @@ class ArrayChannelTest : TestBase() { @Test fun testSimple() = runTest { val q = Channel(1) - check(q.isEmpty && !q.isFull) expect(1) val sender = launch { expect(4) q.send(1) // success -- buffered - check(!q.isEmpty && q.isFull) expect(5) q.send(2) // suspends (buffer full) expect(9) @@ -25,7 +23,6 @@ class ArrayChannelTest : TestBase() { val receiver = launch { expect(6) check(q.receive() == 1) // does not suspend -- took from buffer - check(!q.isEmpty && q.isFull) // waiting sender's element moved to buffer expect(7) check(q.receive() == 2) // does not suspend (takes from sender) expect(8) @@ -33,21 +30,20 @@ class ArrayChannelTest : TestBase() { expect(3) sender.join() receiver.join() - check(q.isEmpty && !q.isFull) finish(10) } @Test fun testClosedBufferedReceiveOrNull() = runTest { val q = Channel(1) - check(q.isEmpty && !q.isFull && !q.isClosedForSend && !q.isClosedForReceive) + check(!q.isClosedForSend && !q.isClosedForReceive) expect(1) launch { expect(5) - check(!q.isEmpty && !q.isFull && q.isClosedForSend && !q.isClosedForReceive) + check(q.isClosedForSend && !q.isClosedForReceive) assertEquals(42, q.receiveOrNull()) expect(6) - check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive) + check(q.isClosedForSend && q.isClosedForReceive) assertEquals(null, q.receiveOrNull()) expect(7) } @@ -56,9 +52,9 @@ class ArrayChannelTest : TestBase() { expect(3) q.close() // goes on expect(4) - check(!q.isEmpty && !q.isFull && q.isClosedForSend && !q.isClosedForReceive) + check(q.isClosedForSend && !q.isClosedForReceive) yield() - check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive) + check(q.isClosedForSend && q.isClosedForReceive) finish(8) } diff --git a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt index 60bccef04d..fafda0d7da 100644 --- a/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt +++ b/kotlinx-coroutines-core/common/test/channels/RendezvousChannelTest.kt @@ -11,7 +11,6 @@ class RendezvousChannelTest : TestBase() { @Test fun testSimple() = runTest { val q = Channel(Channel.RENDEZVOUS) - check(q.isEmpty && q.isFull) expect(1) val sender = launch { expect(4) @@ -31,14 +30,13 @@ class RendezvousChannelTest : TestBase() { expect(3) sender.join() receiver.join() - check(q.isEmpty && q.isFull) finish(10) } @Test fun testClosedReceiveOrNull() = runTest { val q = Channel(Channel.RENDEZVOUS) - check(q.isEmpty && q.isFull && !q.isClosedForSend && !q.isClosedForReceive) + check(!q.isClosedForSend && !q.isClosedForReceive) expect(1) launch { expect(3) @@ -51,9 +49,9 @@ class RendezvousChannelTest : TestBase() { q.send(42) expect(5) q.close() - check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive) + check(q.isClosedForSend && q.isClosedForReceive) yield() - check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive) + check(q.isClosedForSend && q.isClosedForReceive) finish(7) } diff --git a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt index 465699e27c..6e1ee2bf69 100644 --- a/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt +++ b/kotlinx-coroutines-core/common/test/channels/TestChannelKind.kt @@ -54,6 +54,7 @@ private class ChannelViaBroadcast( val sub = broadcast.openSubscription() override val isClosedForReceive: Boolean get() = sub.isClosedForReceive + @Suppress("DEPRECATION_ERROR") override val isEmpty: Boolean get() = sub.isEmpty override suspend fun receive(): E = sub.receive() From 3e4285070518467cbb7d35515aa9a0637071c547 Mon Sep 17 00:00:00 2001 From: Nikita Koval Date: Tue, 19 Mar 2019 18:48:56 +0300 Subject: [PATCH 73/82] Move `systemProp` function to the common module; only the JVM platform implements it properly while others always use provided default value. --- .../common/src/internal/SystemProps.common.kt | 65 +++++++++++++++++++ .../js/src/internal/SystemProps.kt | 7 ++ .../jvm/src/internal/SystemProps.kt | 40 ++---------- .../native/src/internal/SystemProps.kt | 7 ++ 4 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt create mode 100644 kotlinx-coroutines-core/js/src/internal/SystemProps.kt create mode 100644 kotlinx-coroutines-core/native/src/internal/SystemProps.kt diff --git a/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt new file mode 100644 index 0000000000..b7e67ec0bd --- /dev/null +++ b/kotlinx-coroutines-core/common/src/internal/SystemProps.common.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:JvmName("SystemPropsKt") +@file:JvmMultifileClass + +package kotlinx.coroutines.internal + +import kotlin.jvm.* + +/** + * Gets the system property indicated by the specified [property name][propertyName], + * or returns [defaultValue] if there is no property with that key. + * + * **Note: this function should be used in JVM tests only, other platforms use the default value.** + */ +internal fun systemProp( + propertyName: String, + defaultValue: Boolean +): Boolean = systemProp(propertyName)?.toBoolean() ?: defaultValue + +/** + * Gets the system property indicated by the specified [property name][propertyName], + * or returns [defaultValue] if there is no property with that key. It also checks that the result + * is between [minValue] and [maxValue] (inclusively), throws [IllegalStateException] if it is not. + * + * **Note: this function should be used in JVM tests only, other platforms use the default value.** + */ +internal fun systemProp( + propertyName: String, + defaultValue: Int, + minValue: Int = 1, + maxValue: Int = Int.MAX_VALUE +): Int = systemProp(propertyName, defaultValue.toLong(), minValue.toLong(), maxValue.toLong()).toInt() + +/** + * Gets the system property indicated by the specified [property name][propertyName], + * or returns [defaultValue] if there is no property with that key. It also checks that the result + * is between [minValue] and [maxValue] (inclusively), throws [IllegalStateException] if it is not. + * + * **Note: this function should be used in JVM tests only, other platforms use the default value.** + */ +internal fun systemProp( + propertyName: String, + defaultValue: Long, + minValue: Long = 1, + maxValue: Long = Long.MAX_VALUE +): Long { + val value = systemProp(propertyName) ?: return defaultValue + val parsed = value.toLongOrNull() + ?: error("System property '$propertyName' has unrecognized value '$value'") + if (parsed !in minValue..maxValue) { + error("System property '$propertyName' should be in range $minValue..$maxValue, but is '$parsed'") + } + return parsed +} + +/** + * Gets the system property indicated by the specified [property name][propertyName], + * or returns `null` if there is no property with that key. + * + * **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 diff --git a/kotlinx-coroutines-core/js/src/internal/SystemProps.kt b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt new file mode 100644 index 0000000000..6779d4e5d8 --- /dev/null +++ b/kotlinx-coroutines-core/js/src/internal/SystemProps.kt @@ -0,0 +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 + +internal actual fun systemProp(propertyName: String): String? = null \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt index cbef51f48e..ef5ab24118 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/SystemProps.kt @@ -1,13 +1,16 @@ /* - * 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. */ +@file:JvmName("SystemPropsKt") +@file:JvmMultifileClass + package kotlinx.coroutines.internal // number of processors at startup for consistent prop initialization internal val AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors() -internal fun systemProp( +internal actual fun systemProp( propertyName: String ): String? = try { @@ -15,36 +18,3 @@ internal fun systemProp( } catch (e: SecurityException) { null } - -internal fun systemProp( - propertyName: String, - defaultValue: Boolean -): Boolean = - try { - System.getProperty(propertyName)?.toBoolean() ?: defaultValue - } catch (e: SecurityException) { - defaultValue - } - -internal fun systemProp( - propertyName: String, - defaultValue: Int, - minValue: Int = 1, - maxValue: Int = Int.MAX_VALUE -): Int - = systemProp(propertyName, defaultValue.toLong(), minValue.toLong(), maxValue.toLong()).toInt() - -internal fun systemProp( - propertyName: String, - defaultValue: Long, - minValue: Long = 1, - maxValue: Long = Long.MAX_VALUE -): Long { - val value = systemProp(propertyName) ?: return defaultValue - val parsed = value.toLongOrNull() - ?: error("System property '$propertyName' has unrecognized value '$value'") - if (parsed !in minValue..maxValue) { - error("System property '$propertyName' should be in range $minValue..$maxValue, but is '$parsed'") - } - return parsed -} diff --git a/kotlinx-coroutines-core/native/src/internal/SystemProps.kt b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt new file mode 100644 index 0000000000..6779d4e5d8 --- /dev/null +++ b/kotlinx-coroutines-core/native/src/internal/SystemProps.kt @@ -0,0 +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 + +internal actual fun systemProp(propertyName: String): String? = null \ No newline at end of file From b4d3dff72800c87c7e4948611645efb6a1c152aa Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Thu, 7 Mar 2019 16:04:48 +0300 Subject: [PATCH 74/82] Do not use reflective exception pre-handler on newer Androids, since Pie runtime ensures that uncaught exception is always logged Fixes #822 --- .../src/AndroidExceptionPreHandler.kt | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt index 761c5c0845..06d1b4fa49 100644 --- a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt +++ b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt @@ -4,30 +4,42 @@ package kotlinx.coroutines.android +import android.os.* import android.support.annotation.* import kotlinx.coroutines.* import java.lang.reflect.* import kotlin.coroutines.* -private val getter = - try { - Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { - Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) - } - } - catch (e: Throwable) { null /* not found */ } +private val getter by lazy { + try { + Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { + Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) + } + } catch (e: Throwable) { + null /* not found */ + } + } -/** - * Uses Android's `Thread.getUncaughtExceptionPreHandler()` whose default behavior is to log exception. - * See - * [here](https://github.com/aosp-mirror/platform_frameworks_base/blob/2efbc7239f419c931784acf98960ed6abc38c3f2/core/java/com/android/internal/os/RuntimeInit.java#L142) - */ @Keep internal class AndroidExceptionPreHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler { override fun handleException(context: CoroutineContext, exception: Throwable) { - (getter?.invoke(null) as? Thread.UncaughtExceptionHandler) - ?.uncaughtException(Thread.currentThread(), exception) + /* + * If we are on old SDK, then use Android's `Thread.getUncaughtExceptionPreHandler()` that ensures that + * an exception is logged before crashing the application. + * + * Since Android Pie default uncaught exception handler always ensures that exception is logged without interfering with + * pre-handler, so reflection hack is no longer needed. + * + * See https://android-review.googlesource.com/c/platform/frameworks/base/+/654578/ + */ + val thread = Thread.currentThread() + if (Build.VERSION.SDK_INT >= 28) { + thread.uncaughtExceptionHandler.uncaughtException(thread, exception) + } else { + (getter?.invoke(null) as? Thread.UncaughtExceptionHandler) + ?.uncaughtException(thread, exception) + } } } \ No newline at end of file From 5ea9339f144f829da94752f57cdbf044d91a6402 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 13 Mar 2019 15:06:14 +0300 Subject: [PATCH 75/82] Merge lazy getter with AndroidExceptionPreHandler to reduce class count --- .../src/AndroidExceptionPreHandler.kt | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt index 06d1b4fa49..09443269f7 100644 --- a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt +++ b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt @@ -10,20 +10,21 @@ import kotlinx.coroutines.* import java.lang.reflect.* import kotlin.coroutines.* -private val getter by lazy { - try { - Thread::class.java.getDeclaredMethod("getUncaughtExceptionPreHandler").takeIf { - Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) - } - } catch (e: Throwable) { - null /* not found */ - } - } - @Keep internal class AndroidExceptionPreHandler : - AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler -{ + AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler, Function0 { + + 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) + } + } catch (e: Throwable) { + null /* not found */ + } + override fun handleException(context: CoroutineContext, exception: Throwable) { /* * If we are on old SDK, then use Android's `Thread.getUncaughtExceptionPreHandler()` that ensures that @@ -38,8 +39,8 @@ internal class AndroidExceptionPreHandler : if (Build.VERSION.SDK_INT >= 28) { thread.uncaughtExceptionHandler.uncaughtException(thread, exception) } else { - (getter?.invoke(null) as? Thread.UncaughtExceptionHandler) + (preHandler?.invoke(null) as? Thread.UncaughtExceptionHandler) ?.uncaughtException(thread, exception) } } -} \ No newline at end of file +} From 0355b2c4fbb73c1bbe71e80acb2d8a18d08ab333 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 22 Mar 2019 16:01:59 +0300 Subject: [PATCH 76/82] Add ThreadLocal.isPresent and ThreadLocal.ensurePresent methods (#1043) Add ThreadLocal.isPresent and ThreadLocal.ensurePresent methods Fixes #1028 --- .../kotlinx-coroutines-core.txt | 2 + docs/coroutine-context-and-dispatchers.md | 7 +++- .../test/ListenableFutureTest.kt | 2 - .../test/future/FutureTest.kt | 1 - .../jvm/src/ThreadContextElement.kt | 37 +++++++++++++++++++ .../jvm/src/internal/ThreadContext.kt | 3 +- kotlinx-coroutines-core/jvm/test/TestBase.kt | 6 +++ .../jvm/test/ThreadLocalTest.kt | 18 +++++++++ .../jvm/test/guide/example-context-11.kt | 2 +- 9 files changed, 72 insertions(+), 6 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 2705acc0e4..21c473accf 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -481,6 +481,8 @@ public final class kotlinx/coroutines/ThreadContextElement$DefaultImpls { public final class kotlinx/coroutines/ThreadContextElementKt { public static final fun asContextElement (Ljava/lang/ThreadLocal;Ljava/lang/Object;)Lkotlinx/coroutines/ThreadContextElement; public static synthetic fun asContextElement$default (Ljava/lang/ThreadLocal;Ljava/lang/Object;ILjava/lang/Object;)Lkotlinx/coroutines/ThreadContextElement; + public static final fun ensurePresent (Ljava/lang/ThreadLocal;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun isPresent (Ljava/lang/ThreadLocal;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class kotlinx/coroutines/ThreadPoolDispatcherKt { diff --git a/docs/coroutine-context-and-dispatchers.md b/docs/coroutine-context-and-dispatchers.md index 00b0db9549..29da4b4067 100644 --- a/docs/coroutine-context-and-dispatchers.md +++ b/docs/coroutine-context-and-dispatchers.md @@ -635,7 +635,7 @@ fun main() = runBlocking { threadLocal.set("main") println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) { - println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") + println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") yield() println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") } @@ -664,6 +664,10 @@ Post-main, current thread: Thread[main @coroutine#1,5,main], thread local value: +Note how easily one may forget the corresponding context element and then still safely access thread local. +To avoid such situations, it is recommended to use [ensurePresent] method +and fail-fast on improper usages. + `ThreadLocal` has first-class support and can be used with any primitive `kotlinx.coroutines` provides. It has one key limitation: when thread-local is mutated, a new value is not propagated to the coroutine caller (as context element cannot track all `ThreadLocal` object accesses) and updated value is lost on the next suspension. @@ -701,5 +705,6 @@ that should be implemented. [MainScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html [Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html [asContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/as-context-element.html +[ensurePresent]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/java.lang.-thread-local/ensure-present.html [ThreadContextElement]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-thread-context-element/index.html diff --git a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt index bfb5cfd452..cf82318a47 100644 --- a/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt +++ b/integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt @@ -11,9 +11,7 @@ import org.hamcrest.core.* import org.junit.* import org.junit.Assert.* import org.junit.Test -import java.io.* import java.util.concurrent.* -import kotlin.test.assertFailsWith class ListenableFutureTest : TestBase() { @Before diff --git a/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt b/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt index 7038363cb5..7d128c6e18 100644 --- a/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt +++ b/integration/kotlinx-coroutines-jdk8/test/future/FutureTest.kt @@ -16,7 +16,6 @@ import java.util.function.* import kotlin.concurrent.* import kotlin.coroutines.* import kotlin.reflect.* -import kotlin.test.assertFailsWith class FutureTest : TestBase() { @Before diff --git a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt index c68ee45cd5..4e8b6cc42e 100644 --- a/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt +++ b/kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt @@ -135,3 +135,40 @@ public interface ThreadContextElement : CoroutineContext.Element { */ public fun ThreadLocal.asContextElement(value: T = get()): ThreadContextElement = ThreadLocalElement(value, this) + +/** + * Return `true` when current thread local is present in the coroutine context, `false` otherwise. + * Thread local can be present in the context only if it was added via [asContextElement] to the context. + * + * Example of usage: + * ``` + * suspend fun processRequest() { + * if (traceCurrentRequestThreadLocal.isPresent()) { // Probabilistic tracing + * // Do some heavy-weight tracing + * } + * // Process request regularly + * } + * ``` + */ +public suspend inline fun ThreadLocal<*>.isPresent(): Boolean = coroutineContext[ThreadLocalKey(this)] !== null + +/** + * Checks whether current thread local is present in the coroutine context and throws [IllegalStateException] if it is not. + * It is a good practice to validate that thread local is present in the context, especially in large code-bases, + * to avoid stale thread-local values and to have a strict invariants. + * + * E.g. one may use the following method to enforce proper use of the thread locals with coroutines: + * ``` + * public suspend inline fun ThreadLocal.getSafely(): T { + * ensurePresent() + * return get() + * } + * + * // Usage + * withContext(...) { + * val value = threadLocal.getSafely() // Fail-fast in case of improper context + * } + * ``` + */ +public suspend inline fun ThreadLocal<*>.ensurePresent(): Unit = + check(isPresent()) { "ThreadLocal $this is missing from context $coroutineContext" } diff --git a/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt index 7dafb4711f..375dc60b66 100644 --- a/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt +++ b/kotlinx-coroutines-core/jvm/src/internal/ThreadContext.kt @@ -98,7 +98,8 @@ internal fun restoreThreadContext(context: CoroutineContext, oldState: Any?) { } // top-level data class for a nicer out-of-the-box toString representation and class name -private data class ThreadLocalKey(private val threadLocal: ThreadLocal<*>) : CoroutineContext.Key> +@PublishedApi +internal data class ThreadLocalKey(private val threadLocal: ThreadLocal<*>) : CoroutineContext.Key> internal class ThreadLocalElement( private val value: T, diff --git a/kotlinx-coroutines-core/jvm/test/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt index db5c53ae80..6fef760af1 100644 --- a/kotlinx-coroutines-core/jvm/test/TestBase.kt +++ b/kotlinx-coroutines-core/jvm/test/TestBase.kt @@ -201,4 +201,10 @@ public actual open class TestBase actual constructor() { if (exCount < unhandled.size) error("Too few unhandled exceptions $exCount, expected ${unhandled.size}") } + + protected inline fun assertFailsWith(block: () -> Unit): T { + val result = runCatching(block) + assertTrue(result.exceptionOrNull() is T, "Expected ${T::class}, but had $result") + return result.exceptionOrNull()!! as T + } } diff --git a/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt b/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt index 62a340eef4..5d8c3d5c6d 100644 --- a/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt +++ b/kotlinx-coroutines-core/jvm/test/ThreadLocalTest.kt @@ -6,6 +6,7 @@ package kotlinx.coroutines import org.junit.* import org.junit.Test +import java.lang.IllegalStateException import kotlin.test.* @Suppress("RedundantAsync") @@ -22,25 +23,33 @@ class ThreadLocalTest : TestBase() { @Test fun testThreadLocal() = runTest { assertNull(stringThreadLocal.get()) + assertFalse(stringThreadLocal.isPresent()) val deferred = async(Dispatchers.Default + stringThreadLocal.asContextElement("value")) { assertEquals("value", stringThreadLocal.get()) + assertTrue(stringThreadLocal.isPresent()) withContext(executor) { + assertTrue(stringThreadLocal.isPresent()) + assertFailsWith { intThreadLocal.ensurePresent() } assertEquals("value", stringThreadLocal.get()) } + assertTrue(stringThreadLocal.isPresent()) assertEquals("value", stringThreadLocal.get()) } assertNull(stringThreadLocal.get()) deferred.await() assertNull(stringThreadLocal.get()) + assertFalse(stringThreadLocal.isPresent()) } @Test fun testThreadLocalInitialValue() = runTest { intThreadLocal.set(42) + assertFalse(intThreadLocal.isPresent()) val deferred = async(Dispatchers.Default + intThreadLocal.asContextElement(239)) { assertEquals(239, intThreadLocal.get()) withContext(executor) { + intThreadLocal.ensurePresent() assertEquals(239, intThreadLocal.get()) } assertEquals(239, intThreadLocal.get()) @@ -63,6 +72,8 @@ class ThreadLocalTest : TestBase() { withContext(executor) { assertEquals(239, intThreadLocal.get()) assertEquals("pew", stringThreadLocal.get()) + intThreadLocal.ensurePresent() + stringThreadLocal.ensurePresent() } assertEquals(239, intThreadLocal.get()) @@ -129,6 +140,7 @@ class ThreadLocalTest : TestBase() { } deferred.await() + assertFalse(stringThreadLocal.isPresent()) assertEquals("main", stringThreadLocal.get()) } @@ -212,4 +224,10 @@ class ThreadLocalTest : TestBase() { assertNotSame(mainThread, Thread.currentThread()) }.await() } + + @Test + fun testMissingThreadLocal() = runTest { + assertFailsWith { stringThreadLocal.ensurePresent() } + assertFailsWith { intThreadLocal.ensurePresent() } + } } 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 8de958e473..1945495cb8 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-context-11.kt @@ -14,7 +14,7 @@ fun main() = runBlocking { threadLocal.set("main") println("Pre-main, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") val job = launch(Dispatchers.Default + threadLocal.asContextElement(value = "launch")) { - println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") + println("Launch start, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") yield() println("After yield, current thread: ${Thread.currentThread()}, thread local value: '${threadLocal.get()}'") } From 74b250ffbe384198bd8d3e8259829ffda63d88a8 Mon Sep 17 00:00:00 2001 From: Nikita Koval Date: Tue, 19 Mar 2019 13:24:07 +0300 Subject: [PATCH 77/82] Add a JMH producer-consumer benchmark for channels --- benchmarks/build.gradle | 5 + .../ChannelProducerConsumerBenchmark.kt | 146 ++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index a82ce226d8..728804ad4b 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -12,8 +12,13 @@ repositories { jmh.jmhVersion = '1.21' +// It is better to use the following to run benchmarks, otherwise you may get unexpected errors: +// ../gradlew --no-daemon cleanJmhJar jmh jmh { duplicateClassesStrategy DuplicatesStrategy.INCLUDE + failOnError = true + resultFormat = 'CSV' +// include = ['.*ChannelProducerConsumer.*'] } jmhJar { diff --git a/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt b/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt new file mode 100644 index 0000000000..77b907f6e9 --- /dev/null +++ b/benchmarks/src/jmh/kotlin/benchmarks/ChannelProducerConsumerBenchmark.kt @@ -0,0 +1,146 @@ +package benchmarks + +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.selects.select +import org.openjdk.jmh.annotations.* +import org.openjdk.jmh.infra.Blackhole +import java.lang.Integer.max +import java.util.concurrent.ForkJoinPool +import java.util.concurrent.Phaser +import java.util.concurrent.ThreadLocalRandom +import java.util.concurrent.TimeUnit + + +/** + * Benchmark to measure channel algorithm performance in terms of average time per `send-receive` pair; + * actually, it measures the time for a batch of such operations separated into the specified number of consumers/producers. + * It uses different channels (rendezvous, buffered, unlimited; see [ChannelCreator]) and different dispatchers + * (see [DispatcherCreator]). If the [_3_withSelect] property is set, it invokes `send` and + * `receive` via [select], waiting on a local dummy channel simultaneously, simulating a "cancellation" channel. + * + * Please, be patient, this benchmark takes quite a lot of time to complete. + */ +@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MICROSECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MICROSECONDS) +@Fork(value = 3) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +open class ChannelProducerConsumerBenchmark { + @Param + private var _0_dispatcher: DispatcherCreator = DispatcherCreator.FORK_JOIN + + @Param + private var _1_channel: ChannelCreator = ChannelCreator.RENDEZVOUS + + @Param("0", "1000") + private var _2_coroutines: Int = 0 + + @Param("false", "true") + private var _3_withSelect: Boolean = false + + @Param("1", "2", "4") // local machine +// @Param("1", "2", "4", "8", "12") // local machine +// @Param("1", "2", "4", "8", "16", "32", "64", "128", "144") // dasquad +// @Param("1", "2", "4", "8", "16", "32", "64", "96") // Google Cloud + private var _4_parallelism: Int = 0 + + private lateinit var dispatcher: CoroutineDispatcher + private lateinit var channel: Channel + + @InternalCoroutinesApi + @Setup + fun setup() { + dispatcher = _0_dispatcher.create(_4_parallelism) + channel = _1_channel.create() + } + + @Benchmark + fun spmc() { + if (_2_coroutines != 0) return + val producers = max(1, _4_parallelism - 1) + val consumers = 1 + run(producers, consumers) + } + + @Benchmark + fun mpmc() { + val producers = if (_2_coroutines == 0) (_4_parallelism + 1) / 2 else _2_coroutines / 2 + val consumers = producers + run(producers, consumers) + } + + private fun run(producers: Int, consumers: Int) { + val n = APPROX_BATCH_SIZE / producers * producers + val phaser = Phaser(producers + consumers + 1) + // Run producers + repeat(producers) { + GlobalScope.launch(dispatcher) { + val dummy = if (_3_withSelect) _1_channel.create() else null + repeat(n / producers) { + produce(it, dummy) + } + phaser.arrive() + } + } + // Run consumers + repeat(consumers) { + GlobalScope.launch(dispatcher) { + val dummy = if (_3_withSelect) _1_channel.create() else null + repeat(n / consumers) { + consume(dummy) + } + phaser.arrive() + } + } + // Wait until work is done + phaser.arriveAndAwaitAdvance() + } + + private suspend fun produce(element: Int, dummy: Channel?) { + if (_3_withSelect) { + select { + channel.onSend(element) {} + dummy!!.onReceive {} + } + } else { + channel.send(element) + } + doWork() + } + + private suspend fun consume(dummy: Channel?) { + if (_3_withSelect) { + select { + channel.onReceive {} + dummy!!.onReceive {} + } + } else { + channel.receive() + } + doWork() + } +} + +enum class DispatcherCreator(val create: (parallelism: Int) -> CoroutineDispatcher) { + FORK_JOIN({ parallelism -> ForkJoinPool(parallelism).asCoroutineDispatcher() }) +} + +enum class ChannelCreator(private val capacity: Int) { + RENDEZVOUS(Channel.RENDEZVOUS), +// BUFFERED_1(1), + BUFFERED_2(2), +// BUFFERED_4(4), + BUFFERED_32(32), + BUFFERED_128(128), + BUFFERED_UNLIMITED(Channel.UNLIMITED); + + fun create(): Channel = Channel(capacity) +} + +private fun doWork(): Unit = Blackhole.consumeCPU(ThreadLocalRandom.current().nextLong(WORK_MIN, WORK_MAX)) + +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 From 2496dc256712eb3bb282d3291cedc1497a09cdc8 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 5 Mar 2019 18:43:13 +0300 Subject: [PATCH 78/82] Rename CoroutineState to CoroutineInfo and improve its API * Rename jobOrNull to job * Replace coroutine with its context * Add check-and-act on isInstalled flag into synchronized blocks in order to avoid spurious memory leaks during uninstall * Replace WeakHashMap with Set to simplify debug probes --- .../kotlinx-coroutines-debug.txt | 14 +- kotlinx-coroutines-debug/README.md | 4 +- .../{CoroutineState.kt => CoroutineInfo.kt} | 45 +++--- kotlinx-coroutines-debug/src/DebugProbes.kt | 4 +- .../src/internal/DebugProbesImpl.kt | 140 ++++++++++-------- .../src/junit4/CoroutinesTimeoutStatement.kt | 4 +- .../test/CoroutinesDumpTest.kt | 8 +- .../test/RunningThreadStackMergeTest.kt | 1 - .../test/StracktraceUtils.kt | 2 +- 9 files changed, 121 insertions(+), 101 deletions(-) rename kotlinx-coroutines-debug/src/{CoroutineState.kt => CoroutineInfo.kt} (90%) diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt index 96a35c7f83..183495af5c 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-debug.txt @@ -1,11 +1,11 @@ -public final class kotlinx/coroutines/debug/CoroutineState { - public final fun component1 ()Lkotlin/coroutines/Continuation; - public final fun copy (Lkotlin/coroutines/Continuation;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;J)Lkotlinx/coroutines/debug/CoroutineState; - public static synthetic fun copy$default (Lkotlinx/coroutines/debug/CoroutineState;Lkotlin/coroutines/Continuation;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;JILjava/lang/Object;)Lkotlinx/coroutines/debug/CoroutineState; +public final class kotlinx/coroutines/debug/CoroutineInfo { + public final fun component1 ()Lkotlin/coroutines/CoroutineContext; + public final fun copy (Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;J)Lkotlinx/coroutines/debug/CoroutineInfo; + public static synthetic fun copy$default (Lkotlinx/coroutines/debug/CoroutineInfo;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;JILjava/lang/Object;)Lkotlinx/coroutines/debug/CoroutineInfo; public fun equals (Ljava/lang/Object;)Z - public final fun getContinuation ()Lkotlin/coroutines/Continuation; + public final fun getContext ()Lkotlin/coroutines/CoroutineContext; public final fun getCreationStackTrace ()Ljava/util/List; - public final fun getJobOrNull ()Lkotlinx/coroutines/Job; + public final fun getJob ()Lkotlinx/coroutines/Job; public final fun getState ()Lkotlinx/coroutines/debug/State; public fun hashCode ()I public final fun lastObservedStackTrace ()Ljava/util/List; @@ -16,7 +16,7 @@ public final class kotlinx/coroutines/debug/DebugProbes { public static final field INSTANCE Lkotlinx/coroutines/debug/DebugProbes; public final fun dumpCoroutines (Ljava/io/PrintStream;)V public static synthetic fun dumpCoroutines$default (Lkotlinx/coroutines/debug/DebugProbes;Ljava/io/PrintStream;ILjava/lang/Object;)V - public final fun dumpCoroutinesState ()Ljava/util/List; + public final fun dumpCoroutinesInfo ()Ljava/util/List; public final fun getSanitizeStackTraces ()Z public final fun install ()V public final fun jobToString (Lkotlinx/coroutines/Job;)Ljava/lang/String; diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md index 0dc413cd7d..25fc745649 100644 --- a/kotlinx-coroutines-debug/README.md +++ b/kotlinx-coroutines-debug/README.md @@ -10,7 +10,7 @@ Call to [DebugProbes.install] installs debug agent via ByteBuddy and starts spyi After that, you can use [DebugProbes.dumpCoroutines] to print all active (suspended or running) coroutines, including their state, creation and suspension stacktraces. -Additionally, it is possible to process the list of such coroutines via [DebugProbes.dumpCoroutinesState] or dump isolated parts +Additionally, it is possible to process the list of such coroutines via [DebugProbes.dumpCoroutinesInfo] or dump isolated parts of coroutines hierarchy referenced by a [Job] or [CoroutineScope] instances using [DebugProbes.printJob] and [DebugProbes.printScope] respectively. ### Using in your project @@ -159,7 +159,7 @@ java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/management/Mana [DebugProbes]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/index.html [DebugProbes.install]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/install.html [DebugProbes.dumpCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines.html -[DebugProbes.dumpCoroutinesState]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines-state.html +[DebugProbes.dumpCoroutinesInfo]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/dump-coroutines-info.html [DebugProbes.printJob]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-job.html [DebugProbes.printScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/kotlinx.coroutines.debug/-debug-probes/print-scope.html diff --git a/kotlinx-coroutines-debug/src/CoroutineState.kt b/kotlinx-coroutines-debug/src/CoroutineInfo.kt similarity index 90% rename from kotlinx-coroutines-debug/src/CoroutineState.kt rename to kotlinx-coroutines-debug/src/CoroutineInfo.kt index 9d4489d4be..2d4b6805f1 100644 --- a/kotlinx-coroutines-debug/src/CoroutineState.kt +++ b/kotlinx-coroutines-debug/src/CoroutineInfo.kt @@ -12,11 +12,11 @@ import kotlin.coroutines.* import kotlin.coroutines.jvm.internal.* /** - * Class describing coroutine state. + * Class describing coroutine info such as its context, state and stacktrace. */ @ExperimentalCoroutinesApi -public data class CoroutineState internal constructor( - public val continuation: Continuation<*>, +public data class CoroutineInfo internal constructor( + val context: CoroutineContext, private val creationStackBottom: CoroutineStackFrame, @JvmField internal val sequenceNumber: Long ) { @@ -25,7 +25,7 @@ public data class CoroutineState internal constructor( * [Job] associated with a current coroutine or null. * May be later used in [DebugProbes.printJob]. */ - public val jobOrNull: Job? get() = continuation.context[Job] + public val job: Job? get() = context[Job] /** * Creation stacktrace of the coroutine. @@ -42,11 +42,12 @@ public data class CoroutineState internal constructor( @JvmField internal var lastObservedThread: Thread? = null - private var lastObservedFrame: CoroutineStackFrame? = null + @JvmField + internal var lastObservedFrame: CoroutineStackFrame? = null // Copy constructor - internal constructor(coroutine: Continuation<*>, state: CoroutineState) : this( - coroutine, + internal constructor(coroutine: Continuation<*>, state: CoroutineInfo) : this( + coroutine.context, state.creationStackBottom, state.sequenceNumber ) { @@ -54,6 +55,21 @@ public data class CoroutineState internal constructor( this.lastObservedFrame = state.lastObservedFrame } + /** + * Last observed stacktrace of the coroutine captured on its suspension or resumption point. + * It means that for [running][State.RUNNING] coroutines resulting stacktrace is inaccurate and + * reflects stacktrace of the resumption point, not the actual current stacktrace. + */ + public fun lastObservedStackTrace(): List { + var frame: CoroutineStackFrame? = lastObservedFrame ?: return emptyList() + val result = ArrayList() + while (frame != null) { + frame.getStackTraceElement()?.let { result.add(sanitize(it)) } + frame = frame.callerFrame + } + return result + } + private fun creationStackTrace(): List { // Skip "Coroutine creation stacktrace" frame return sequence { yieldFrames(creationStackBottom.callerFrame) }.toList() @@ -79,21 +95,6 @@ public data class CoroutineState internal constructor( lastObservedThread = null } } - - /** - * Last observed stacktrace of the coroutine captured on its suspension or resumption point. - * It means that for [running][State.RUNNING] coroutines resulting stacktrace is inaccurate and - * reflects stacktrace of the resumption point, not the actual current stacktrace. - */ - public fun lastObservedStackTrace(): List { - var frame: CoroutineStackFrame? = lastObservedFrame ?: return emptyList() - val result = ArrayList() - while (frame != null) { - frame.getStackTraceElement()?.let { result.add(sanitize(it)) } - frame = frame.callerFrame - } - return result - } } /** diff --git a/kotlinx-coroutines-debug/src/DebugProbes.kt b/kotlinx-coroutines-debug/src/DebugProbes.kt index af30c5e811..a81fd7a880 100644 --- a/kotlinx-coroutines-debug/src/DebugProbes.kt +++ b/kotlinx-coroutines-debug/src/DebugProbes.kt @@ -95,10 +95,10 @@ public object DebugProbes { printJob(scope.coroutineContext[Job] ?: error("Job is not present in the scope"), out) /** - * Returns all existing coroutine states. + * Returns all existing coroutines info. * The resulting collection represents a consistent snapshot of all existing coroutines at the moment of invocation. */ - public fun dumpCoroutinesState(): List = DebugProbesImpl.dumpCoroutinesState() + public fun dumpCoroutinesInfo(): List = DebugProbesImpl.dumpCoroutinesInfo() /** * Dumps all active coroutines into the given output stream, providing a consistent snapshot of all existing coroutines at the moment of invocation. diff --git a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt index bf4286d3e9..29b1e36e09 100644 --- a/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-debug/src/internal/DebugProbesImpl.kt @@ -13,6 +13,7 @@ import java.io.* import java.text.* import java.util.* import kotlin.collections.ArrayList +import kotlin.collections.HashMap import kotlin.coroutines.* import kotlin.coroutines.jvm.internal.* import kotlinx.coroutines.internal.artificialFrame as createArtificialFrame // IDEA bug workaround @@ -25,7 +26,7 @@ import kotlinx.coroutines.internal.artificialFrame as createArtificialFrame // I internal object DebugProbesImpl { private const val ARTIFICIAL_FRAME_MESSAGE = "Coroutine creation stacktrace" private val dateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss") - private val capturedCoroutines = WeakHashMap, CoroutineState>() + private val capturedCoroutines = HashSet>() @Volatile private var installations = 0 private val isInstalled: Boolean get() = installations > 0 @@ -40,7 +41,7 @@ internal object DebugProbesImpl { * Then at least three RUNNING -> RUNNING transitions will occur consecutively and complexity of each is O(depth). * To avoid that quadratic complexity, we are caching lookup result for such chains in this map and update it incrementally. */ - private val stateCache = WeakHashMap() + private val callerInfoCache = HashMap() @Synchronized public fun install() { @@ -63,6 +64,7 @@ internal object DebugProbesImpl { if (--installations != 0) return capturedCoroutines.clear() + callerInfoCache.clear() val cl = Class.forName("kotlin.coroutines.jvm.internal.DebugProbesKt") val cl2 = Class.forName("kotlinx.coroutines.debug.internal.NoOpProbesKt") @@ -77,17 +79,17 @@ internal object DebugProbesImpl { public fun hierarchyToString(job: Job): String { check(isInstalled) { "Debug probes are not installed" } val jobToStack = capturedCoroutines - .filterKeys { it.delegate.context[Job] != null } - .mapKeys { it.key.delegate.context[Job]!! } + .filter { it.delegate.context[Job] != null } + .associateBy({ it.delegate.context[Job]!! }, {it.info}) return buildString { job.build(jobToStack, this, "") } } - private fun Job.build(map: Map, builder: StringBuilder, indent: String) { - val state = map[this] + private fun Job.build(map: Map, builder: StringBuilder, indent: String) { + val info = map[this] val newIndent: String - if (state == null) { // Append coroutine without stacktrace + if (info == null) { // Append coroutine without stacktrace // Do not print scoped coroutines and do not increase indentation level @Suppress("INVISIBLE_REFERENCE") if (this !is kotlinx.coroutines.internal.ScopeCoroutine<*>) { @@ -98,9 +100,9 @@ internal object DebugProbesImpl { } } else { // Append coroutine with its last stacktrace element - val element = state.lastObservedStackTrace().firstOrNull() - val contState = state.state - builder.append("$indent$debugString, continuation is $contState at line $element\n") + val element = info.lastObservedStackTrace().firstOrNull() + val state = info.state + builder.append("$indent$debugString, continuation is $state at line $element\n") newIndent = indent + "\t" } // Append children with new indent @@ -113,39 +115,40 @@ internal object DebugProbesImpl { private val Job.debugString: String get() = if (this is JobSupport) toDebugString() else toString() @Synchronized - public fun dumpCoroutinesState(): List { + public fun dumpCoroutinesInfo(): List { check(isInstalled) { "Debug probes are not installed" } - return capturedCoroutines.entries.asSequence() - .map { CoroutineState(it.key.delegate, it.value) } + return capturedCoroutines.asSequence() + .map { CoroutineInfo(it.delegate, it.info) } .sortedBy { it.sequenceNumber } .toList() } public fun dumpCoroutines(out: PrintStream) { - check(isInstalled) { "Debug probes are not installed" } // Avoid inference with other out/err invocations by creating a string first dumpCoroutines().let { out.println(it) } } @Synchronized private fun dumpCoroutines(): String = buildString { + check(isInstalled) { "Debug probes are not installed" } // Synchronization window can be reduce even more, but no need to do it here append("Coroutines dump ${dateFormat.format(System.currentTimeMillis())}") capturedCoroutines .asSequence() - .sortedBy { it.value.sequenceNumber } - .forEach { (key, value) -> - val observedStackTrace = value.lastObservedStackTrace() - val enhancedStackTrace = enhanceStackTraceWithThreadDump(value, observedStackTrace) - val state = if (value.state == State.RUNNING && enhancedStackTrace === observedStackTrace) - "${value.state} (Last suspension stacktrace, not an actual stacktrace)" + .sortedBy { it.info.sequenceNumber } + .forEach { owner -> + val info = owner.info + val observedStackTrace = info.lastObservedStackTrace() + val enhancedStackTrace = enhanceStackTraceWithThreadDump(info, observedStackTrace) + val state = if (info.state == State.RUNNING && enhancedStackTrace === observedStackTrace) + "${info.state} (Last suspension stacktrace, not an actual stacktrace)" else - value.state.toString() + info.state.toString() - append("\n\nCoroutine $key, state: $state") + append("\n\nCoroutine ${owner.delegate}, state: $state") if (observedStackTrace.isEmpty()) { append("\n\tat ${createArtificialFrame(ARTIFICIAL_FRAME_MESSAGE)}") - printStackTrace(value.creationStackTrace) + printStackTrace(info.creationStackTrace) } else { printStackTrace(enhancedStackTrace) } @@ -153,17 +156,17 @@ internal object DebugProbesImpl { } /** - * Tries to enhance [coroutineTrace] (obtained by call to [CoroutineState.lastObservedStackTrace]) with - * thread dump of [CoroutineState.lastObservedThread]. + * Tries to enhance [coroutineTrace] (obtained by call to [CoroutineInfo.lastObservedStackTrace]) with + * thread dump of [CoroutineInfo.lastObservedThread]. * * Returns [coroutineTrace] if enhancement was unsuccessful or the enhancement result. */ private fun enhanceStackTraceWithThreadDump( - state: CoroutineState, + info: CoroutineInfo, coroutineTrace: List ): List { - val thread = state.lastObservedThread - if (state.state != State.RUNNING || thread == null) return coroutineTrace + val thread = info.lastObservedThread + if (info.state != State.RUNNING || thread == null) return coroutineTrace // Avoid security manager issues val actualTrace = runCatching { thread.stackTrace }.getOrNull() ?: return coroutineTrace @@ -257,48 +260,53 @@ internal object DebugProbesImpl { internal fun probeCoroutineSuspended(frame: Continuation<*>) = updateState(frame, State.SUSPENDED) private fun updateState(frame: Continuation<*>, state: State) { - if (!isInstalled) return // KT-29997 is here only since 1.3.30 if (state == State.RUNNING && KotlinVersion.CURRENT.isAtLeast(1, 3, 30)) { - updateRunningState(frame, state) + val stackFrame = frame as? CoroutineStackFrame ?: return + updateRunningState(stackFrame, state) return } // Find ArtificialStackFrame of the coroutine - val owner = frame.owner() + val owner = frame.owner() ?: return updateState(owner, frame, state) } - @Synchronized // See comment to stateCache - private fun updateRunningState(continuation: Continuation<*>, state: State) { - val frame = continuation as? CoroutineStackFrame ?: return - val coroutineState = stateCache.remove(frame) ?: capturedCoroutines[frame.owner()] ?: return - // Do not cache states for proxy-classes such as ScopeCoroutines - val caller = frame.realCaller() - if (caller != null) { - stateCache[caller] = coroutineState + @Synchronized // See comment to callerInfoCache + private fun updateRunningState(frame: CoroutineStackFrame, state: State) { + if (!isInstalled) return + // Lookup coroutine info in cache or by traversing stack frame + val info: CoroutineInfo + val cached = callerInfoCache.remove(frame) + if (cached != null) { + info = cached + } else { + info = frame.owner()?.info ?: return + // Guard against improper implementations of CoroutineStackFrame and bugs in the compiler + callerInfoCache.remove(info.lastObservedFrame?.realCaller()) } - coroutineState.updateState(state, continuation) + info.updateState(state, frame as Continuation<*>) + // Do not cache it for proxy-classes such as ScopeCoroutines + val caller = frame.realCaller() ?: return + callerInfoCache[caller] = info } private tailrec fun CoroutineStackFrame.realCaller(): CoroutineStackFrame? { val caller = callerFrame ?: return null - if (caller.getStackTraceElement() != null) return caller - else return caller.realCaller() + return if (caller.getStackTraceElement() != null) caller else caller.realCaller() } @Synchronized - private fun updateState(owner: ArtificialStackFrame<*>?, frame: Continuation<*>, state: State) { - val coroutineState = capturedCoroutines[owner] ?: return - coroutineState.updateState(state, frame) + private fun updateState(owner: CoroutineOwner<*>, frame: Continuation<*>, state: State) { + if (!isInstalled) return + owner.info.updateState(state, frame) } - private fun Continuation<*>.owner(): ArtificialStackFrame<*>? = - (this as? CoroutineStackFrame)?.owner() + private fun Continuation<*>.owner(): CoroutineOwner<*>? = (this as? CoroutineStackFrame)?.owner() - private tailrec fun CoroutineStackFrame.owner(): ArtificialStackFrame<*>? = - if (this is ArtificialStackFrame<*>) this else callerFrame?.owner() + private tailrec fun CoroutineStackFrame.owner(): CoroutineOwner<*>? = + if (this is CoroutineOwner<*>) this else callerFrame?.owner() internal fun probeCoroutineCreated(completion: Continuation): Continuation { if (!isInstalled) return completion @@ -312,7 +320,7 @@ internal object DebugProbesImpl { * Here we replace completion with a sequence of CoroutineStackFrame objects * which represents creation stacktrace, thus making stacktrace recovery mechanism * even more verbose (it will attach coroutine creation stacktrace to all exceptions), - * and then using this artificial frame as an identifier of coroutineSuspended/resumed calls. + * and then using CoroutineOwner completion as unique identifier of coroutineSuspended/resumed calls. */ val stacktrace = sanitizeStackTrace(Exception()) val frame = stacktrace.foldRight(null) { frame, acc -> @@ -320,24 +328,38 @@ internal object DebugProbesImpl { override val callerFrame: CoroutineStackFrame? = acc override fun getStackTraceElement(): StackTraceElement = frame } - } - return ArtificialStackFrame(completion, frame!!).also { - storeFrame(it, completion) - } + }!! + + return createOwner(completion, frame) } @Synchronized - private fun storeFrame(frame: ArtificialStackFrame, completion: Continuation) { - capturedCoroutines[frame] = CoroutineState(completion, frame, ++sequenceNumber) + private fun createOwner(completion: Continuation, frame: CoroutineStackFrame): Continuation { + if (!isInstalled) return completion + val info = CoroutineInfo(completion.context, frame, ++sequenceNumber) + val owner = CoroutineOwner(completion, info, frame) + capturedCoroutines += owner + return owner } @Synchronized - private fun probeCoroutineCompleted(coroutine: ArtificialStackFrame<*>) { - capturedCoroutines.remove(coroutine) + private fun probeCoroutineCompleted(owner: CoroutineOwner<*>) { + capturedCoroutines.remove(owner) + /* + * This removal is a guard against improperly implemented CoroutineStackFrame + * and bugs in the compiler. + */ + val caller = owner.info.lastObservedFrame?.realCaller() + callerInfoCache.remove(caller) } - private class ArtificialStackFrame( + /** + * This class is injected as completion of all continuations in [probeCoroutineCompleted]. + * It is owning the coroutine info and responsible for managing all its external info related to debug agent. + */ + private class CoroutineOwner( @JvmField val delegate: Continuation, + @JvmField val info: CoroutineInfo, frame: CoroutineStackFrame ) : Continuation by delegate, CoroutineStackFrame by frame { override fun resumeWith(result: Result) { diff --git a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt index fd74fa96ec..a00a17d58d 100644 --- a/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt +++ b/kotlinx-coroutines-debug/src/junit4/CoroutinesTimeoutStatement.kt @@ -73,8 +73,8 @@ internal class CoroutinesTimeoutStatement( private fun cancelIfNecessary() { if (cancelOnTimeout) { - DebugProbes.dumpCoroutinesState().forEach { - it.jobOrNull?.cancel() + DebugProbes.dumpCoroutinesInfo().forEach { + it.job?.cancel() } } } diff --git a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt index a59f22341c..35e9d1e9f2 100644 --- a/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt +++ b/kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt @@ -5,8 +5,6 @@ package kotlinx.coroutines.debug import kotlinx.coroutines.* -import kotlinx.coroutines.debug.junit4.* -import org.junit.* import org.junit.Test import kotlin.coroutines.* import kotlin.test.* @@ -32,8 +30,8 @@ class CoroutinesDumpTest : DebugTestBase() { "\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" + "\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:99)\n") - val found = DebugProbes.dumpCoroutinesState().single { it.jobOrNull === deferred } - assertSame(deferred, found.jobOrNull) + val found = DebugProbes.dumpCoroutinesInfo().single { it.job === deferred } + assertSame(deferred, found.job) runBlocking { deferred.cancelAndJoin() } } @@ -96,7 +94,7 @@ class CoroutinesDumpTest : DebugTestBase() { } awaitCoroutineStarted() - val coroutine = DebugProbes.dumpCoroutinesState().first() + val coroutine = DebugProbes.dumpCoroutinesInfo().first() val result = coroutine.creationStackTrace.fold(StringBuilder()) { acc, element -> acc.append(element.toString()) acc.append('\n') diff --git a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt index 1decf54430..72082942e8 100644 --- a/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt +++ b/kotlinx-coroutines-debug/test/RunningThreadStackMergeTest.kt @@ -17,7 +17,6 @@ class RunningThreadStackMergeTest : DebugTestBase() { fun testStackMergeWithContext() = runTest { launchCoroutine() awaitCoroutineStarted() - verifyDump( "Coroutine \"coroutine#1\":BlockingCoroutine{Active}@62230679", // <- this one is ignored "Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@50284dc4, state: RUNNING\n" + diff --git a/kotlinx-coroutines-debug/test/StracktraceUtils.kt b/kotlinx-coroutines-debug/test/StracktraceUtils.kt index 62dcd78d45..cab4ed86b3 100644 --- a/kotlinx-coroutines-debug/test/StracktraceUtils.kt +++ b/kotlinx-coroutines-debug/test/StracktraceUtils.kt @@ -97,7 +97,7 @@ public fun verifyPartialDump(createdCoroutinesCount: Int, vararg frames: String) trace.any { tr -> tr.contains(frame) } } - assertEquals(createdCoroutinesCount, DebugProbes.dumpCoroutinesState().size) + assertEquals(createdCoroutinesCount, DebugProbes.dumpCoroutinesInfo().size) assertTrue(matches) } From 6227c64cb00d447843f03187e86e56e97541c24a Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Tue, 19 Mar 2019 13:22:19 +0300 Subject: [PATCH 79/82] Improved coroutine exception handling logic * JobSupport.handleJobException (which is called before the coroutine goes to the final state) is now called only when parent did not handle exception and is used only in launch-like coroutines (launch and actor) to report uncaught exception. * The final result of other types coroutines that, by default, have an object "to store exceptions" is consistently processed after all other notifications when the coroutine state is already complete and is reported as uncaught exception as a last-resort processing tactic when it cannot be otherwise handled. * The above change makes the order of notifications for future { ... } and other async-like coroutine builders consistent with the order in which async { ... }.await() is notified. * The "handled" state of exception (whether it was processed or not) is now stored in CompletedExceptionally marker class (pulled this field up from CancelledContinuation). * AbstractCoroutine.onCompletedExceptionally is renamed to onCancelled and includes "handled" flag. * protected val JobSupport.completionCauseHandled is introduced to access "handled" flag, which simplified reactive streams integration. * "suppressed" flag is dropped from JobSupport.onCompletionInternal. * Fixed exception processing in reactive integrations -- exception that is thrown from a cancelled (disposed) coroutine is not lost anymore. --- .../kotlinx-coroutines-core.txt | 5 +- .../src/ListenableFuture.kt | 6 +- .../src/future/Future.kt | 6 +- .../common/src/AbstractCoroutine.kt | 15 +++-- .../common/src/Builders.common.kt | 9 +-- .../common/src/CompletedExceptionally.kt | 15 +++-- .../common/src/JobSupport.kt | 66 +++++++++---------- kotlinx-coroutines-core/common/src/Timeout.kt | 2 +- .../common/src/channels/Broadcast.kt | 9 ++- .../common/src/channels/Produce.kt | 9 ++- .../common/src/internal/Scopes.kt | 2 +- .../common/test/AbstractCoroutineTest.kt | 6 +- .../common/test/ParentCancellationTest.kt | 44 +++++++++---- kotlinx-coroutines-core/jvm/src/Builders.kt | 2 +- .../jvm/src/channels/Actor.kt | 9 +-- .../test/exceptions/ProduceExceptionsTest.kt | 7 +- .../jvm/test/exceptions/SuppressionTests.kt | 6 +- .../src/Publish.kt | 25 ++----- .../kotlinx-coroutines-reactor/src/Mono.kt | 8 ++- .../test/MonoTest.kt | 50 ++++++++++++++ .../src/RxCompletable.kt | 8 ++- .../kotlinx-coroutines-rx2/src/RxMaybe.kt | 10 +-- .../src/RxObservable.kt | 12 +++- .../kotlinx-coroutines-rx2/src/RxSingle.kt | 8 ++- .../test/CompletableTest.kt | 51 +++++++++++++- .../kotlinx-coroutines-rx2/test/MaybeTest.kt | 50 ++++++++++++++ .../kotlinx-coroutines-rx2/test/SingleTest.kt | 49 ++++++++++++++ 27 files changed, 360 insertions(+), 129 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 21c473accf..d8293385cc 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -6,8 +6,8 @@ public abstract class kotlinx/coroutines/AbstractCoroutine : kotlinx/coroutines/ public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; public fun isActive ()Z protected fun onCancellation (Ljava/lang/Throwable;)V + protected fun onCancelled (Ljava/lang/Throwable;Z)V protected fun onCompleted (Ljava/lang/Object;)V - protected fun onCompletedExceptionally (Ljava/lang/Throwable;)V protected fun onStart ()V public final fun resumeWith (Ljava/lang/Object;)V public final fun start (Lkotlinx/coroutines/CoroutineStart;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V @@ -382,11 +382,12 @@ public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlin public fun getChildJobCancellationCause ()Ljava/lang/Throwable; public final fun getChildren ()Lkotlin/sequences/Sequence; protected final fun getCompletionCause ()Ljava/lang/Throwable; + protected final fun getCompletionCauseHandled ()Z public final fun getCompletionExceptionOrNull ()Ljava/lang/Throwable; protected fun getHandlesException ()Z public final fun getKey ()Lkotlin/coroutines/CoroutineContext$Key; public final fun getOnJoin ()Lkotlinx/coroutines/selects/SelectClause0; - protected fun handleJobException (Ljava/lang/Throwable;Z)V + protected fun handleJobException (Ljava/lang/Throwable;)Z public final fun invokeOnCompletion (Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/DisposableHandle; public final fun invokeOnCompletion (ZZLkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/DisposableHandle; public fun isActive ()Z diff --git a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt index cb190aaf53..a924bb4aa3 100644 --- a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt +++ b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt @@ -68,10 +68,10 @@ private class ListenableFutureCoroutine( future.set(value) } - override fun handleJobException(exception: Throwable, handled: Boolean) { - if (!future.setException(exception) && !handled) { + override fun onCancelled(cause: Throwable, handled: Boolean) { + if (!future.setException(cause) && !handled) { // prevents loss of exception that was not handled by parent & could not be set to SettableFuture - handleCoroutineException(context, exception) + handleCoroutineException(context, cause) } } } diff --git a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt index e890b025ee..8c4d74e01d 100644 --- a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt +++ b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt @@ -57,10 +57,10 @@ private class CompletableFutureCoroutine( future.complete(value) } - override fun handleJobException(exception: Throwable, handled: Boolean) { - if (!future.completeExceptionally(exception) && !handled) { + override fun onCancelled(cause: Throwable, handled: Boolean) { + if (!future.completeExceptionally(cause) && !handled) { // prevents loss of exception that was not handled by parent & could not be set to CompletableFuture - handleCoroutineException(context, exception) + handleCoroutineException(context, cause) } } } diff --git a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt index 3bdf003e3c..aa6d095f04 100644 --- a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt @@ -24,7 +24,7 @@ import kotlin.jvm.* * * [onCancellation] is invoked as soon as coroutine is _failing_, or is cancelled, * or when it completes for any reason. * * [onCompleted] is invoked when coroutine completes with a value. - * * [onCompletedExceptionally] in invoked when coroutines completes with exception. + * * [onCancelled] in invoked when coroutines completes with exception (cancelled). * * @param parentContext context of the parent coroutine. * @param active when `true` (by default) coroutine is created in _active_ state, when `false` in _new_ state. @@ -89,20 +89,21 @@ public abstract class AbstractCoroutine( protected override fun onCancellation(cause: Throwable?) {} /** - * This function is invoked once when job is completed normally with the specified [value]. + * This function is invoked once when job was completed normally with the specified [value]. */ protected open fun onCompleted(value: T) {} /** - * This function is invoked once when job is completed exceptionally with the specified [exception]. + * This function is invoked once when job was cancelled with the specified [cause]. + * @param cause The cancellation (failure) cause + * @param handled `true` if the exception was handled by parent (always `true` when it is a [CancellationException]) */ - // todo: rename to onCancelled - protected open fun onCompletedExceptionally(exception: Throwable) {} + protected open fun onCancelled(cause: Throwable, handled: Boolean) {} @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { + internal override fun onCompletionInternal(state: Any?, mode: Int) { if (state is CompletedExceptionally) - onCompletedExceptionally(state.cause) + onCancelled(state.cause, state.handled) else onCompleted(state as T) } diff --git a/kotlinx-coroutines-core/common/src/Builders.common.kt b/kotlinx-coroutines-core/common/src/Builders.common.kt index e311b73bcc..aeb714e692 100644 --- a/kotlinx-coroutines-core/common/src/Builders.common.kt +++ b/kotlinx-coroutines-core/common/src/Builders.common.kt @@ -179,8 +179,9 @@ private open class StandaloneCoroutine( parentContext: CoroutineContext, active: Boolean ) : AbstractCoroutine(parentContext, active) { - override fun handleJobException(exception: Throwable, handled: Boolean) { - if (!handled) handleCoroutineException(context, exception) + override fun handleJobException(exception: Throwable): Boolean { + handleCoroutineException(context, exception) + return true } } @@ -240,10 +241,10 @@ private class DispatchedCoroutine( } } - override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { + override fun onCompletionInternal(state: Any?, mode: Int) { if (tryResume()) return // completed before getResult invocation -- bail out // otherwise, getResult has already commenced, i.e. completed later or in other thread - super.onCompletionInternal(state, mode, suppressed) + super.onCompletionInternal(state, mode) } fun getResult(): Any? { diff --git a/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt b/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt index 0f5ad7f570..d15c857566 100644 --- a/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt +++ b/kotlinx-coroutines-core/common/src/CompletedExceptionally.kt @@ -18,8 +18,12 @@ internal fun Result.toState(): Any? = * or artificial [CancellationException] if no cause was provided */ internal open class CompletedExceptionally( - @JvmField public val cause: Throwable + @JvmField public val cause: Throwable, + handled: Boolean = false ) { + private val _handled = atomic(handled) + val handled: Boolean get() = _handled.value + fun makeHandled(): Boolean = _handled.compareAndSet(false, true) override fun toString(): String = "$classSimpleName[$cause]" } @@ -34,10 +38,7 @@ internal class CancelledContinuation( continuation: Continuation<*>, cause: Throwable?, handled: Boolean -) : CompletedExceptionally(cause ?: CancellationException("Continuation $continuation was cancelled normally")) { - private val resumed = atomic(false) - private val handled = atomic(handled) - - fun makeResumed(): Boolean = resumed.compareAndSet(false, true) - fun makeHandled(): Boolean = handled.compareAndSet(false, true) +) : CompletedExceptionally(cause ?: CancellationException("Continuation $continuation was cancelled normally"), handled) { + private val _resumed = atomic(false) + fun makeResumed(): Boolean = _resumed.compareAndSet(false, true) } diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index 43034ae2a8..85d5c68ae3 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -118,7 +118,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren ------ completion listeners are not admitted anymore, invokeOnCompletion returns NonDisposableHandle + parentHandle.dispose + notifyCompletion (invoke all completion listeners) - + onCompletionInternal / onCompleted / onCompletedExceptionally + + onCompletionInternal / onCompleted / onCancelled --------------------------------------------------------------------------------- */ @@ -193,9 +193,9 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren // ## IMPORTANT INVARIANT: Only one thread can be concurrently invoking this method. private fun tryFinalizeFinishingState(state: Finishing, proposedUpdate: Any?, mode: Int): Boolean { /* - * Note: proposed state can be Incompleted, e.g. + * Note: proposed state can be Incomplete, e.g. * async { - * smth.invokeOnCompletion {} // <- returns handle which implements Incomplete under the hood + * something.invokeOnCompletion {} // <- returns handle which implements Incomplete under the hood * } */ require(this.state === state) // consistency check -- it cannot change @@ -203,12 +203,10 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren require(state.isCompleting) // consistency check -- must be marked as completing val proposedException = (proposedUpdate as? CompletedExceptionally)?.cause // Create the final exception and seal the state so that no more exceptions can be added - var suppressed = false val finalException = synchronized(state) { val exceptions = state.sealLocked(proposedException) val finalCause = getFinalRootCause(state, exceptions) - // Report suppressed exceptions if initial cause doesn't match final cause (due to JCE unwrapping) - if (finalCause != null) suppressed = suppressExceptions(finalCause, exceptions) || finalCause !== state.rootCause + if (finalCause != null) addSuppressedExceptions(finalCause, exceptions) finalCause } // Create the final state object @@ -222,13 +220,13 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } // Now handle the final exception if (finalException != null) { - val handledByParent = cancelParent(finalException) - handleJobException(finalException, handledByParent) + val handled = cancelParent(finalException) || handleJobException(finalException) + if (handled) (finalState as CompletedExceptionally).makeHandled() } // Then CAS to completed state -> it must succeed require(_state.compareAndSet(state, finalState.boxIncomplete())) { "Unexpected state: ${_state.value}, expected: $state, update: $finalState" } // And process all post-completion actions - completeStateFinalization(state, finalState, mode, suppressed) + completeStateFinalization(state, finalState, mode) return true } @@ -243,18 +241,15 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren return exceptions.firstOrNull { it !is CancellationException } ?: exceptions[0] } - private fun suppressExceptions(rootCause: Throwable, exceptions: List): Boolean { - if (exceptions.size <= 1) return false // nothing more to do here + private fun addSuppressedExceptions(rootCause: Throwable, exceptions: List) { + if (exceptions.size <= 1) return // nothing more to do here val seenExceptions = identitySet(exceptions.size) - var suppressed = false for (exception in exceptions) { val unwrapped = unwrap(exception) if (unwrapped !== rootCause && unwrapped !is CancellationException && seenExceptions.add(unwrapped)) { rootCause.addSuppressedThrowable(unwrapped) - suppressed = true } } - return suppressed } // fast-path method to finalize normally completed coroutines without children @@ -262,12 +257,12 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren check(state is Empty || state is JobNode<*>) // only simple state without lists where children can concurrently add check(update !is CompletedExceptionally) // only for normal completion if (!_state.compareAndSet(state, update.boxIncomplete())) return false - completeStateFinalization(state, update, mode, false) + completeStateFinalization(state, update, mode) return true } // suppressed == true when any exceptions were suppressed while building the final completion cause - private fun completeStateFinalization(state: Incomplete, update: Any?, mode: Int, suppressed: Boolean) { + private fun completeStateFinalization(state: Incomplete, update: Any?, mode: Int) { /* * Now the job in THE FINAL state. We need to properly handle the resulting state. * Order of various invocations here is important. @@ -303,7 +298,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * It should be last so all callbacks observe consistent state * of the job which doesn't depend on callback scheduling. */ - onCompletionInternal(update, mode, suppressed) + onCompletionInternal(update, mode) } private fun notifyCancelling(list: NodeList, cause: Throwable) { @@ -387,18 +382,21 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * [cancel] cause, [CancellationException] or **`null` if this job had completed normally**. * This function throws [IllegalStateException] when invoked for an job that has not [completed][isCompleted] nor * is being cancelled yet. - * - * @suppress **This is unstable API and it is subject to change.** */ - protected fun getCompletionCause(): Throwable? = loopOnState { state -> - return when (state) { + protected val completionCause: Throwable? + get() = when (val state = state) { is Finishing -> state.rootCause ?: error("Job is still new or active: $this") is Incomplete -> error("Job is still new or active: $this") is CompletedExceptionally -> state.cause else -> null } - } + + /** + * Returns `true` when [completionCause] exception was handled by parent coroutine. + */ + protected val completionCauseHandled: Boolean + get() = state.let { it is CompletedExceptionally && it.handled } @Suppress("OverridingDeprecatedMember") public final override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle = @@ -859,8 +857,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } public final override val children: Sequence get() = sequence { - val state = this@JobSupport.state - when (state) { + when (val state = this@JobSupport.state) { is ChildHandleNode -> yield(state.childJob) is Incomplete -> state.list?.let { list -> list.forEach { yield(it.childJob) } @@ -885,6 +882,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren /** * Override to process any exceptions that were encountered while invoking completion handlers * installed via [invokeOnCompletion]. + * * @suppress **This is unstable API and it is subject to change.** */ internal open fun handleOnCompletionException(exception: Throwable) { @@ -910,7 +908,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren protected open val cancelsParent: Boolean get() = true /** - * Returns `true` for jobs that handle their exceptions via [handleJobException] or integrate them + * Returns `true` for jobs that handle their exceptions or integrate them * into the job's result via [onCompletionInternal]. The only instance of the [Job] that does not * handle its exceptions is [JobImpl] and its subclass [SupervisorJobImpl]. * @@ -919,17 +917,18 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren protected open val handlesException: Boolean get() = true /** - * Handles the final job [exception] after it was reported to the by the parent, - * where [handled] is `true` when parent had already handled exception and `false` otherwise. + * Handles the final job [exception] that was not handled by the parent coroutine. + * Returns `true` if it handles exception (so handling at later stages is not needed). + * It is designed to be overridden by launch-like coroutines + * (`StandaloneCoroutine` and `ActorCoroutine`) that don't have a result type + * that can represent exceptions. * * This method is invoked **exactly once** when the final exception of the job is determined * and before it becomes complete. At the moment of invocation the job and all its children are complete. * - * Note, [handled] is always `true` when [exception] is [CancellationException]. - * * @suppress **This is unstable API and it is subject to change.* */ - protected open fun handleJobException(exception: Throwable, handled: Boolean) {} + protected open fun handleJobException(exception: Throwable): Boolean = false private fun cancelParent(cause: Throwable): Boolean { // CancellationException is considered "normal" and parent is not cancelled when child produces it. @@ -944,10 +943,10 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren * Override for post-completion actions that need to do something with the state. * @param state the final state. * @param mode completion mode. - * @param suppressed true when any exceptions were suppressed while building the final completion cause. + * * @suppress **This is unstable API and it is subject to change.** */ - internal open fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) {} + internal open fun onCompletionInternal(state: Any?, mode: Int) {} // for nicer debugging public override fun toString(): String = @@ -1015,8 +1014,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren return } if (exception === rootCause) return // nothing to do - val eh = _exceptionsHolder // volatile read - when (eh) { + when (val eh = _exceptionsHolder) { // volatile read null -> _exceptionsHolder = exception is Throwable -> { if (exception === eh) return // nothing to do diff --git a/kotlinx-coroutines-core/common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt index efda5a7b17..086c5612d5 100644 --- a/kotlinx-coroutines-core/common/src/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/Timeout.kt @@ -95,7 +95,7 @@ private open class TimeoutCoroutine( } @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { + internal override fun onCompletionInternal(state: Any?, mode: Int) { if (state is CompletedExceptionally) uCont.resumeUninterceptedWithExceptionMode(state.cause, mode) else diff --git a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt index d2f7fe6447..4ad6b8c42f 100644 --- a/kotlinx-coroutines-core/common/src/channels/Broadcast.kt +++ b/kotlinx-coroutines-core/common/src/channels/Broadcast.kt @@ -109,10 +109,13 @@ private open class BroadcastCoroutine( return true // does not matter - result is used in DEPRECATED functions only } - override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { - val cause = (state as? CompletedExceptionally)?.cause + override fun onCompleted(value: Unit) { + _channel.close() + } + + override fun onCancelled(cause: Throwable, handled: Boolean) { val processed = _channel.close(cause) - if (cause != null && !processed && suppressed) handleCoroutineException(context, cause) + if (!processed && !handled) handleCoroutineException(context, cause) } } diff --git a/kotlinx-coroutines-core/common/src/channels/Produce.kt b/kotlinx-coroutines-core/common/src/channels/Produce.kt index e456d82d0d..9d1df1d430 100644 --- a/kotlinx-coroutines-core/common/src/channels/Produce.kt +++ b/kotlinx-coroutines-core/common/src/channels/Produce.kt @@ -94,9 +94,12 @@ private class ProducerCoroutine( override val isActive: Boolean get() = super.isActive - override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { - val cause = (state as? CompletedExceptionally)?.cause + override fun onCompleted(value: Unit) { + _channel.close() + } + + override fun onCancelled(cause: Throwable, handled: Boolean) { val processed = _channel.close(cause) - if (cause != null && !processed && suppressed) handleCoroutineException(context, cause) + if (!processed && !handled) handleCoroutineException(context, cause) } } diff --git a/kotlinx-coroutines-core/common/src/internal/Scopes.kt b/kotlinx-coroutines-core/common/src/internal/Scopes.kt index 5ffaa61e71..7fa6e7c792 100644 --- a/kotlinx-coroutines-core/common/src/internal/Scopes.kt +++ b/kotlinx-coroutines-core/common/src/internal/Scopes.kt @@ -23,7 +23,7 @@ internal open class ScopeCoroutine( get() = false // it throws exception to parent instead of cancelling it @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { + internal override fun onCompletionInternal(state: Any?, mode: Int) { if (state is CompletedExceptionally) { val exception = if (mode == MODE_IGNORE) state.cause else recoverStackTrace(state.cause, uCont) uCont.resumeUninterceptedWithExceptionMode(exception, mode) diff --git a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt index 5f6dbd10cc..5e46ea1963 100644 --- a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt +++ b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt @@ -28,7 +28,7 @@ class AbstractCoroutineTest : TestBase() { expect(8) } - override fun onCompletedExceptionally(exception: Throwable) { + override fun onCancelled(cause: Throwable, handled: Boolean) { expectUnreached() } } @@ -67,8 +67,8 @@ class AbstractCoroutineTest : TestBase() { expectUnreached() } - override fun onCompletedExceptionally(exception: Throwable) { - assertTrue(exception is TestException1) + override fun onCancelled(cause: Throwable, handled: Boolean) { + assertTrue(cause is TestException1) expect(9) } } diff --git a/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt index 1e688d437b..23f2a10a97 100644 --- a/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt +++ b/kotlinx-coroutines-core/common/test/ParentCancellationTest.kt @@ -40,56 +40,56 @@ class ParentCancellationTest : TestBase() { @Test fun testLaunchChild() = runTest { - testParentCancellation { fail -> + testParentCancellation(runsInScopeContext = true) { fail -> launch { fail() } } } @Test fun testAsyncChild() = runTest { - testParentCancellation { fail -> + testParentCancellation(runsInScopeContext = true) { fail -> async { fail() } } } @Test fun testProduceChild() = runTest { - testParentCancellation { fail -> + testParentCancellation(runsInScopeContext = true) { fail -> produce { fail() } } } @Test fun testBroadcastChild() = runTest { - testParentCancellation { fail -> + testParentCancellation(runsInScopeContext = true) { fail -> broadcast { fail() }.openSubscription() } } @Test fun testSupervisorChild() = runTest { - testParentCancellation(expectParentActive = true, expectUnhandled = true) { fail -> + testParentCancellation(expectParentActive = true, expectUnhandled = true, runsInScopeContext = true) { fail -> supervisorScope { fail() } } } @Test fun testCoroutineScopeChild() = runTest { - testParentCancellation(expectParentActive = true, expectRethrows = true) { fail -> + testParentCancellation(expectParentActive = true, expectRethrows = true, runsInScopeContext = true) { fail -> coroutineScope { fail() } } } @Test fun testWithContextChild() = runTest { - testParentCancellation(expectParentActive = true, expectRethrows = true) { fail -> + testParentCancellation(expectParentActive = true, expectRethrows = true, runsInScopeContext = true) { fail -> withContext(CoroutineName("fail")) { fail() } } } @Test fun testWithTimeoutChild() = runTest { - testParentCancellation(expectParentActive = true, expectRethrows = true) { fail -> + testParentCancellation(expectParentActive = true, expectRethrows = true, runsInScopeContext = true) { fail -> withTimeout(1000) { fail() } } } @@ -98,16 +98,32 @@ class ParentCancellationTest : TestBase() { expectParentActive: Boolean = false, expectRethrows: Boolean = false, expectUnhandled: Boolean = false, + runsInScopeContext: Boolean = false, child: suspend CoroutineScope.(block: suspend CoroutineScope.() -> Unit) -> Unit ) { - testWithException(expectParentActive, expectRethrows, expectUnhandled, TestException(), child) - testWithException(true, expectRethrows, false, CancellationException("Test"), child) + testWithException( + expectParentActive, + expectRethrows, + expectUnhandled, + runsInScopeContext, + TestException(), + child + ) + testWithException( + true, + expectRethrows, + false, + runsInScopeContext, + CancellationException("Test"), + child + ) } private suspend fun CoroutineScope.testWithException( expectParentActive: Boolean, expectRethrows: Boolean, expectUnhandled: Boolean, + runsInScopeContext: Boolean, throwException: Throwable, child: suspend CoroutineScope.(block: suspend CoroutineScope.() -> Unit) -> Unit ) { @@ -124,10 +140,10 @@ class ParentCancellationTest : TestBase() { throw throwException } grandchild.join() - if (expectUnhandled) { - assertSame(throwException, unhandledException) - } else { - assertNull(unhandledException) + when { + !expectParentActive && runsInScopeContext -> expectUnreached() + expectUnhandled -> assertSame(throwException, unhandledException) + else -> assertNull(unhandledException) } } if (expectRethrows && throwException !is CancellationException) { diff --git a/kotlinx-coroutines-core/jvm/src/Builders.kt b/kotlinx-coroutines-core/jvm/src/Builders.kt index 010e6705d9..269410d21d 100644 --- a/kotlinx-coroutines-core/jvm/src/Builders.kt +++ b/kotlinx-coroutines-core/jvm/src/Builders.kt @@ -61,7 +61,7 @@ private class BlockingCoroutine( override val cancelsParent: Boolean get() = false // it throws exception to parent instead of cancelling it - override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) { + override fun onCompletionInternal(state: Any?, mode: Int) { // wake up blocked thread if (Thread.currentThread() != blockedThread) LockSupport.unpark(blockedThread) diff --git a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt index f24eb6892b..a67fe1fa4a 100644 --- a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt +++ b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt @@ -127,16 +127,17 @@ private open class ActorCoroutine( channel: Channel, active: Boolean ) : ChannelCoroutine(parentContext, channel, active), ActorScope { + override val cancelsParent: Boolean get() = true + override fun onCancellation(cause: Throwable?) { _channel.cancel(cause?.let { it as? CancellationException ?: CancellationException("$classSimpleName was cancelled", it) }) } - override val cancelsParent: Boolean get() = true - - override fun handleJobException(exception: Throwable, handled: Boolean) { - if (!handled) handleCoroutineException(context, exception) + override fun handleJobException(exception: Throwable): Boolean { + handleCoroutineException(context, exception) + return true } } diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt b/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt index 56da2aac8c..b4df58ac34 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/ProduceExceptionsTest.kt @@ -51,17 +51,16 @@ class ProduceExceptionsTest : TestBase() { @Test fun testSuppressedException() = runTest { - val produce = produce(Job()) { + val produce = produce(NonCancellable) { launch(start = CoroutineStart.ATOMIC) { - throw TestException() + throw TestException() // child coroutine fails } try { delay(Long.MAX_VALUE) } finally { - throw TestException2() + throw TestException2() // but parent throws another exception while cleaning up } } - try { produce.receive() expectUnreached() diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt index 6ccd73d337..60b5d2b9f6 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt @@ -31,9 +31,9 @@ class SuppressionTests : TestBase() { expectUnreached() } - override fun onCompletedExceptionally(exception: Throwable) { - assertTrue(exception is ArithmeticException) - checkException(exception.suppressed[0]) + override fun onCancelled(cause: Throwable, handled: Boolean) { + assertTrue(cause is ArithmeticException) + checkException(cause.suppressed[0]) expect(9) } } diff --git a/reactive/kotlinx-coroutines-reactive/src/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/Publish.kt index a94e7cdbda..d6b713bfe2 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Publish.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Publish.kt @@ -68,8 +68,6 @@ private class PublisherCoroutine( @Volatile private var cancelled = false // true when Subscription.cancel() is invoked - private var shouldHandleException = false // when handleJobException is invoked - override val isClosedForSend: Boolean get() = isCompleted override val isFull: Boolean = mutex.isLocked override fun close(cause: Throwable?): Boolean = cancelCoroutine(cause) @@ -172,14 +170,11 @@ private class PublisherCoroutine( try { if (_nRequested.value >= CLOSED) { _nRequested.value = SIGNALLED // we'll signal onError/onCompleted (that the final state -- no CAS needed) - val cause = getCompletionCause() + val cause = completionCause // Specification requires that after cancellation requested we don't call onXXX if (cancelled) { - // If the parent had failed to handle our exception (handleJobException was invoked), then - // we must not loose this exception - if (shouldHandleException && cause != null) { - handleCoroutineException(context, cause) - } + // If the parent had failed to handle our exception, then we must not lose this exception + if (cause != null && !completionCauseHandled) handleCoroutineException(context, cause) } else { try { if (cause != null && cause !is CancellationException) { @@ -191,7 +186,7 @@ private class PublisherCoroutine( } catch (e: Throwable) { handleCoroutineException(context, e) } - } + } } } finally { mutex.unlock() @@ -240,19 +235,11 @@ private class PublisherCoroutine( } } - // Note: It is invoked when parent fails to handle an exception and strictly before onCompleted[Exception] - // so here we just raise a flag (and it need NOT be volatile!) to handle this exception. - // This way we defer decision to handle this exception based on our ability to send this exception - // to the subscriber (see doLockedSignalCompleted) - override fun handleJobException(exception: Throwable, handled: Boolean) { - if (!handled) shouldHandleException = true - } - - override fun onCompletedExceptionally(exception: Throwable) { + override fun onCompleted(value: Unit) { signalCompleted() } - override fun onCompleted(value: Unit) { + override fun onCancelled(cause: Throwable, handled: Boolean) { signalCompleted() } diff --git a/reactive/kotlinx-coroutines-reactor/src/Mono.kt b/reactive/kotlinx-coroutines-reactor/src/Mono.kt index 49d3fa169d..7174fb6021 100644 --- a/reactive/kotlinx-coroutines-reactor/src/Mono.kt +++ b/reactive/kotlinx-coroutines-reactor/src/Mono.kt @@ -50,8 +50,12 @@ private class MonoCoroutine( } } - override fun onCompletedExceptionally(exception: Throwable) { - if (!disposed) sink.error(exception) + override fun onCancelled(cause: Throwable, handled: Boolean) { + if (!disposed) { + sink.error(cause) + } else if (!handled) { + handleCoroutineException(context, cause) + } } override fun dispose() { diff --git a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt index c3bb00f01a..7c72edc484 100644 --- a/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt +++ b/reactive/kotlinx-coroutines-reactor/test/MonoTest.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.reactive.* import org.hamcrest.core.* import org.junit.* import org.junit.Assert.* +import org.reactivestreams.* import reactor.core.publisher.* import java.time.Duration.* @@ -204,4 +205,53 @@ class MonoTest : TestBase() { { assert(it is RuntimeException) } ) } + + @Test + fun testSuppressedException() = runTest { + val mono = mono(NonCancellable) { + launch(start = CoroutineStart.ATOMIC) { + throw TestException() // child coroutine fails + } + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException2() // but parent throws another exception while cleaning up + } + } + try { + mono.awaitSingle() + expectUnreached() + } catch (e: TestException) { + assertTrue(e.suppressed[0] is TestException2) + } + } + + @Test + fun testUnhandledException() = runTest( + unhandled = listOf { it -> it is TestException } + ) { + expect(1) + var subscription: Subscription? = null + val mono = mono(NonCancellable) { + expect(4) + subscription!!.cancel() // cancel our own subscription, so that delay will get cancelled + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException() // would not be able to handle it since mono is disposed + } + } + mono.subscribe(object : Subscriber { + override fun onSubscribe(s: Subscription) { + expect(2) + subscription = s + } + override fun onNext(t: Unit?) { expectUnreached() } + override fun onComplete() { expectUnreached() } + override fun onError(t: Throwable) { expectUnreached() } + }) + expect(3) + yield() // run coroutine + finish(5) + } } diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt index 21026afec7..f44ecf7e0c 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt @@ -44,7 +44,11 @@ private class RxCompletableCoroutine( if (!subscriber.isDisposed) subscriber.onComplete() } - override fun onCompletedExceptionally(exception: Throwable) { - if (!subscriber.isDisposed) subscriber.onError(exception) + override fun onCancelled(cause: Throwable, handled: Boolean) { + if (!subscriber.isDisposed) { + subscriber.onError(cause) + } else if (!handled) { + handleCoroutineException(context, cause) + } } } diff --git a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt index 6615414073..3e3f13b43f 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt @@ -5,10 +5,8 @@ package kotlinx.coroutines.rx2 import io.reactivex.* -import io.reactivex.functions.* import kotlinx.coroutines.* import kotlin.coroutines.* -import kotlin.experimental.* /** * Creates cold [maybe][Maybe] that will run a given [block] in a coroutine. @@ -49,7 +47,11 @@ private class RxMaybeCoroutine( } } - override fun onCompletedExceptionally(exception: Throwable) { - if (!subscriber.isDisposed) subscriber.onError(exception) + override fun onCancelled(cause: Throwable, handled: Boolean) { + if (!subscriber.isDisposed) { + subscriber.onError(cause) + } else if (!handled) { + handleCoroutineException(context, cause) + } } } diff --git a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt index 96490b1e06..8f2e9f4ba5 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt @@ -134,7 +134,7 @@ private class RxObservableCoroutine( try { if (_signal.value >= CLOSED) { _signal.value = SIGNALLED // we'll signal onError/onCompleted (that the final state -- no CAS needed) - val cause = getCompletionCause() + val cause = completionCause try { if (cause != null && cause !is CancellationException) subscriber.onError(cause) @@ -150,9 +150,17 @@ private class RxObservableCoroutine( } } - override fun onCancellation(cause: Throwable?) { + private fun signalCompleted() { if (!_signal.compareAndSet(OPEN, CLOSED)) return // abort, other thread invoked doLockedSignalCompleted if (mutex.tryLock()) // if we can acquire the lock doLockedSignalCompleted() } + + override fun onCompleted(value: Unit) { + signalCompleted() + } + + override fun onCancelled(cause: Throwable, handled: Boolean) { + signalCompleted() + } } \ No newline at end of file diff --git a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt index bc60d8e80a..53992d4eb4 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt @@ -44,7 +44,11 @@ private class RxSingleCoroutine( if (!subscriber.isDisposed) subscriber.onSuccess(value) } - override fun onCompletedExceptionally(exception: Throwable) { - if (!subscriber.isDisposed) subscriber.onError(exception) + override fun onCancelled(cause: Throwable, handled: Boolean) { + if (!subscriber.isDisposed) { + subscriber.onError(cause) + } else if (!handled) { + handleCoroutineException(context, cause) + } } } diff --git a/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt b/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt index 5aeb8b36c2..a11807c83c 100644 --- a/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/CompletableTest.kt @@ -4,8 +4,9 @@ package kotlinx.coroutines.rx2 +import io.reactivex.* +import io.reactivex.disposables.* import kotlinx.coroutines.* -import kotlinx.coroutines.reactive.* import org.hamcrest.core.* import org.junit.* import org.junit.Assert.* @@ -109,4 +110,52 @@ class CompletableTest : TestBase() { { assert(it is RuntimeException) } ) } + + @Test + fun testSuppressedException() = runTest { + val completable = rxCompletable(NonCancellable) { + launch(start = CoroutineStart.ATOMIC) { + throw TestException() // child coroutine fails + } + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException2() // but parent throws another exception while cleaning up + } + } + try { + completable.await() + expectUnreached() + } catch (e: TestException) { + assertTrue(e.suppressed[0] is TestException2) + } + } + + @Test + fun testUnhandledException() = runTest( + unhandled = listOf { it -> it is TestException } + ) { + expect(1) + var disposable: Disposable? = null + val completable = rxCompletable(NonCancellable) { + expect(4) + disposable!!.dispose() // cancel our own subscription, so that delay will get cancelled + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException() // would not be able to handle it since mono is disposed + } + } + completable.subscribe(object : CompletableObserver { + override fun onSubscribe(d: Disposable) { + expect(2) + disposable = d + } + override fun onComplete() { expectUnreached() } + override fun onError(t: Throwable) { expectUnreached() } + }) + expect(3) + yield() // run coroutine + finish(5) + } } diff --git a/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt b/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt index eab2ffc7c3..5ef6d0664f 100644 --- a/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/MaybeTest.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.rx2 import io.reactivex.* +import io.reactivex.disposables.* import io.reactivex.functions.* import io.reactivex.internal.functions.Functions.* import kotlinx.coroutines.* @@ -238,4 +239,53 @@ class MaybeTest : TestBase() { yield() // must cancel code inside maybe!!! finish(7) } + + @Test + fun testSuppressedException() = runTest { + val maybe = rxMaybe(NonCancellable) { + launch(start = CoroutineStart.ATOMIC) { + throw TestException() // child coroutine fails + } + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException2() // but parent throws another exception while cleaning up + } + } + try { + maybe.await() + expectUnreached() + } catch (e: TestException) { + assertTrue(e.suppressed[0] is TestException2) + } + } + + @Test + fun testUnhandledException() = runTest( + unhandled = listOf { it -> it is TestException } + ) { + expect(1) + var disposable: Disposable? = null + val maybe = rxMaybe(NonCancellable) { + expect(4) + disposable!!.dispose() // cancel our own subscription, so that delay will get cancelled + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException() // would not be able to handle it since mono is disposed + } + } + maybe.subscribe(object : MaybeObserver { + override fun onSubscribe(d: Disposable) { + expect(2) + disposable = d + } + override fun onComplete() { expectUnreached() } + override fun onSuccess(t: Unit) { expectUnreached() } + override fun onError(t: Throwable) { expectUnreached() } + }) + expect(3) + yield() // run coroutine + finish(5) + } } diff --git a/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt b/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt index 56e5e266d6..2ae9570265 100644 --- a/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt +++ b/reactive/kotlinx-coroutines-rx2/test/SingleTest.kt @@ -5,6 +5,7 @@ package kotlinx.coroutines.rx2 import io.reactivex.* +import io.reactivex.disposables.* import kotlinx.coroutines.* import org.hamcrest.core.* import org.junit.* @@ -189,4 +190,52 @@ class SingleTest : TestBase() { { assert(it is RuntimeException) } ) } + + @Test + fun testSuppressedException() = runTest { + val single = rxSingle(NonCancellable) { + launch(start = CoroutineStart.ATOMIC) { + throw TestException() // child coroutine fails + } + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException2() // but parent throws another exception while cleaning up + } + } + try { + single.await() + expectUnreached() + } catch (e: TestException) { + assertTrue(e.suppressed[0] is TestException2) + } + } + + @Test + fun testUnhandledException() = runTest( + unhandled = listOf { it -> it is TestException } + ) { + expect(1) + var disposable: Disposable? = null + val single = rxSingle(NonCancellable) { + expect(4) + disposable!!.dispose() // cancel our own subscription, so that delay will get cancelled + try { + delay(Long.MAX_VALUE) + } finally { + throw TestException() // would not be able to handle it since mono is disposed + } + } + single.subscribe(object : SingleObserver { + override fun onSubscribe(d: Disposable) { + expect(2) + disposable = d + } + override fun onSuccess(t: Unit) { expectUnreached() } + override fun onError(t: Throwable) { expectUnreached() } + }) + expect(3) + yield() // run coroutine + finish(5) + } } From f2604f656c7c315f997336c0d2db4a050160734f Mon Sep 17 00:00:00 2001 From: Roman Elizarov Date: Fri, 22 Mar 2019 14:37:40 +0300 Subject: [PATCH 80/82] Tweaked order of notifications for better error handling & consistency * JobSupport.onCompletionInternal(onCompleted/onCancelled) is now invoked before all the user-installed listeners with is consistent with how the onCancelling/invokeOnCancelling(onCancelling=true) works. * Now all the state processing (updating the future, reporting unhandled exception, etc) in onCompletionInternal happens before observers that .join/.wait the coroutine are resumed and even before the state is set to final (to avoid exception handing races) with the exception of fast-path successful completion of coroutine. * JobSupport.afterCompletionInternal is introduced. It is invoked after all use-installed listeners and that is where scoped coroutines resume the rest of the code. * Remove empty AbstractCoroutine.onCancellation, move docs to JobSupport * onCancellation renamed to onCancelling for consistency with invokeOnCompletion(onCancelling=true) --- .../kotlinx-coroutines-core.txt | 6 +- .../common/src/AbstractCoroutine.kt | 30 ++++----- .../common/src/Builders.common.kt | 4 +- .../common/src/JobSupport.kt | 63 ++++++++++++------- kotlinx-coroutines-core/common/src/Timeout.kt | 2 +- .../common/src/internal/Scopes.kt | 2 +- .../common/test/AbstractCoroutineTest.kt | 14 ++--- kotlinx-coroutines-core/jvm/src/Builders.kt | 2 +- .../jvm/src/channels/Actor.kt | 2 +- .../jvm/test/exceptions/SuppressionTests.kt | 6 +- .../src/Publish.kt | 19 +++--- .../src/RxObservable.kt | 21 ++++--- 12 files changed, 95 insertions(+), 76 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 d8293385cc..54aa9cfc68 100644 --- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt +++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt @@ -5,9 +5,9 @@ public abstract class kotlinx/coroutines/AbstractCoroutine : kotlinx/coroutines/ public final fun getContext ()Lkotlin/coroutines/CoroutineContext; public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; public fun isActive ()Z - protected fun onCancellation (Ljava/lang/Throwable;)V protected fun onCancelled (Ljava/lang/Throwable;Z)V protected fun onCompleted (Ljava/lang/Object;)V + protected final fun onCompletionInternal (Ljava/lang/Object;)V protected fun onStart ()V public final fun resumeWith (Ljava/lang/Object;)V public final fun start (Lkotlinx/coroutines/CoroutineStart;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V @@ -368,6 +368,7 @@ public final class kotlinx/coroutines/JobKt { public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlinx/coroutines/Job, kotlinx/coroutines/ParentJob, kotlinx/coroutines/selects/SelectClause0 { public fun (Z)V + protected fun afterCompletionInternal (Ljava/lang/Object;I)V public final fun attachChild (Lkotlinx/coroutines/ChildJob;)Lkotlinx/coroutines/ChildHandle; public synthetic fun cancel ()V public synthetic fun cancel (Ljava/lang/Throwable;)Z @@ -396,7 +397,8 @@ public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlin public final fun isCompletedExceptionally ()Z public final fun join (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun minusKey (Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext; - protected fun onCancellation (Ljava/lang/Throwable;)V + protected fun onCancelling (Ljava/lang/Throwable;)V + protected fun onCompletionInternal (Ljava/lang/Object;)V public final fun parentCancelled (Lkotlinx/coroutines/ParentJob;)V public fun plus (Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext; public fun plus (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job; diff --git a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt index aa6d095f04..842187c1fd 100644 --- a/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt +++ b/kotlinx-coroutines-core/common/src/AbstractCoroutine.kt @@ -20,9 +20,8 @@ import kotlin.jvm.* * * The following methods are available for override: * - * * [onStart] is invoked when coroutine is create in not active state and is [started][Job.start]. - * * [onCancellation] is invoked as soon as coroutine is _failing_, or is cancelled, - * or when it completes for any reason. + * * [onStart] is invoked when coroutine was created in not active state and is being [started][Job.start]. + * * [onCancelling] is invoked as soon as coroutine is being cancelled for any reason (or completes). * * [onCompleted] is invoked when coroutine completes with a value. * * [onCancelled] in invoked when coroutines completes with exception (cancelled). * @@ -77,31 +76,26 @@ public abstract class AbstractCoroutine( } /** - * This function is invoked once when this coroutine is cancelled - * similarly to [invokeOnCompletion] with `onCancelling` set to `true`. - * - * The meaning of [cause] parameter: - * * Cause is `null` when job has completed normally. - * * Cause is an instance of [CancellationException] when job was cancelled _normally_. - * **It should not be treated as an error**. In particular, it should not be reported to error logs. - * * Otherwise, the job had been cancelled or failed with exception. - */ - protected override fun onCancellation(cause: Throwable?) {} - - /** - * This function is invoked once when job was completed normally with the specified [value]. + * This function is invoked once when job was completed normally with the specified [value], + * right before all the waiters for coroutine's completion are notified. */ protected open fun onCompleted(value: T) {} /** - * This function is invoked once when job was cancelled with the specified [cause]. + * This function is invoked once when job was cancelled with the specified [cause], + * right before all the waiters for coroutine's completion are notified. + * + * **Note:** the state of the coroutine might not be final yet in this function and should not be queried. + * You can use [completionCause] and [completionCauseHandled] to recover parameters that we passed + * to this `onCancelled` invocation only when [isCompleted] returns `true`. + * * @param cause The cancellation (failure) cause * @param handled `true` if the exception was handled by parent (always `true` when it is a [CancellationException]) */ protected open fun onCancelled(cause: Throwable, handled: Boolean) {} @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int) { + protected final override fun onCompletionInternal(state: Any?) { if (state is CompletedExceptionally) onCancelled(state.cause, state.handled) else diff --git a/kotlinx-coroutines-core/common/src/Builders.common.kt b/kotlinx-coroutines-core/common/src/Builders.common.kt index aeb714e692..5df1e9b8db 100644 --- a/kotlinx-coroutines-core/common/src/Builders.common.kt +++ b/kotlinx-coroutines-core/common/src/Builders.common.kt @@ -241,10 +241,10 @@ private class DispatchedCoroutine( } } - override fun onCompletionInternal(state: Any?, mode: Int) { + override fun afterCompletionInternal(state: Any?, mode: Int) { if (tryResume()) return // completed before getResult invocation -- bail out // otherwise, getResult has already commenced, i.e. completed later or in other thread - super.onCompletionInternal(state, mode) + super.afterCompletionInternal(state, mode) } fun getResult(): Any? { diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index 85d5c68ae3..4c36202ca4 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -98,9 +98,9 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren ~ active coroutine is working (or scheduled to execution) >> childCancelled / cancelImpl invoked ## CANCELLING: state is Finishing, state.rootCause != null - ------ cancelling listeners are not admitted anymore, invokeOnCompletion(onCancellation=true) returns NonDisposableHandle + ------ cancelling listeners are not admitted anymore, invokeOnCompletion(onCancelling=true) returns NonDisposableHandle ------ new children get immediately cancelled, but are still admitted to the list - + onCancellation + + onCancelling + notifyCancelling (invoke all cancelling listeners -- cancel all children, suspended functions resume with exception) + cancelParent (rootCause of cancellation is communicated to the parent, parent is cancelled, too) ~ waits for completion of coroutine body @@ -203,7 +203,9 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren require(state.isCompleting) // consistency check -- must be marked as completing val proposedException = (proposedUpdate as? CompletedExceptionally)?.cause // Create the final exception and seal the state so that no more exceptions can be added + var wasCancelling = false // KLUDGE: we cannot have contract for our own expect fun synchronized val finalException = synchronized(state) { + wasCancelling = state.isCancelling val exceptions = state.sealLocked(proposedException) val finalCause = getFinalRootCause(state, exceptions) if (finalCause != null) addSuppressedExceptions(finalCause, exceptions) @@ -223,6 +225,10 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren val handled = cancelParent(finalException) || handleJobException(finalException) if (handled) (finalState as CompletedExceptionally).makeHandled() } + // Process state updates for the final state before the state of the Job is actually set to the final state + // to avoid races where outside observer may see the job in the final state, yet exception is not handled yet. + if (!wasCancelling) onCancelling(finalException) + onCompletionInternal(finalState) // Then CAS to completed state -> it must succeed require(_state.compareAndSet(state, finalState.boxIncomplete())) { "Unexpected state: ${_state.value}, expected: $state, update: $finalState" } // And process all post-completion actions @@ -257,6 +263,8 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren check(state is Empty || state is JobNode<*>) // only simple state without lists where children can concurrently add check(update !is CompletedExceptionally) // only for normal completion if (!_state.compareAndSet(state, update.boxIncomplete())) return false + onCancelling(null) // simple state is not a failure + onCompletionInternal(update) completeStateFinalization(state, update, mode) return true } @@ -275,14 +283,8 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } val cause = (update as? CompletedExceptionally)?.cause /* - * 2) Invoke onCancellation: for resource cancellation resource cancellation etc. - * Only notify is was not notified yet. - * Note: we do not use notifyCancelling here, since we are going to invoke all completion as our next step - */ - if (!state.isCancelling) onCancellation(cause) - /* - * 3) Invoke completion handlers: .join(), callbacks etc. - * It's important to invoke them only AFTER exception handling, see #208 + * 2) Invoke completion handlers: .join(), callbacks etc. + * It's important to invoke them only AFTER exception handling and everything else, see #208 */ if (state is JobNode<*>) { // SINGLE/SINGLE+ state -- one completion handler (common case) try { @@ -294,16 +296,15 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren state.list?.notifyCompletion(cause) } /* - * 4) Invoke onCompletionInternal: onNext(), timeout de-registration etc. - * It should be last so all callbacks observe consistent state - * of the job which doesn't depend on callback scheduling. + * 3) Resumes the rest of the code in scoped coroutines + * (runBlocking, coroutineScope, withContext, withTimeout, etc) */ - onCompletionInternal(update, mode) + afterCompletionInternal(update, mode) } private fun notifyCancelling(list: NodeList, cause: Throwable) { // first cancel our own children - onCancellation(cause) + onCancelling(cause) notifyHandlers>(list, cause) // then cancel parent cancelParent(cause) // tentative cancellation -- does not matter if there is no parent @@ -671,7 +672,7 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren val causeException = causeExceptionCache ?: createCauseException(cause).also { causeExceptionCache = it } state.addExceptionLocked(causeException) } - // take cause for notification is was not cancelling before + // take cause for notification if was not in cancelling state before state.rootCause.takeIf { !wasCancelling } } notifyRootCause?.let { notifyCancelling(state.list, it) } @@ -890,12 +891,21 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } /** - * This function is invoked once when job is being cancelled, fails, or is completed. - * It's an optimization for [invokeOnCompletion] with `onCancellation` set to `true`. + * This function is invoked once as soon as this job is being cancelled for any reason or completes, + * similarly to [invokeOnCompletion] with `onCancelling` set to `true`. + * + * The meaning of [cause] parameter: + * * Cause is `null` when job has completed normally. + * * Cause is an instance of [CancellationException] when job was cancelled _normally_. + * **It should not be treated as an error**. In particular, it should not be reported to error logs. + * * Otherwise, the job had been cancelled or failed with exception. + * + * The specified [cause] is not the final cancellation cause of this job. + * A job may produce other exceptions while it is failing and the final cause might be different. * * @suppress **This is unstable API and it is subject to change.* */ - protected open fun onCancellation(cause: Throwable?) {} + protected open fun onCancelling(cause: Throwable?) {} /** * When this function returns `true` the parent is cancelled on cancellation of this job. @@ -940,13 +950,24 @@ public open class JobSupport constructor(active: Boolean) : Job, ChildJob, Paren } /** - * Override for post-completion actions that need to do something with the state. + * Override for completion actions that need to update some external object depending on job's state, + * right before all the waiters for coroutine's completion are notified. + * + * @param state the final state. + * + * @suppress **This is unstable API and it is subject to change.** + */ + protected open fun onCompletionInternal(state: Any?) {} + + /** + * Override for the very last action on job's completion to resume the rest of the code in scoped coroutines. + * * @param state the final state. * @param mode completion mode. * * @suppress **This is unstable API and it is subject to change.** */ - internal open fun onCompletionInternal(state: Any?, mode: Int) {} + protected open fun afterCompletionInternal(state: Any?, mode: Int) {} // for nicer debugging public override fun toString(): String = diff --git a/kotlinx-coroutines-core/common/src/Timeout.kt b/kotlinx-coroutines-core/common/src/Timeout.kt index 086c5612d5..9437fd6766 100644 --- a/kotlinx-coroutines-core/common/src/Timeout.kt +++ b/kotlinx-coroutines-core/common/src/Timeout.kt @@ -95,7 +95,7 @@ private open class TimeoutCoroutine( } @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int) { + override fun afterCompletionInternal(state: Any?, mode: Int) { if (state is CompletedExceptionally) uCont.resumeUninterceptedWithExceptionMode(state.cause, mode) else diff --git a/kotlinx-coroutines-core/common/src/internal/Scopes.kt b/kotlinx-coroutines-core/common/src/internal/Scopes.kt index 7fa6e7c792..e424c9a2e8 100644 --- a/kotlinx-coroutines-core/common/src/internal/Scopes.kt +++ b/kotlinx-coroutines-core/common/src/internal/Scopes.kt @@ -23,7 +23,7 @@ internal open class ScopeCoroutine( get() = false // it throws exception to parent instead of cancelling it @Suppress("UNCHECKED_CAST") - internal override fun onCompletionInternal(state: Any?, mode: Int) { + override fun afterCompletionInternal(state: Any?, mode: Int) { if (state is CompletedExceptionally) { val exception = if (mode == MODE_IGNORE) state.cause else recoverStackTrace(state.cause, uCont) uCont.resumeUninterceptedWithExceptionMode(exception, mode) diff --git a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt index 5e46ea1963..ffde0f9635 100644 --- a/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt +++ b/kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt @@ -18,14 +18,14 @@ class AbstractCoroutineTest : TestBase() { expect(3) } - override fun onCancellation(cause: Throwable?) { + override fun onCancelling(cause: Throwable?) { assertEquals(null, cause) expect(5) } override fun onCompleted(value: String) { assertEquals("OK", value) - expect(8) + expect(6) } override fun onCancelled(cause: Throwable, handled: Boolean) { @@ -35,12 +35,12 @@ class AbstractCoroutineTest : TestBase() { coroutine.invokeOnCompletion(onCancelling = true) { assertEquals(null, it) - expect(6) + expect(7) } coroutine.invokeOnCompletion { assertEquals(null, it) - expect(7) + expect(8) } expect(2) coroutine.start() @@ -58,7 +58,7 @@ class AbstractCoroutineTest : TestBase() { expect(3) } - override fun onCancellation(cause: Throwable?) { + override fun onCancelling(cause: Throwable?) { assertTrue(cause is TestException1) expect(5) } @@ -69,7 +69,7 @@ class AbstractCoroutineTest : TestBase() { override fun onCancelled(cause: Throwable, handled: Boolean) { assertTrue(cause is TestException1) - expect(9) + expect(8) } } @@ -80,7 +80,7 @@ class AbstractCoroutineTest : TestBase() { coroutine.invokeOnCompletion { assertTrue(it is TestException1) - expect(8) + expect(9) } expect(2) diff --git a/kotlinx-coroutines-core/jvm/src/Builders.kt b/kotlinx-coroutines-core/jvm/src/Builders.kt index 269410d21d..1f371cf04c 100644 --- a/kotlinx-coroutines-core/jvm/src/Builders.kt +++ b/kotlinx-coroutines-core/jvm/src/Builders.kt @@ -61,7 +61,7 @@ private class BlockingCoroutine( override val cancelsParent: Boolean get() = false // it throws exception to parent instead of cancelling it - override fun onCompletionInternal(state: Any?, mode: Int) { + override fun afterCompletionInternal(state: Any?, mode: Int) { // wake up blocked thread if (Thread.currentThread() != blockedThread) LockSupport.unpark(blockedThread) diff --git a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt index a67fe1fa4a..2d16225317 100644 --- a/kotlinx-coroutines-core/jvm/src/channels/Actor.kt +++ b/kotlinx-coroutines-core/jvm/src/channels/Actor.kt @@ -129,7 +129,7 @@ private open class ActorCoroutine( ) : ChannelCoroutine(parentContext, channel, active), ActorScope { override val cancelsParent: Boolean get() = true - override fun onCancellation(cause: Throwable?) { + override fun onCancelling(cause: Throwable?) { _channel.cancel(cause?.let { it as? CancellationException ?: CancellationException("$classSimpleName was cancelled", it) }) diff --git a/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt index 60b5d2b9f6..6034fccbca 100644 --- a/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt +++ b/kotlinx-coroutines-core/jvm/test/exceptions/SuppressionTests.kt @@ -21,7 +21,7 @@ class SuppressionTests : TestBase() { expect(3) } - override fun onCancellation(cause: Throwable?) { + override fun onCancelling(cause: Throwable?) { assertTrue(cause is ArithmeticException) assertTrue(cause.suppressed.isEmpty()) expect(5) @@ -34,7 +34,7 @@ class SuppressionTests : TestBase() { override fun onCancelled(cause: Throwable, handled: Boolean) { assertTrue(cause is ArithmeticException) checkException(cause.suppressed[0]) - expect(9) + expect(8) } } @@ -47,7 +47,7 @@ class SuppressionTests : TestBase() { coroutine.invokeOnCompletion { assertTrue(it is ArithmeticException) checkException(it.suppressed[0]) - expect(8) + expect(9) } expect(2) diff --git a/reactive/kotlinx-coroutines-reactive/src/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/Publish.kt index d6b713bfe2..4a73fccf45 100644 --- a/reactive/kotlinx-coroutines-reactive/src/Publish.kt +++ b/reactive/kotlinx-coroutines-reactive/src/Publish.kt @@ -162,19 +162,20 @@ private class PublisherCoroutine( */ mutex.unlock() // check isCompleted and and try to regain lock to signal completion - if (isCompleted && mutex.tryLock()) doLockedSignalCompleted() + if (isCompleted && mutex.tryLock()) { + doLockedSignalCompleted(completionCause, completionCauseHandled) + } } // assert: mutex.isLocked() & isCompleted - private fun doLockedSignalCompleted() { + private fun doLockedSignalCompleted(cause: Throwable?, handled: Boolean) { try { if (_nRequested.value >= CLOSED) { _nRequested.value = SIGNALLED // we'll signal onError/onCompleted (that the final state -- no CAS needed) - val cause = completionCause // Specification requires that after cancellation requested we don't call onXXX if (cancelled) { // If the parent had failed to handle our exception, then we must not lose this exception - if (cause != null && !completionCauseHandled) handleCoroutineException(context, cause) + if (cause != null && !handled) handleCoroutineException(context, cause) } else { try { if (cause != null && cause !is CancellationException) { @@ -217,7 +218,7 @@ private class PublisherCoroutine( } // assert: isCompleted - private fun signalCompleted() { + private fun signalCompleted(cause: Throwable?, handled: Boolean) { while (true) { // lock-free loop for nRequested val cur = _nRequested.value if (cur == SIGNALLED) return // some other thread holding lock already signalled cancellation/completion @@ -225,10 +226,10 @@ private class PublisherCoroutine( if (!_nRequested.compareAndSet(cur, CLOSED)) continue // retry on failed CAS // Ok -- marked as CLOSED, now can unlock the mutex if it was locked due to backpressure if (cur == 0L) { - doLockedSignalCompleted() + doLockedSignalCompleted(cause, handled) } else { // otherwise mutex was either not locked or locked in concurrent onNext... try lock it to signal completion - if (mutex.tryLock()) doLockedSignalCompleted() + if (mutex.tryLock()) doLockedSignalCompleted(cause, handled) // Note: if failed `tryLock`, then `doLockedNext` will signal after performing `unlock` } return // done anyway @@ -236,11 +237,11 @@ private class PublisherCoroutine( } override fun onCompleted(value: Unit) { - signalCompleted() + signalCompleted(null, false) } override fun onCancelled(cause: Throwable, handled: Boolean) { - signalCompleted() + signalCompleted(cause, handled) } override fun cancel() { diff --git a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt index 8f2e9f4ba5..97910dad4d 100644 --- a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt +++ b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt @@ -103,7 +103,7 @@ private class RxObservableCoroutine( private fun doLockedNext(elem: T) { // check if already closed for send if (!isActive) { - doLockedSignalCompleted() + doLockedSignalCompleted(completionCause, completionCauseHandled) throw getCancellationException() } // notify subscriber @@ -114,27 +114,28 @@ private class RxObservableCoroutine( // to abort the corresponding send/offer invocation. From the standpoint of coroutines machinery, // this failure is essentially equivalent to a failure of a child coroutine. cancelCoroutine(e) - doLockedSignalCompleted() + doLockedSignalCompleted(e, false) throw e } /* There is no sense to check for `isActive` before doing `unlock`, because cancellation/completion might - happen after this check and before `unlock` (see `onCancellation` that does not do anything + happen after this check and before `unlock` (see signalCompleted that does not do anything if it fails to acquire the lock that we are still holding). We have to recheck `isCompleted` after `unlock` anyway. */ mutex.unlock() // recheck isActive if (!isActive && mutex.tryLock()) - doLockedSignalCompleted() + doLockedSignalCompleted(completionCause, completionCauseHandled) } // assert: mutex.isLocked() - private fun doLockedSignalCompleted() { + private fun doLockedSignalCompleted(cause: Throwable?, handled: Boolean) { + // todo: handled is ignored here, might need something like in PublisherCoroutine to process + // cancellation failures try { if (_signal.value >= CLOSED) { _signal.value = SIGNALLED // we'll signal onError/onCompleted (that the final state -- no CAS needed) - val cause = completionCause try { if (cause != null && cause !is CancellationException) subscriber.onError(cause) @@ -150,17 +151,17 @@ private class RxObservableCoroutine( } } - private fun signalCompleted() { + private fun signalCompleted(cause: Throwable?, handled: Boolean) { if (!_signal.compareAndSet(OPEN, CLOSED)) return // abort, other thread invoked doLockedSignalCompleted if (mutex.tryLock()) // if we can acquire the lock - doLockedSignalCompleted() + doLockedSignalCompleted(cause, handled) } override fun onCompleted(value: Unit) { - signalCompleted() + signalCompleted(null, false) } override fun onCancelled(cause: Throwable, handled: Boolean) { - signalCompleted() + signalCompleted(cause, handled) } } \ No newline at end of file From 0d69e1353d9fcd5867fe74e0912d3f36dc7d8ea8 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Mon, 25 Mar 2019 19:21:40 +0300 Subject: [PATCH 81/82] Unmute test that was failing due to JS BE bug --- kotlinx-coroutines-core/common/test/SupervisorTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/test/SupervisorTest.kt b/kotlinx-coroutines-core/common/test/SupervisorTest.kt index 7ed6a1d7b0..7fdd8fcbdd 100644 --- a/kotlinx-coroutines-core/common/test/SupervisorTest.kt +++ b/kotlinx-coroutines-core/common/test/SupervisorTest.kt @@ -131,7 +131,6 @@ class SupervisorTest : TestBase() { } @Test - @Ignore // JS BE bug fun testSupervisorThrowsWithFailingChild() = runTest(unhandled = listOf({e -> e is TestException2})) { try { supervisorScope { From d36fc16f6e64e372ca2f5089c1cf2b6b8e208268 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 26 Mar 2019 11:14:38 +0300 Subject: [PATCH 82/82] Version 1.2.0-alpha --- CHANGES.md | 28 +++++++++++++++++++ README.md | 10 +++---- bump-version.sh | 7 ++--- 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 +- 9 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0f76a3a3d5..3205844b74 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,33 @@ # Change log for kotlinx.coroutines +## Version 1.2.0-alpha + +* Major debug agent improvements. Real stacktraces are merged with coroutine stacktraces for running coroutines, merging heuristic is improved, API is cleaned up and is on its road to stabilization (#997). +* `CoroutineTimeout` rule or JUnit4 is introduced to simplify coroutines debugging (#938). +* Stacktrace recovery improvements. Exceptions with custom properties are no longer copied, `CopyableThrowable` interface is introduced, machinery is [documented](https://github.com/Kotlin/kotlinx.coroutines/blob/develop/docs/debugging.md) (#921, #950). +* `Dispatchers.Unconfined`, `MainCoroutineDispatcher.immediate`, `MainScope` and `CoroutineScope.cancel` are promoted to stable API (#972). +* `CompletableJob` is introduced (#971). +* Structured concurrency is integrated into futures and listenable futures (#1008). +* `ensurePresent` and `isPresent` extensions for `ThreadLocal` (#1028). +* `ensureActive` extensions for `CoroutineContext`, `CoroutineScope` and `Job` (#963). +* `SendChannel.isFull` and `ReceiveChannel.isEmpty` are deprecated (#1053). +* `withContext` checks cancellation on entering (#962). +* Operator `invoke` on `CoroutineDispatcher` (#428). +* Java 8 extensions for `delay` and `withTimeout` now properly handle too large values (#428). +* Performance of `Dispatcher.Main` initialization is significantly improved (#878). +* A global exception handler for fatal exceptions in coroutines is introduced (#808, #773). +* Major improvements in cancellation machinery and exceptions delivery consistency. Cancel with custom exception is completely removed. +* Kotlin version is updated to 1.3.21. +* Do not use private API on newer Androids to handle exceptions (#822). + +Bug fixes: +* Proper `select` support in debug agent (#931). +* Proper `supervisorScope` support in debug agent (#915). +* Throwing `initCause` does no longer trigger an internal error (#933). +* Lazy actors are started when calling `close` in order to cleanup their resources (#939). +* Minor bugs in reactive integrations are fixed (#1008). +* Experimental scheduler shutdown sequence is fixed (#990). + ## Version 1.1.1 * Maintenance release, no changes in the codebase diff --git a/README.md b/README.md index d4b6617362..e454e09340 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.1.1) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.1.1) +[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.coroutines/images/download.svg?version=1.2.0-alpha) ](https://bintray.com/kotlin/kotlinx/kotlinx.coroutines/1.2.0-alpha) Library support for Kotlin coroutines with [multiplatform](#multiplatform) support. This is a companion version for Kotlin `1.3.21` release. @@ -75,7 +75,7 @@ Add dependencies (you can also add other modules that you need): org.jetbrains.kotlinx kotlinx-coroutines-core - 1.1.1 + 1.2.0-alpha ``` @@ -93,7 +93,7 @@ Add dependencies (you can also add other modules that you need): ```groovy dependencies { - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.0-alpha' } ``` @@ -119,7 +119,7 @@ Add dependencies (you can also add other modules that you need): ```groovy dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.0-alpha") } ``` @@ -147,7 +147,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.1.1' +implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.0-alpha' ``` This gives you access to Android [Dispatchers.Main](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-android/kotlinx.coroutines.android/kotlinx.coroutines.-dispatchers/index.html) coroutine dispatcher and also makes sure that in case of crashed coroutine with unhandled exception this diff --git a/bump-version.sh b/bump-version.sh index ab1649759e..00930cbd49 100755 --- a/bump-version.sh +++ b/bump-version.sh @@ -16,11 +16,10 @@ update_version() { } update_version "README.md" -update_version "core/kotlinx-coroutines-debug/README.md" -update_version "core/kotlinx-coroutines-test/README.md" +update_version "kotlinx-coroutines-core/README.md" +update_version "kotlinx-coroutines-debug/README.md" +update_version "kotlinx-coroutines-test/README.md" update_version "ui/coroutines-guide-ui.md" -update_version "ui/coroutines-guide-ui.md" -update_version "native/README.md" update_version "ui/kotlinx-coroutines-android/example-app/gradle.properties" update_version "ui/kotlinx-coroutines-android/animation-app/gradle.properties" update_version "gradle.properties" diff --git a/gradle.properties b/gradle.properties index 33b6e97936..69198219fe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Kotlin -version=1.1.1-SNAPSHOT +version=1.2.0-alpha-SNAPSHOT group=org.jetbrains.kotlinx kotlin_version=1.3.21 diff --git a/kotlinx-coroutines-debug/README.md b/kotlinx-coroutines-debug/README.md index 25fc745649..b8475f19f4 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.1.1' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.2.0-alpha' } ``` @@ -57,7 +57,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.1.1.jar`. +You can run your application with an additional argument: `-javaagent:kotlinx-coroutines-debug-1.2.0-alpha.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 a461bf4bea..8259e891ef 100644 --- a/kotlinx-coroutines-test/README.md +++ b/kotlinx-coroutines-test/README.md @@ -7,7 +7,7 @@ Test utilities for `kotlinx.coroutines`. Provides `Dispatchers.setMain` to overr Add `kotlinx-coroutines-test` to your project test dependencies: ``` dependencies { - testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.1.1' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.0-alpha' } ``` diff --git a/ui/coroutines-guide-ui.md b/ui/coroutines-guide-ui.md index 223af58a49..296ccc8779 100644 --- a/ui/coroutines-guide-ui.md +++ b/ui/coroutines-guide-ui.md @@ -165,7 +165,7 @@ Add dependencies on `kotlinx-coroutines-android` module to the `dependencies { . `app/build.gradle` file: ```groovy -implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1" +implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.0-alpha" ``` 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 da95499227..320e02744f 100644 --- a/ui/kotlinx-coroutines-android/animation-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/animation-app/gradle.properties @@ -19,5 +19,5 @@ org.gradle.jvmargs=-Xmx1536m kotlin.coroutines=enable kotlin_version=1.3.21 -coroutines_version=1.1.1 +coroutines_version=1.2.0-alpha diff --git a/ui/kotlinx-coroutines-android/example-app/gradle.properties b/ui/kotlinx-coroutines-android/example-app/gradle.properties index da95499227..320e02744f 100644 --- a/ui/kotlinx-coroutines-android/example-app/gradle.properties +++ b/ui/kotlinx-coroutines-android/example-app/gradle.properties @@ -19,5 +19,5 @@ org.gradle.jvmargs=-Xmx1536m kotlin.coroutines=enable kotlin_version=1.3.21 -coroutines_version=1.1.1 +coroutines_version=1.2.0-alpha