Joffrey
05/19/2022, 12:44 PMsuspend fun main
is considered inactive?
suspend fun main() {
println(currentCoroutineContext().isActive) // prints false
}
https://pl.kotl.in/sVFnLz9mMephemient
05/19/2022, 1:04 PMsuspend fun main
uses a super simple dispatcher instead of depending on kotlinx.coroutines. since it doesn't have a Job
, it's !isActive
. https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/jvm/src/kotlin/coroutines/jvm/internal/RunSuspend.ktsuspend fun main() = coroutineScpoe {
println(isActive)
}
produces true
because it goes into the kotlinx.coroutines world, but without that, it doesn'tJoffrey
05/19/2022, 1:12 PMcoroutineContext.isActive
was from kotlinx.coroutines
, unlike coroutineContext
.
Yeah I understand the other options of using coroutineScope
or removing suspend
and using runBlocking
.
That said, it makes using suspend fun main
pretty awkward if you use things that are aware of structured concurrency without wrapping them in coroutines first. I wonder if production code should use it at all, now.ephemient
05/19/2022, 1:14 PMJoffrey
05/19/2022, 1:16 PMsuspend fun
from a library that relies on while(coroutineContext.isActive)
. I didn't need to launch a coroutine to call that function from suspend fun main
.suspend fun
directly from suspend fun main
without coroutine, or the fact that the lib function was using while(isActive)
š¤ephemient
05/19/2022, 1:19 PMwhile (currentCoroutineContext().isActive)
seems like a bug to begin with. it'll fail in anything else that uses (non-kotlinx.)coroutines too, e.g. sequence()
buildersJoffrey
05/19/2022, 1:22 PMsequence
builders have restricted suspend
access via special annotations, though, exactly to avoid this kind of problemsephemient
05/19/2022, 1:25 PMJoffrey
05/19/2022, 1:32 PMwhile(isActive)
in the function in question is just superstition I believe, because the loop contains suspending calls anyway so it shouldn't be necessary. And even if that were not the case, we could also introduce yield()
calls in the loop and it would have the same effect of detecting cancellation. Still begs the question, should while(isActive)
be considered an anti-pattern in general?ephemient
05/19/2022, 1:35 PMwhile (isActive)
could be useful if you're looping around non-suspending code, but it should be known to come from a CoroutineScope
- from a function local coroutineScope {}
if it's not given an external scope. a CoroutineContext
is usually not something you'd be touchingyield()
to suspend) then it's probably not useful to use isActive
, I thinkJoffrey
05/19/2022, 1:41 PMisActive
is defined on the coroutineContext
itself, even though it doesn't have any meaning when there is no Job
in the context. I think defining it at this level anyway with the value false
is just a footgun.coroutineScope
would work, it is painfully not obvious why it would be there if no coroutines are launched in it. The connection between the presence of coroutineScope
and the usage of coroutineContext.isActive
is not shown by the compiler, and I think seeing such code I would be the first person to carelessly remove the "useless" coroutineScope
wrapperephemient
05/19/2022, 1:43 PMCoroutineScope
, but I agree the one on CoroutineContext
is a likely footgunJoffrey
05/19/2022, 1:43 PMCoroutineScope
would solve the problem I was mentioningephemient
05/19/2022, 1:44 PMcoroutineScope
from coroutineScope { while (isActive) { ... } }
will break compilation