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