Manuel Pérez Alcolea
10/05/2024, 12:58 AMvar currentJob: Job? = null
fun haveFun() {
currentJob = someScope.launch(Dispatchers.IO) {
// ...
}.apply {
invokeOnCompletion {
currentJob = null
}
}
}
There are two assignments: could it happen (even if it's unlikely) that invokeOnCompletion runs before the assignment of someScope.launch(...) { ... }?Daniel Pitts
10/05/2024, 1:19 AMDaniel Pitts
10/05/2024, 1:20 AMsomeScope.launch(...){...}.also { job ->
currentJob = job
job.invokeOnComplete { currentJob = null }
}Joffrey
10/05/2024, 7:59 AMcurrentJob = someScope.launch { ... }
currentJob.invokeOnCompletion { currentJob = null }Mark
10/05/2024, 10:53 AMcurrentJob == this before setting it to null, just in case another coroutine has set currentJob in the meantime?Daniel Pitts
10/05/2024, 3:12 PMManuel Pérez Alcolea
10/05/2024, 9:26 PM.apply. My question was actually about what .apply compiles to: in typical synchronized code and immutable values, we don't really care how it does what it does. But this made me wonder the compiler transformed .apply in a way that 1) It created the job first 2) it ran .apply 3) it assigned the job to currentJob or if 1) it created the job 2) it assigned the job to currentJob 3) it ran the .apply block.
The decompiler to Java couldn't quite answer this and I wasn't going to learn the in and outs of bytecode haha.ephemient
10/06/2024, 6:11 AMapply is just a normal (albeit inline) function, so yes it gets called before currentJob is assignedephemient
10/06/2024, 11:42 PMval currentJob = AtomicReference<Job>()
fun haveFun() {
val newJob = someScope.launch(start = CoroutineStart.LAZY) { ... }
if (currentJob.compareAndSet(null, newJob)) {
newJob.invokeOnCancellation { currentJob.compareAndSet(newJob, null) }
newJob.start()
} else {
newJob.cancel()
}
}
or depending on your use case, maybe a single actor triggered by a flow or channel would be a better solutionDmitry Khalanskiy [JB]
10/07/2024, 10:52 AMinvokeOnCompletion is very rarely useful. If you explain what you intend to do, maybe we could suggest a more idiomatic approach.
For example, if you need null to do while (currentJob != null) or something to that effect, it may be possible to replace it with while (currentJob.isActive).Daniel Pitts
10/07/2024, 12:43 PM