user1725145
user1725145

Reputation: 4042

How to write Kotlin-colloquial code to retry synchronously until timeout or success?

After reading Kotlin documentation, I came up with the following code (which is not working - see below) to repeat a function call until it returns true, or timeout is reached.
I want to pause execution until this code block reaches timeout or success - it is not supposed to execute asynchronously.

Log.d(TAG, "This is the last line to be logged")
runBlocking {
    Log.d(TAG, "this line is never logged")
    try {
        withTimeout(timeoutMsL) {
            while ((isActive) && (!success)) {
                success = doSomething()
            }
        } 
    }
    catch (ex: TimeoutCancellationException) {
        Log.d(TAG, "this line is never logged either")
        doSomethingElse()
    }
}

timeoutMsL is a Long with typical value 50 ms. This code is called from C++ over the JNI. When I run it

I have read that runBlocking should be avoided, but also you have to call withTimeout from an existing coroutine.
If I use a normal coroutine, execution of the calling function will continue before timeout /success is reached - I need to prevent this from happening.

How should this be coded in Kotlin?

Upvotes: 1

Views: 1954

Answers (1)

Kiskae
Kiskae

Reputation: 25603

Your problem probably lies in doSomething(). Kotlin's coroutine implementation relies a lot on cooperative execution where child coroutines check flags to see if they have been cancelled (as withTimeout() would do). This would mean the outer coroutines will pause until they confirm the child coroutines have ended, blocking the entire function.

if doSomething never suspends and never checks if it is still active it will just run until completion regardless of the external situation.

To fix this, there are two options:

  1. Make doSomething() a suspend function and regularly suspend with either yield() or ensureActive() to respond to cancellation.
  2. Execute it on a dispatcher that is designed to interrupt normal blocking code like withContext(Dispatchers.IO).

Upvotes: 1

Related Questions