groostav
08/08/2019, 9:36 PMJob
and parent-child'ing.
suspend fun doLongRunningWork {
val myContext = coroutineContext
requireNotNull(myContext[Job])
val async1 = someScope.async {
//...
}
val async2 = someScope.async(myContext) {
//...
}
//maybe this code joins on async1 & async2, maybe not. should that impact my approach?
}
the latter exerts a rather strange back-pressure on the callers coroutine-entrypoint. Why the distinction?zak.taccardi
08/08/2019, 9:37 PMzak.taccardi
08/08/2019, 9:37 PMzak.taccardi
08/08/2019, 9:37 PMsuspend fun doLongRunningWork()
will complete (resume) potentially before the two async coroutines completezak.taccardi
08/08/2019, 9:38 PMawaitAll(async1, async2)
to suspend doLongRunningWork()
until they completegroostav
08/08/2019, 9:38 PMmyContext
groostav
08/08/2019, 9:39 PMgroostav
08/08/2019, 9:39 PMcoroutineScope {}
builder...groostav
08/08/2019, 9:43 PMrunBlocking
from completing... although, does async
complete in such a case? does await
give you a value but join()
suspend?
I must write tests.groostav
08/08/2019, 9:52 PMCompleting
state.zak.taccardi
08/08/2019, 9:53 PMzak.taccardi
08/08/2019, 9:53 PMzak.taccardi
08/08/2019, 9:54 PMzak.taccardi
08/08/2019, 9:54 PMgroostav
08/08/2019, 9:56 PMasync1
is not a child of the Job executing doLongRunningWork
and async2
is a child of same. Why do we need to distinguish between the two?groostav
08/08/2019, 9:57 PMdoLongRunningWork
complete when its own block is complete. The latter will prevent the Job
of doLongRunningWork
from completing, pushing it into the Completing
state, for as long as async2
is running.zak.taccardi
08/08/2019, 9:58 PMgildor
08/09/2019, 2:47 AMgildor
08/09/2019, 2:49 AMgroostav
08/09/2019, 4:46 AMyou [never should] launch coroutines to different scope from suspending functionin short, what im asking is: why? Consider your the designer of "TornadoUI" UI framework. Lets say you use an annotation processing system and you want to support coroutines. Should you idiomatically ask callers to write functions like
@Tornado suspend fun onClick(e: ActionEvent)
or should you ask them to write
@Tornado fun CoroutineScope.onClick(e: ActionEvent)
--or something else?
If you do decide that "simplicity is most important", and so you want your users to write regular UI event handlers @Tornado suspend fun handle(e: Event)
, what should you do if they call launch(coroutineContext) { delay(9999)
. Do you refuse to dispatch further events to that handler? Should you throw an exception?groostav
08/09/2019, 4:49 AMlouiscad
08/09/2019, 6:00 AMsuspend fun doLongRunningWork = coroutineScope {
val async1 = async {
//...
}
val async2 = async {
//...
}
... // Probably await the async values, otherwise, use launch.
} // This code definitely joins async1 & async2 if you don't await them
groostav
08/09/2019, 6:32 PMgildor
08/10/2019, 1:01 AMgildor
08/10/2019, 1:06 AMwhat should you do if they callThis is indifferent to launch and scopes, user can just call delay(9999) And now, you shouldn't throw exception I don't see any problem in this case if you use proper event stream abstraction like Flow, which has different strategies for backpressure. With suspend function you always have only 2 choices: suspend until client is processing or launch new coroutine and suspend, as you mentioned above, with Flow you can also buffer and conflatelaunch(coroutineContext) { delay(9999)
louiscad
08/11/2019, 2:12 PM@Tornado
annotation means and does?groostav
08/11/2019, 11:24 PMoperator fun EntryPointAPI.plusAssign(handler: your_concurrent_handler_type)
if you wanted a winforms style ui API. The thing I’m trying to get at is: what should the lambda type be? And what should the UI framework do if it returns but silently appended a child job to the context you gave it?louiscad
08/11/2019, 11:37 PM