Hello, I'm trying to solve the following problem:...
# coroutines
t
Hello, I'm trying to solve the following problem: Multiple Coroutines (on different threads) may send a request to an API. The API may respond, that a login is required. In this case the first coroutine should initiate the login sequence. All other coroutines should suspend until the sequence is executed. I currently implemented this as follows:
Copy code
val loginSequence = SharedMethod<String>()

suspend fun request() {
    try {
        loginSequence
            .awaitIfNeeded()

        return doRequest(...)
    } catch(e: LoginRequiredException) {
        return loginSequence.awaitOrBlock(
            onBlockReturn = {
                return@awaitOrBlock executeLoginSequence(e)
            },
            onAwaitReturn = {
                return@awaitOrBlock doRequest(
                    ...
                )
            })
    }
}
with the implementation of this class with mutexes:
Copy code
class SharedMethod<T> {
    private val mutex: Mutex = Mutex()

    suspend fun awaitOrBlock(
        onBlockReturn: suspend () -> T,
        onAwaitReturn: suspend () -> T
    ): T = coroutineScope {
        val isLocked = mutex.tryLock()

        if (!isLocked) {
            awaitIfNeeded()

            return@coroutineScope onAwaitReturn()
        }

        try {
            return@coroutineScope onBlockReturn()
        } finally {
            mutex.unlock()
        }
    }

    suspend fun awaitIfNeeded() {
        while (mutex.isLocked) {
            delay(1000)
        }
    }
}
Is there a better way to implement this behaviour? Especially the "while (mutex.isLocked) {...}" seems pretty ugly. Is this the right place for using mutexes? Happy to hear your thoughts. :)
d
Just
lock
the mutex isn't of trying to poll it.
👍 1
t
Thank you very much 🙂