Tianyu Zhu
05/26/2022, 12:39 AMfun justSomeFunction() {
launchACoroutine(<http://Dispatchers.IO|Dispatchers.IO>) {
while (true) {
// just do some work
}
}
}
Nick Allen
05/26/2022, 12:50 AMjustSomeFunction
to block until the work is done? Is justSomeFunction
called as part of some larger process that will want to know when the work finishes, or that may be cancelled and so this work should be cancelled too?Tianyu Zhu
05/26/2022, 12:54 AMjustSomeFunction
to return as soon as the coroutine is launched. Fire and forget.Nick Allen
05/26/2022, 1:08 AMBreaker ACT
05/26/2022, 7:43 AMgildor
05/26/2022, 12:18 PMFrancesc
05/26/2022, 5:50 PMJoffrey
05/26/2022, 10:41 PMGlobalScope
, but then you're outside structured concurrency so you need to return the Job
from your function (the one that launch
returned to you) so you can cancel the coroutine manually when necessarygildor
05/27/2022, 1:44 AMDALDEI
06/04/2022, 11:06 AMJoffrey
06/04/2022, 11:07 AMGlobalScope
by mistake?gildor
06/04/2022, 1:10 PMgildor
06/04/2022, 1:12 PMJoffrey
06/04/2022, 2:04 PMgildor
06/06/2022, 1:55 AMJoffrey
06/06/2022, 9:09 AMcancel()
will not really help you much here. If you have classes that accept an external CoroutineScope
, and that make the mistake of cancelling it, why would they not make the mistake of using the CoroutineScope
interface instead of the new non cancellable interface? The same problematic code could persist on the consumer side. The problem is not accidental cancellation IMO, the intention of cancelling an external scope is a mistake in itself, not an unintended side effect of something elseJoffrey
06/06/2022, 9:12 AMSometimes you want to cancel all tasks
In that case you use structured concurrency, and cancel the scope that you created yourself for this very purpose, not an externally provided scope.
GlobalScope
is giving up on structured concurrency, and has an opt-in requirement to make sure you understand this before using it. So I don't see GlobalScope.cancel()
ever happening directly either (but that wouldn't be accidental anyway)gildor
06/06/2022, 3:07 PMgildor
06/06/2022, 3:09 PMgildor
06/06/2022, 3:10 PMNick Allen
06/06/2022, 5:01 PMclass ChildCoroutineScope(private val parent: CoroutineScope): CoroutineScope by parent + Job(parent.coroutineContext[Job])
(untested just typed it out)
FYI, I've run into issues mixing up scopes when I have more than one, a scope
parameter and a this
launched scope and can easily see someone cancelling the wrong one.Joffrey
06/06/2022, 7:41 PMGlobalScope
".
1. I don't believe anyone ever tries to call GlobalScope.cancel()
directly at all. If that happens, it's not an accident (as in an unintended consequence of a correct intention), it's a mistake (the intention itself was wrong).
2. The only way that cancelling the GlobalScope
could happen potentially by accident would be if some code receives a scope from elsewhere as CoroutineScope
, and tries to cancel it. That's also IMO just an incorrect intention in the first place (with any scope, not just when GlobalScope
is passed). So, yes, that could lead to accidental cancellation of the GlobalScope
, but it's first and foremost a bigger mistake about cancelling externally-provided scopes.
Why wouldn't it help?@gildor I thought what you were suggesting is just a new interface (a super interface of
CoroutineScope
) that wouldn't have a cancel()
method. If the problematic code asks for a CoroutineScope
and chooses to cancel it, the fact that another interface is available doesn't prevent this from happening (they could still decide to ask for a CoroutineScope
instead of the new interface).
But what I agree that if GlobalScope
didn't implement CoroutineScope
anymore, then it could not be passed to those incorrect pieces of code. I am not sure GlobalScope
could be changed this way. I also believe it would not be worth the breaking change given that it prevents an arguably small accident from code that has bigger problems anyway.
FYI, I've run into issues mixing up scopes when I have more than one, a@Nick Allen That's fair, although I have trouble imagining a situation where one needs to cancel "this" scopes from locally launched coroutines. So I'd argue neither should be cancelled? Maybe it's just wishful thinking, and valid situations like this do arise.parameter and ascope
launched scope and can easily see someone cancelling the wrong one.this
gildor
06/07/2022, 2:06 AMIf the problematic code asks for aIt’s correct, but it will be one more level of protection. Also on DI environment it’s very easy, you can do not add cancellable version of top level contextand chooses to cancel it,CoroutineScope
worth the breaking change given that it prevents an arguably small accident from codeYou can say exactly the same about List vs MutableList I believe there are valid ways to migrate in 2-3 versions, no need to break existing code
gildor
06/07/2022, 2:12 AMYou could leverage the type system with something like:Yes, this what we are doing, we even have helper builder for this (probably worth to request adding it to kotlinx.coroutines) Want to clarify, I understand how to work with it, I just also have experience in very big project fully based on coroutines on which multiple developers work, and no,
The only way that cancelling theBut GlobalScope will not be cancelled! It doesn’t have job, nothing to cancel. You cannot cancel it in any way, all jobs started from it have Job without parent. My original comment was about David’s message, that they use custom scope with SupervisorJob, which is indeed one of ways to handle it (and we use this approach too, for example we have UserScope, which started on login and cancelled on logout), my concern is that this approach, although we use it, is error prone in a very nasty way, when scope can be accidentally cancelled by any code, so it’s better to at least always provide new child scope, so it will prevent code which injected it, to cancel all the jobscould happen potentially by accidentGlobalScope
DALDEI
06/07/2022, 3:30 AM