Home > Software engineering >  Questions about kotlin coroutine & SharedFlow usage
Questions about kotlin coroutine & SharedFlow usage

Time:02-28

I am newbie and would want to ask correct usage of coroutine and sharedFlow.

For example of below code, in the function I want to parallel call two actions. I expect that there will be 3 possible result:

-The action1 return result first, then we use its result to return for function foo. -The action2 return result first, then we use its result to return. -The whole action is timeout after 3s and throw timeout error.

suspend fun foo() {
val a = MutableSharedFlow<Int>()
val sf = a.asSharedFlow()

return withTimeout(3000) {
  launch {
    action1().let { a.emit(it) }
  }
  launch {
    action2().let { a.emit(it) }
  }
  sf.first {
    return@withTimeout it
  }
}
}

My question is:

  1. After foo is returned, would the two launched coroutine for action1 and action2 cancelled? or they will continue to run in the background?

  2. Let’s say action 1 is returned, but action 2 is not return back forever (may be network issue). Although the code may already quit foo, will action2 cause a leaking SharedFlow forever?

  3. Do I need to do anything explicitly to close the MutableSharedFlow or SharedFlow which declared inside the function foo? or will they be closed and garbage collected normally after the function foo returned?

CodePudding user response:

Since withTimeout cancels its jobs after the timeout, any remaining child coroutines will be cancelled when it returns. It's not clear to me from the documentation if it immediately cancels children when it returns before the timeout (we could check the source code to find out). But once they're cancelled, there will be no more held references to the shared flow, so it will be released.

Your sf variable doesn't accomplish anything.

Using a flow internally in the function is convoluted. You could replace it all with:

suspend fun foo(): Int? = withTimeoutOrNull(3000) {
    select<Int> {
        async { action1() }.onAwait { it }
        async { action2() }.onAwait { it }
    }
}
  • Related