https://kotlinlang.org logo
Title
m

melatonina

03/15/2021, 4:13 PM
Is this a good way to create a dispatcher which runs coroutines on a high priority thread?
import java.util.concurrent.Executors

import kotlinx.coroutines.asCoroutineDispatcher
import kotlin.concurrent.thread

fun highPriorityContext() = Executors.newSingleThreadExecutor { runnable ->
    thread(priority = Thread.MAX_PRIORITY) { runnable.run() }
}.asCoroutineDispatcher()
e

elizarov

03/16/2021, 6:31 AM
Yes. It is as good as it gets.
m

melatonina

03/16/2021, 9:57 PM
Thanks, @elizarov. Unfortunately, when I
launch
a coroutine in a CoroutineScope with that context, I get this exception:
java.lang.IllegalThreadStateException
        at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:964)
        at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1382)
        at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:630)
        at kotlinx.coroutines.ExecutorCoroutineDispatcherBase.dispatch(Executors.kt:94)
        at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:305)
        at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.startCoroutineImpl(Builders.common.kt:192)
        at kotlinx.coroutines.BuildersKt.startCoroutineImpl(Unknown Source:1)
        at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:145)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
        at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:49)
        at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
If I replace that context with
newFixedThreadPoolContext(1)
I don't get the exception. Do you understand what is happening from the stack trace?
b

baxter

03/17/2021, 5:48 AM
The
thread()
function starts threads immediately, unless you pass
start = false
to it. Executors don't want threads that have already started.
💯 1
m

melatonina

03/17/2021, 10:13 AM
Thanks, @baxter! That was the problem, indeed.
I'm using this dispatcher to run an audio playback system loop which synthesizes some audio material and the blocks on the
write
call to a output device. After the the blocking
write
call, I execute:
if (!isActive) {
    yield()
}
In order to allow cooperative cancellation. When I want shutdown this playback system, I just cancel the corresponding job, and, If I run on
<http://Dispatchers.IO|Dispatchers.IO>
, this works. It also works with
newFixedThreadPoolContext(1)
. If I use the high-priority dispatcher, it doesn't. Do you know why this is happening?