Skip to content

Commit 64d38cd

Browse files
deva666Anton Spaans
authored and
Anton Spaans
committed
Add extension to ExecutorService to return closeable CoroutineDispatcher
Fixes Kotlin#278
1 parent bb53003 commit 64d38cd

File tree

2 files changed

+30
-1
lines changed
  • core/kotlinx-coroutines-core/src

2 files changed

+30
-1
lines changed

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Executors.kt

+19-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,26 @@
1616

1717
package kotlinx.coroutines.experimental
1818

19+
import java.io.Closeable
1920
import java.util.concurrent.Executor
21+
import java.util.concurrent.ExecutorService
2022
import java.util.concurrent.RejectedExecutionException
2123
import java.util.concurrent.ScheduledExecutorService
2224
import java.util.concurrent.TimeUnit
2325
import kotlin.coroutines.experimental.CoroutineContext
2426

27+
/**
28+
* [CoroutineDispatcher] that implements [Closeable]
29+
*/
30+
abstract class CloseableCoroutineDispatcher: CoroutineDispatcher(), Closeable
31+
32+
/**
33+
* Converts an instance of [ExecutorService] to an implementation of [CloseableCoroutineDispatcher].
34+
*/
35+
public fun ExecutorService.asCoroutineDispatcher(): CloseableCoroutineDispatcher =
36+
// we know that an implementation of Executor.asCoroutineDispatcher actually returns a closeable one
37+
(this as Executor).asCoroutineDispatcher() as CloseableCoroutineDispatcher
38+
2539
/**
2640
* Converts an instance of [Executor] to an implementation of [CoroutineDispatcher].
2741
* @suppress **Deprecated**: Renamed to [asCoroutineDispatcher].
@@ -42,7 +56,7 @@ private class ExecutorCoroutineDispatcher(override val executor: Executor) : Exe
4256
/**
4357
* @suppress **This is unstable API and it is subject to change.**
4458
*/
45-
public abstract class ExecutorCoroutineDispatcherBase : CoroutineDispatcher(), Delay {
59+
public abstract class ExecutorCoroutineDispatcherBase : CloseableCoroutineDispatcher(), Delay {
4660
/**
4761
* @suppress **This is unstable API and it is subject to change.**
4862
*/
@@ -77,6 +91,10 @@ public abstract class ExecutorCoroutineDispatcherBase : CoroutineDispatcher(), D
7791
return DefaultExecutor.invokeOnTimeout(time, unit, block)
7892
}
7993

94+
override fun close() {
95+
(executor as? ExecutorService)?.shutdown()
96+
}
97+
8098
override fun toString(): String = executor.toString()
8199
override fun equals(other: Any?): Boolean = other is ExecutorCoroutineDispatcherBase && other.executor === executor
82100
override fun hashCode(): Int = System.identityHashCode(executor)

core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/ExecutorsTest.kt

+11
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,15 @@ class ExecutorsTest : TestBase() {
6666
ctx1.close()
6767
ctx2.close()
6868
}
69+
70+
@Test
71+
fun testShutdownExecutorService() {
72+
val executorService = Executors.newSingleThreadExecutor { r -> Thread(r, "TestExecutor") }
73+
val dispatcher = executorService.asCoroutineDispatcher()
74+
runBlocking (dispatcher) {
75+
checkThreadName("TestExecutor")
76+
}
77+
dispatcher.close()
78+
check(executorService.isShutdown)
79+
}
6980
}

0 commit comments

Comments
 (0)