aboutsummaryrefslogtreecommitdiff
path: root/kotlinx-coroutines-core
diff options
context:
space:
mode:
authorRoman Elizarov <elizarov@gmail.com>2019-08-22 15:20:38 +0300
committerVsevolod Tolstopyatov <qwwdfsad@gmail.com>2019-08-22 15:20:38 +0300
commitbcf4a8cba083e5650b1c63a05da481f1b61c3e75 (patch)
tree6469761f98fa7bc75afc683b67e78cf819f1279e /kotlinx-coroutines-core
parent9b7c03c123181c7f027bf002a1ecc8ec1d9205b9 (diff)
downloadkotlinx.coroutines-bcf4a8cba083e5650b1c63a05da481f1b61c3e75.tar.gz
Introduce CoroutineDispatcher.asExecutor() extension (#1457)
Fixes #1450
Diffstat (limited to 'kotlinx-coroutines-core')
-rw-r--r--kotlinx-coroutines-core/jvm/src/Executors.kt20
-rw-r--r--kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt45
2 files changed, 57 insertions, 8 deletions
diff --git a/kotlinx-coroutines-core/jvm/src/Executors.kt b/kotlinx-coroutines-core/jvm/src/Executors.kt
index c5ce5372..7d7f4ba7 100644
--- a/kotlinx-coroutines-core/jvm/src/Executors.kt
+++ b/kotlinx-coroutines-core/jvm/src/Executors.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines
@@ -35,15 +35,27 @@ public abstract class ExecutorCoroutineDispatcher: CoroutineDispatcher(), Closea
*/
@JvmName("from") // this is for a nice Java API, see issue #255
public fun ExecutorService.asCoroutineDispatcher(): ExecutorCoroutineDispatcher =
- // we know that an implementation of Executor.asCoroutineDispatcher actually returns a closeable one
- (this as Executor).asCoroutineDispatcher() as ExecutorCoroutineDispatcher
+ ExecutorCoroutineDispatcherImpl(this)
/**
* Converts an instance of [Executor] to an implementation of [CoroutineDispatcher].
*/
@JvmName("from") // this is for a nice Java API, see issue #255
public fun Executor.asCoroutineDispatcher(): CoroutineDispatcher =
- ExecutorCoroutineDispatcherImpl(this)
+ (this as? DispatcherExecutor)?.dispatcher ?: ExecutorCoroutineDispatcherImpl(this)
+
+/**
+ * Converts an instance of [CoroutineDispatcher] to an implementation of [Executor].
+ *
+ * It returns the original executor when used on the result of [Executor.asCoroutineDispatcher] extensions.
+ */
+public fun CoroutineDispatcher.asExecutor(): Executor =
+ (this as? ExecutorCoroutineDispatcher)?.executor ?: DispatcherExecutor(this)
+
+private class DispatcherExecutor(@JvmField val dispatcher: CoroutineDispatcher) : Executor {
+ override fun execute(block: Runnable) = dispatcher.dispatch(EmptyCoroutineContext, block)
+ override fun toString(): String = dispatcher.toString()
+}
private class ExecutorCoroutineDispatcherImpl(override val executor: Executor) : ExecutorCoroutineDispatcherBase() {
init {
diff --git a/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
index a959b4eb..2cf43618 100644
--- a/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
@@ -1,11 +1,13 @@
/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines
-import org.junit.Test
-import java.util.concurrent.Executors
+import org.junit.*
+import org.junit.Assert.*
+import java.util.concurrent.*
+import kotlin.coroutines.*
class ExecutorsTest : TestBase() {
private fun checkThreadName(prefix: String) {
@@ -32,7 +34,7 @@ class ExecutorsTest : TestBase() {
}
@Test
- fun testToExecutor() {
+ fun testExecutorToDispatcher() {
val executor = Executors.newSingleThreadExecutor { r -> Thread(r, "TestExecutor") }
runBlocking(executor.asCoroutineDispatcher()) {
checkThreadName("TestExecutor")
@@ -41,6 +43,41 @@ class ExecutorsTest : TestBase() {
}
@Test
+ fun testConvertedDispatcherToExecutor() {
+ val executor: ExecutorService = Executors.newSingleThreadExecutor { r -> Thread(r, "TestExecutor") }
+ val dispatcher: CoroutineDispatcher = executor.asCoroutineDispatcher()
+ assertSame(executor, dispatcher.asExecutor())
+ executor.shutdown()
+ }
+
+ @Test
+ fun testDefaultDispatcherToExecutor() {
+ val latch = CountDownLatch(1)
+ Dispatchers.Default.asExecutor().execute {
+ checkThreadName("DefaultDispatcher")
+ latch.countDown()
+ }
+ latch.await()
+ }
+
+ @Test
+ fun testCustomDispatcherToExecutor() {
+ expect(1)
+ val dispatcher = object : CoroutineDispatcher() {
+ override fun dispatch(context: CoroutineContext, block: Runnable) {
+ expect(2)
+ block.run()
+ }
+ }
+ val executor = dispatcher.asExecutor()
+ assertSame(dispatcher, executor.asCoroutineDispatcher())
+ executor.execute {
+ expect(3)
+ }
+ finish(4)
+ }
+
+ @Test
fun testTwoThreads() {
val ctx1 = newSingleThreadContext("Ctx1")
val ctx2 = newSingleThreadContext("Ctx2")