From 29d08e4518e1b7bdbb2b51a5c5a3226e36f9654b Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 16 Jun 2020 21:29:52 +0300 Subject: [PATCH 1/3] Recognizable toString implementation in default dispatchers --- .../common/src/Unconfined.kt | 2 +- .../jvm/src/scheduling/Dispatcher.kt | 18 ++++++++++++------ .../jvm/src/scheduling/Tasks.kt | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/Unconfined.kt b/kotlinx-coroutines-core/common/src/Unconfined.kt index ce03a28765..a0997a51d3 100644 --- a/kotlinx-coroutines-core/common/src/Unconfined.kt +++ b/kotlinx-coroutines-core/common/src/Unconfined.kt @@ -26,7 +26,7 @@ internal object Unconfined : CoroutineDispatcher() { "isDispatchNeeded and dispatch calls.") } - override fun toString(): String = "Unconfined" + override fun toString(): String = "Dispatchers.Unconfined" } /** diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt index 35ebf92d1b..e0903ab0e7 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt @@ -14,7 +14,12 @@ import kotlin.coroutines.* * Default instance of coroutine dispatcher. */ internal object DefaultScheduler : ExperimentalCoroutineDispatcher() { - val IO = blocking(systemProp(IO_PARALLELISM_PROPERTY_NAME, 64.coerceAtLeast(AVAILABLE_PROCESSORS))) + val IO: CoroutineDispatcher = LimitingDispatcher( + this, + systemProp(IO_PARALLELISM_PROPERTY_NAME, 64.coerceAtLeast(AVAILABLE_PROCESSORS)), + "Dispatchers.IO", + TASK_PROBABLY_BLOCKING + ) override fun close() { throw UnsupportedOperationException("$DEFAULT_SCHEDULER_NAME cannot be closed") @@ -85,7 +90,7 @@ public open class ExperimentalCoroutineDispatcher( */ public fun blocking(parallelism: Int = BLOCKING_DEFAULT_PARALLELISM): CoroutineDispatcher { require(parallelism > 0) { "Expected positive parallelism level, but have $parallelism" } - return LimitingDispatcher(this, parallelism, TASK_PROBABLY_BLOCKING) + return LimitingDispatcher(this, parallelism, null, TASK_PROBABLY_BLOCKING) } /** @@ -98,7 +103,7 @@ public open class ExperimentalCoroutineDispatcher( public fun limited(parallelism: Int): CoroutineDispatcher { require(parallelism > 0) { "Expected positive parallelism level, but have $parallelism" } require(parallelism <= corePoolSize) { "Expected parallelism level lesser than core pool size ($corePoolSize), but have $parallelism" } - return LimitingDispatcher(this, parallelism, TASK_NON_BLOCKING) + return LimitingDispatcher(this, parallelism, null, TASK_NON_BLOCKING) } internal fun dispatchWithContext(block: Runnable, context: TaskContext, tailDispatch: Boolean) { @@ -130,8 +135,9 @@ public open class ExperimentalCoroutineDispatcher( } private class LimitingDispatcher( - val dispatcher: ExperimentalCoroutineDispatcher, - val parallelism: Int, + private val dispatcher: ExperimentalCoroutineDispatcher, + private val parallelism: Int, + private val name: String?, override val taskMode: Int ) : ExecutorCoroutineDispatcher(), TaskContext, Executor { @@ -190,7 +196,7 @@ private class LimitingDispatcher( } override fun toString(): String { - return "${super.toString()}[dispatcher = $dispatcher]" + return name ?: "${super.toString()}[dispatcher = $dispatcher]" } /** diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt index 247615d777..9e7219c10e 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt @@ -11,7 +11,7 @@ import java.util.concurrent.* // TODO most of these fields will be moved to 'object ExperimentalDispatcher' -internal const val DEFAULT_SCHEDULER_NAME = "DefaultDispatcher" +internal const val DEFAULT_SCHEDULER_NAME = "Dispatchers.Default" // 100us as default @JvmField From 2ca924f4063d322ea4e07b1652792374e35e45eb Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 16 Jun 2020 21:31:14 +0300 Subject: [PATCH 2/3] Fast-path for disabled debug probes --- .../jvm/src/debug/internal/DebugProbesImpl.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt index 6e8d19fb3f..6ff51f3da5 100644 --- a/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt +++ b/kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt @@ -272,6 +272,7 @@ internal object DebugProbesImpl { internal fun probeCoroutineSuspended(frame: Continuation<*>) = updateState(frame, SUSPENDED) private fun updateState(frame: Continuation<*>, state: String) { + if (!isInstalled) return // KT-29997 is here only since 1.3.30 if (state == RUNNING && KotlinVersion.CURRENT.isAtLeast(1, 3, 30)) { val stackFrame = frame as? CoroutineStackFrame ?: return From 7b457b0cf7b52babffd276119c4bcd79a17556fb Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 17 Jun 2020 12:19:02 +0300 Subject: [PATCH 3/3] Do not change Dispatcher.Default thread names --- docs/flow.md | 2 +- kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt | 4 ++-- kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt | 5 ++++- kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/flow.md b/docs/flow.md index 9b331588c3..f0f570d65a 100644 --- a/docs/flow.md +++ b/docs/flow.md @@ -697,7 +697,7 @@ This code produces the following exception: ```text Exception in thread "main" java.lang.IllegalStateException: Flow invariant is violated: Flow was collected in [CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@5511c7f8, BlockingEventLoop@2eac3323], - but emission happened in [CoroutineId(1), "coroutine#1":DispatchedCoroutine{Active}@2dae0000, DefaultDispatcher]. + but emission happened in [CoroutineId(1), "coroutine#1":DispatchedCoroutine{Active}@2dae0000, Dispatchers.Default]. Please refer to 'flow' documentation or use 'flowOn' instead at ... ``` diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt index e0903ab0e7..e0890eff66 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Dispatcher.kt @@ -22,10 +22,10 @@ internal object DefaultScheduler : ExperimentalCoroutineDispatcher() { ) override fun close() { - throw UnsupportedOperationException("$DEFAULT_SCHEDULER_NAME cannot be closed") + throw UnsupportedOperationException("$DEFAULT_DISPATCHER_NAME cannot be closed") } - override fun toString(): String = DEFAULT_SCHEDULER_NAME + override fun toString(): String = DEFAULT_DISPATCHER_NAME @InternalCoroutinesApi @Suppress("UNUSED") diff --git a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt index 9e7219c10e..a317b9754c 100644 --- a/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt +++ b/kotlinx-coroutines-core/jvm/src/scheduling/Tasks.kt @@ -11,7 +11,10 @@ import java.util.concurrent.* // TODO most of these fields will be moved to 'object ExperimentalDispatcher' -internal const val DEFAULT_SCHEDULER_NAME = "Dispatchers.Default" +// User-visible name +internal const val DEFAULT_DISPATCHER_NAME = "Dispatchers.Default" +// Internal debuggability name + thread name prefixes +internal const val DEFAULT_SCHEDULER_NAME = "DefaultDispatcher" // 100us as default @JvmField diff --git a/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt b/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt index 15c9e1e4c6..1d7f952500 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/test/FlowGuideTest.kt @@ -151,7 +151,7 @@ class FlowGuideTest { test("ExampleFlow14") { kotlinx.coroutines.guide.exampleFlow14.main() }.verifyExceptions( "Exception in thread \"main\" java.lang.IllegalStateException: Flow invariant is violated:", "\t\tFlow was collected in [CoroutineId(1), \"coroutine#1\":BlockingCoroutine{Active}@5511c7f8, BlockingEventLoop@2eac3323],", - "\t\tbut emission happened in [CoroutineId(1), \"coroutine#1\":DispatchedCoroutine{Active}@2dae0000, DefaultDispatcher].", + "\t\tbut emission happened in [CoroutineId(1), \"coroutine#1\":DispatchedCoroutine{Active}@2dae0000, Dispatchers.Default].", "\t\tPlease refer to 'flow' documentation or use 'flowOn' instead", "\tat ..." )