https://kotlinlang.org logo
#coroutines
Title
# coroutines
j

Juan Rada

10/25/2023, 2:00 PM
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

kevin.cianfarini

10/25/2023, 2:02 PM
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

Riccardo Lippolis

10/25/2023, 2:03 PM
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

Juan Rada

10/25/2023, 2:05 PM
perfect exactly what I was looking for!
a

Alexandru Nedelcu

10/25/2023, 2:24 PM
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

ephemient

10/25/2023, 2:31 PM
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

Jacob

10/25/2023, 2:36 PM
IOW @Alexandru Nedelcu Its good UX to convert blocking functions to suspend functions?
f

franztesca

10/25/2023, 2:47 PM
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

Alexandru Nedelcu

10/25/2023, 3:22 PM
@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)