I have a case where there is a global boolean whic...
# coroutines
m
I have a case where there is a global boolean which I’m referencing inside a launched coroutine but also mutating that in a different coroutine outside the coroutine where it is checked. This could lead to an edge case where the
job
checking its value could be looking at an old value and not most recent value changed by another thread and take an incorrect code path. We can set the field as `@Volatile`to ensure atomic read/writes and visiblity to other threads. But could this concern also be resolved by sharing a coroutine context between the 2 jobs? I think by default
launch
uses
Dispatchers.DEFAULT
. Would passing in a defined coroutinecontext to the
launch
block ensure the dispatcher shares a thread for those 2 coroutines?
Copy code
class Engine(val scope: CoroutineScope) {
@Volatile private var msgReceived = false
val job: Job? = null

init {
       scope.launch {
                 flow
                .onEach {
                    msgReceived = true
                    job?.cancel()
                    job = null
                }
                .launchIn(this)
     }
}

fun anotherMethod() {
            job =
                scope.launch {
                    delay(DELAY)
                    if (!msgReceived) {
                        flow.emit(Error())
                    }
                }
        } 

}
Could
@Volatile
be replaced with a custom context passed into the 2
launch()
s?
s
You can only avoid such a race condition if that Dispatcher is backed by a single-thread pool, ie the pool/Dispatcher can only run one coroutine at a time. You can use a coroutine Mutex or just plain atomic constructs like you already do if that's not the case.
v
you can create a dispatcher with limited parallelism:
Copy code
Dispatchers.Default.limitedParallelism(1)
coroutines launched to this dispatcher will be ran on at most 1 thread at a time, but the thread can change
z
I’d probably use an AtomicReference to store the job.
m
@Zach Klippenstein (he/him) [MOD] Do you mean in place of marking the mutating value as volatile or in addition to? What would be the concern by not storing the job in an AtomicReference?
z
I mean instead of using a muted or limiting dispatcher