diff options
author | Roman Elizarov <elizarov@gmail.com> | 2019-08-22 15:20:38 +0300 |
---|---|---|
committer | Vsevolod Tolstopyatov <qwwdfsad@gmail.com> | 2019-08-22 15:20:38 +0300 |
commit | bcf4a8cba083e5650b1c63a05da481f1b61c3e75 (patch) | |
tree | 6469761f98fa7bc75afc683b67e78cf819f1279e /kotlinx-coroutines-core | |
parent | 9b7c03c123181c7f027bf002a1ecc8ec1d9205b9 (diff) | |
download | kotlinx.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.kt | 20 | ||||
-rw-r--r-- | kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt | 45 |
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") |