score:4

Accepted answer

@ir42 said right, you should use channels for this purpose.

use channel and make one coroutine that is suspended and awaiting for the channel's sender to send the logs (strings or whatever).

using the default channel rendezvouschannel, when a sender sends a log the waiting coroutine resumes and if another sender sends the message then that next sender is suspended till the awaiting coroutine pulls the log from channel.

example demonstrating use of rendezvouschannel

val channel = channel<string>()    // channel of strings
val sendchannel: sendchannel<string> = channel  // hide that this instance can receive, store this in order to send to this channel

scope.launch(dispatchers.io) {
    while (!channel.isclosedforreceive) {
        val log = channel.receive()
        // process the log
    }
}

// somewhere else
sendchannel.send("test log")

score:0

you can try to emit logs to mutablesharedflow to write logs sequentially to a file:

class logger {
    // make sure `replay`(in case some logs were emitted before sharedflow is being collected)
    // and `extrabuffercapacity` is enough to handle all logs
    private val sharedflow = mutablesharedflow<string>(replay = 64, extrabuffercapacity = 64)
    private val scope = coroutinescope(dispatchers.io)

    init {
        sharedflow.oneach { log ->
            println("$log")
            // write to file here
            timeunit.milliseconds.sleep(100) // simulate writing to file
        }.launchin(scope)
    }

    fun log(message: string) {
        sharedflow.tryemit(message) 
    }
}

fun test() {

    val logger = logger()

    repeat(10) { item ->
        logger.log("log $item")
    }
}

need to be sure there are enough elements set to replay and extrabuffercapacity parameters of mutablesharedflow to handle all logs.


Related Query

More Query from same tag