https://kotlinlang.org logo
Title
j

Jan Skrasek

07/30/2021, 10:10 PM
A different between
MutableSharedFlow()
and
Channel()
with runBlockingTest I would expect both to behave the same; Yet when not using extraBufferaCapacity = 1, my following test fails for MutableSharedFlow and not for Channel. (See gist) https://gist.github.com/hrach/94ba0dc427ad2f08a73467d8972516a2 • why is there a difference? • is both behavior correct? • is correct that there is a difference?
n

Nick Allen

07/30/2021, 11:55 PM
Read: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-mutable-shared-flow/try-emit.html You are setting up your
MutableSharedFlow
with no buffer space and
SUSPEND
strategy.
tryEmit
will always fail and return false.
:thank-you: 1
MutableSharedFlow
replaces
BroadcastChannel
, not
Channel
. It can send events to many listeners, but it is not a queue.
j

Jan Skrasek

07/31/2021, 5:52 AM
You are setting up your
MutableSharedFlow
with no buffer space and
SUSPEND
strategy.
tryEmit
will always fail and return false.
This seems to be crucial info. It could be in kdoc. Still I don't understand why channel with no buffer is able to handle this.
n

Nick Allen

07/31/2021, 6:19 PM
Flow
uses a callback mechanism. When you call
emit
on a
FlowCollector
you wait for
emit
to finish. If
MutableSharedFlow
isn't allowed to store the value in a buffer, its
emit
needs to loop through the listeners and wait for
emit
to finish for each listener.
Edit: MutableSharedFlow doesn't wait for listeners to finish.
Channel.send
waits for the data to be received, it does not wait for the data to be processed at all. It's more of a hand-off.
send
doesn't need to suspend just to tell another coroutine to resume.
I guess that didn't really clarify anything for you.
Channel
works because that's how it's designed to work.
MutableSharedFlow
could maybe work if its implementation changed, idk. Right now it just checks the buffer and buffer strategy to determine if tryEmit can work without suspending. This is nice because it's simple and fast. It could conceivably check if all listeners are "ready" but I imagine that could cause performance or just complexity issues. I wouldn't say it's super clear, but the behavior does feel like it's documented in the kdocs here: "When this function returns 
false
, it means that the call to a plain emit function will suspend until there is a buffer space available."
j

Jan Skrasek

07/31/2021, 9:21 PM
thanks!