hello everyone! I was wondering what would be the ...
# multiplatform
d
hello everyone! I was wondering what would be the recommended way to make this code thread safe for multiplatform
Copy code
private var currentJob: Job? = null

fun flushData() {
    if (currentJob?.isActive == true) return
    currentJob = scope.launch {
        // Flush data while there is data to flush
    }
}
The idea would be to avoid creating new unnecessary
currentJob
having
flushData
accessed potentially from any thread
I checke the docs and it shows the usage of
Atomic
types but that only works in JVM and
Mutex.withLock
already requires to be launched from a Coroutine. The API is exposed to Android and iOS, so it seems best not to require the usage of Coroutines to call this method
c
I would probably buffer the requests through a
Channel
, and then you can read from the Channel as a Flow to apply the skipping/restarting logic you need safely. Something like this might work
Copy code
val flushDataChannel = Channel<Unit>(RENDEZVOUS, BufferOverflow.DROP_LATEST)

fun flushData() {
    flushDataChannel.trySend(Unit) // returns ChannelResult.Failed if it's already processing a request
}

fun CoroutineScope.processFlushData() = launch {
    flushDataChannel
        .consumeAsFlow()
        .onEach { /* Perform flush data operation */ }
        .launchIn(this)
}
d
ah, it seems that
Channel
with
BufferOverflow.DROP_LATEST
can do the job, let me try. Thanks!
c
Yeah, using a Channel and Flow operators makes it pretty easy to tweak the actual logic to your needs. Whether to cancel and restart, ignore subsequent requests, etc. is all pretty easy to configure and makes it easy to read and understand the intent behind that code
d
how do you use
processFlushData
?
c
Somewhere else in your application, you’d start it so that it’s running in the background
d
I am missing the connection between
flushData
(called externally) and
processFlushData
extension
I'll check Channels docs, as I haven't really used them much
c
processFlushData
is something you’d call once when the application starts up, so that it’s always ready to actually flush the data when you need to, but calling this method itself does not actually flush the data.
flushData
can be called from anywhere, on any thread, and it will simply request that the data be flushed by sending an object into the Channel. Only if
processFlushData
is currently running in the background will the request actually be accepted and the data flushed
d
ah, I get it now. Thanks once again!