Is there any annotation to indicate a function is ...
# coroutines
j
Is there any annotation to indicate a function is blocking? so the caller need to wrap function call in
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
if want to call function from a coroutine?
k
Blocking isnt exactly well defined.
while (true) { }
is also blocking. Blocking in terms of needing to offload to a different thread really just means that something is a slow synchronous API
r
there's an
@Blocking
annotation available in the JetBrains java-annotations library, which at least gives some IntelliJ IDE support (and possibilities for static analysis), maybe that helps
👍 2
j
perfect exactly what I was looking for!
a
If a function blocks the thread, this can have an impact on the correctness of the program, as the main thread-pool is limited, so you can end up with thread-starvation long before available resources are exhausted. This is why it's a good idea to have blocking I/O redirected to its own thread-pool (or to virtual threads after jdk 21). And leaving that decision up to the caller of your API is bad UX, because the correctness of the program shouldn't depend on what thread-pool you initiate a function call.
In other words, most of the time, it's probably better to have that
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
in your implementation, instead of relying on the caller to do it. I'd also add that it should probably be
runInterruptible(<http://Dispatchers.IO|Dispatchers.IO>
.
e
the IDE has an inspection that warns about usages of functions declared to throw
IOException
in a suspending context that isn't wrapped in
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
. it's definitely not perfect (https://youtrack.jetbrains.com/issue/KTIJ-843) but it catches some common Java IO methods
j
IOW @Alexandru Nedelcu Its good UX to convert blocking functions to suspend functions?
f
If you want to make it more compile safe, you can use context receivers.
Copy code
object Blocking

suspend fun <R> runSuspending(block: Blocking.() -> R): R =
    withContext(<http://Dispatchers.IO|Dispatchers.IO>) { Blocking.block() }


context(Blocking)
fun myBlockingFunction() {
    Thread.sleep(1000)
}

context(Blocking)
fun myOtherFunction() {
    myBlockingFunction()
}

suspend fun main() {

    // Doesn't compile
    myOtherFunction()

    runSuspending {
        myOtherFunction()
    }

}
👍 1
a
@Jacob in the context of Kotlin, yes, because as it is, blocking functions on top of the JVM are slightly error-prone. This will change somewhat with virtual threads, but basically you have to worry about: 1. what threads you're blocking (can you afford to block those threads?); 2. interruption. Kotlin's suspended functions can take care of it, with a little care.
(just in a Kotlin context ofc, if you're exposing a Java API, that's a different thing entirely)