Skip to content

Commit

Permalink
Introduce CoroutineDispatcher.asExecutor() extension
Browse files Browse the repository at this point in the history
Fixes #1450
  • Loading branch information
elizarov committed Aug 21, 2019
1 parent fbaedc4 commit 86c0367
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ public abstract class kotlinx/coroutines/ExecutorCoroutineDispatcher : kotlinx/c
}

public final class kotlinx/coroutines/ExecutorsKt {
public static final fun asExecutor (Lkotlinx/coroutines/CoroutineDispatcher;)Ljava/util/concurrent/Executor;
public static final fun from (Ljava/util/concurrent/Executor;)Lkotlinx/coroutines/CoroutineDispatcher;
public static final fun from (Ljava/util/concurrent/ExecutorService;)Lkotlinx/coroutines/ExecutorCoroutineDispatcher;
}
Expand Down
15 changes: 14 additions & 1 deletion kotlinx-coroutines-core/jvm/src/Executors.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -45,6 +45,19 @@ public fun ExecutorService.asCoroutineDispatcher(): ExecutorCoroutineDispatcher
public fun Executor.asCoroutineDispatcher(): CoroutineDispatcher =
ExecutorCoroutineDispatcherImpl(this)

/**
* Converts an instance of [CoroutineDispatcher] to an implementation of [Executor].
*
* It returns an 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(private 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 {
initFutureCancellation()
Expand Down
27 changes: 23 additions & 4 deletions kotlinx-coroutines-core/jvm/test/ExecutorsTest.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/*
* 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.*

class ExecutorsTest : TestBase() {
private fun checkThreadName(prefix: String) {
Expand All @@ -32,14 +33,32 @@ class ExecutorsTest : TestBase() {
}

@Test
fun testToExecutor() {
fun testExecutorToDispatcher() {
val executor = Executors.newSingleThreadExecutor { r -> Thread(r, "TestExecutor") }
runBlocking(executor.asCoroutineDispatcher()) {
checkThreadName("TestExecutor")
}
executor.shutdown()
}

@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(2)
Dispatchers.Default.asExecutor().execute {
checkThreadName("DefaultDispatcher")
latch.countDown()
}
latch.countDown()
}

@Test
fun testTwoThreads() {
val ctx1 = newSingleThreadContext("Ctx1")
Expand Down

0 comments on commit 86c0367

Please sign in to comment.