Skip to content

Commit 1d48a7c

Browse files
committed
Allow to shutdown executor from withing worker thread
Fixed #612
1 parent 118ee99 commit 1d48a7c

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ internal class CoroutineScheduler(
300300
fun shutdown(timeout: Long) {
301301
// atomically set termination flag which is checked when workers are added or removed
302302
if (!isTerminated.compareAndSet(false, true)) return
303+
304+
/*
305+
* Shutdown current thread. Note that shutdown is testing utility,
306+
* so we don't do anything special to properly verify that no tasks are submitted after close()
307+
*/
308+
val thread = Thread.currentThread()
309+
(thread as? Worker)?.tryReleaseCpu(WorkerState.TERMINATED)
310+
303311
// Capture # of created workers that cannot change anymore (mind the synchronized block!)
304312
val created = synchronized(workers) { createdWorkers }
305313
for (i in 1..created) {
@@ -653,7 +661,7 @@ internal class CoroutineScheduler(
653661
* Releases CPU token if worker has any and changes state to [newState]
654662
* @return whether worker had CPU token
655663
*/
656-
private fun tryReleaseCpu(newState: WorkerState): Boolean {
664+
internal fun tryReleaseCpu(newState: WorkerState): Boolean {
657665
val previousState = state
658666
val hadCpu = previousState == WorkerState.CPU_ACQUIRED
659667
if (hadCpu) cpuPermits.release()

core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt

+14-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
package kotlinx.coroutines.experimental.scheduling
66

77
import kotlinx.coroutines.experimental.TestBase
8-
import org.junit.Test
9-
import java.util.concurrent.CountDownLatch
8+
import org.junit.*
9+
import java.lang.Runnable
10+
import java.util.concurrent.*
11+
import kotlin.coroutines.experimental.*
1012

1113
class CoroutineSchedulerTest : TestBase() {
1214

@@ -115,6 +117,16 @@ class CoroutineSchedulerTest : TestBase() {
115117
ExperimentalCoroutineDispatcher(4, 1)
116118
}
117119

120+
@Test
121+
fun testSelfClose() {
122+
val dispatcher = ExperimentalCoroutineDispatcher(1, 1)
123+
val latch = CountDownLatch(1)
124+
dispatcher.dispatch(EmptyCoroutineContext, Runnable {
125+
dispatcher.close(); latch.countDown()
126+
})
127+
latch.await()
128+
}
129+
118130
private fun testUniformDistribution(worker: CoroutineScheduler.Worker, bound: Int) {
119131
val result = IntArray(bound)
120132
val iterations = 10_000_000

0 commit comments

Comments
 (0)