Skip to content

Commit

Permalink
Introduce first version of Dispatchers.IO for K/N
Browse files Browse the repository at this point in the history
* Emulate expect declaration refinement via extension property as the only way to do it in a backwards-compatible manner: in the current model it is impossible to have
  common 'expect' Dispatchers declaration, then refined 'concurrent' Dispatchers declaration with 'expect val IO' and then JVM declaration with JVM-specific members. Current solutions seems to be the less intrusive one
* Elasticity is not supported as K/N Workers API lacks capability to gracefully shutdown workers, meaning that for any unlimited underlying pool, memory consumption is only going to grow in an unbound manner

Fixes #3205
  • Loading branch information
qwwdfsad committed Jan 4, 2023
1 parent 0eb94dd commit ac91fe2
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 4 deletions.
1 change: 1 addition & 0 deletions kotlinx-coroutines-core/api/kotlinx-coroutines-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ public final class kotlinx/coroutines/Dispatchers {

public final class kotlinx/coroutines/DispatchersKt {
public static final field IO_PARALLELISM_PROPERTY_NAME Ljava/lang/String;
public static final synthetic fun getIO (Lkotlinx/coroutines/Dispatchers;)Lkotlinx/coroutines/CoroutineDispatcher;
}

public abstract interface class kotlinx/coroutines/DisposableHandle {
Expand Down
2 changes: 1 addition & 1 deletion kotlinx-coroutines-core/common/src/Dispatchers.common.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import kotlin.coroutines.*
public expect object Dispatchers {
/**
* The default [CoroutineDispatcher] that is used by all standard builders like
* [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc
* [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc.
* if neither a dispatcher nor any other [ContinuationInterceptor] is specified in their context.
*
* It is backed by a shared pool of threads on JVM. By default, the maximum number of threads used
Expand Down
18 changes: 18 additions & 0 deletions kotlinx-coroutines-core/concurrent/src/Dispatchers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

package kotlinx.coroutines

/**
* The [CoroutineDispatcher] that is designed for offloading blocking IO tasks to a shared pool of threads.
* Additional threads in this pool are created on demand.
*
* By default, the pool is backed by `64` standalone threads, for the additional details
* such as elasticity, dynamic sizing and interaction with [CoroutineDispatcher.limitedParallelism],
* please refer to the documentation of `Dispatchers.IO` on specific platform.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public expect val Dispatchers.IO: CoroutineDispatcher


Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ package kotlinx.coroutines
class DefaultDispatcherConcurrencyTest : AbstractDispatcherConcurrencyTest() {
override val dispatcher: CoroutineDispatcher = Dispatchers.Default
}

class IoDispatcherConcurrencyTest : AbstractDispatcherConcurrencyTest() {
override val dispatcher: CoroutineDispatcher = Dispatchers.IO
}
14 changes: 11 additions & 3 deletions kotlinx-coroutines-core/jvm/src/Dispatchers.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

@file:Suppress("unused")

package kotlinx.coroutines

import kotlinx.coroutines.internal.*
Expand Down Expand Up @@ -161,3 +159,13 @@ public actual object Dispatchers {
DefaultScheduler.shutdown()
}
}

/**
* `actual` counterpart of the corresponding `expect` declaration.
* Should never be used directly from JVM sources, all accesses
* to `Dispatchers.IO` should be resolved to the corresponding member of [Dispatchers] object.
* @suppress
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
@Deprecated(message = "Should not be used directly", level = DeprecationLevel.HIDDEN)
public actual val Dispatchers.IO: CoroutineDispatcher get() = Dispatchers.IO
13 changes: 13 additions & 0 deletions kotlinx-coroutines-core/native/src/Dispatchers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ public actual object Dispatchers {
internal fun injectMain(dispatcher: MainCoroutineDispatcher) {
injectedMainDispatcher = dispatcher
}

internal val IO: CoroutineDispatcher = newFixedThreadPoolContext(64, "Dispatchers.IO")
}

/**
* The [CoroutineDispatcher] that is designed for offloading blocking IO tasks to a shared pool of threads.
* Additional threads in this pool are created on demand.
*
* On Native platforms it is backed by a standalone [newFixedThreadPoolContext] with `64` worker threads in it.
* **NB**: this dispatcher **does not** share the same elasticity behaviour for [CoroutineDispatcher.limitedParallelism]
* as `Dispatchers.IO` on JVM.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public actual val Dispatchers.IO: CoroutineDispatcher get() = IO

internal expect fun createMainDispatcher(default: CoroutineDispatcher): MainCoroutineDispatcher

0 comments on commit ac91fe2

Please sign in to comment.