-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Closed
Description
When using channel with any buffer size, after filling full buffer with some elements, and then sending even more (those calls will suspend), after receiving first value from buffer, on first element, where send suspends, onUndeliveredElement will be called, and after next receive, onUndeliveredElement will be called on next element and so on, so calling onUndeliveredElement on all elements, that overflow buffer.
Reproducer:
class Resource(val i: Int) {
var closed = false
override fun toString(): String = "Resource($i, closed=$closed)"
}
@Test
fun testChannel() = test { //promise on js, runBlocking on jvm
val channel = Channel<Resource>(3) {
println("CLOSE: $it")
it.closed = true
}
val job = launch {
repeat(6) {
println("RECEIVE - ${channel.receive()}")
}
}
(0..5).map {
val r = Resource(it)
async {
println("SEND: $r")
channel.send(r)
println("SENT: $r")
}
}.awaitAll()
job.join()
}JVM/Native output - expected:
SEND: Resource(0, closed=false)
SENT: Resource(0, closed=false)
SEND: Resource(1, closed=false)
SENT: Resource(1, closed=false)
SEND: Resource(2, closed=false)
SENT: Resource(2, closed=false)
SEND: Resource(3, closed=false)
SENT: Resource(3, closed=false)
SEND: Resource(4, closed=false)
SEND: Resource(5, closed=false)
RECEIVE - Resource(0, closed=false)
RECEIVE - Resource(1, closed=false)
RECEIVE - Resource(2, closed=false)
RECEIVE - Resource(3, closed=false)
RECEIVE - Resource(4, closed=false)
RECEIVE - Resource(5, closed=false)
SENT: Resource(4, closed=false)
SENT: Resource(5, closed=false)
JS (same for browser/node legacy/IR) output - wrong:
SEND: Resource(0, closed=false)
SENT: Resource(0, closed=false)
SEND: Resource(1, closed=false)
SENT: Resource(1, closed=false)
SEND: Resource(2, closed=false)
SENT: Resource(2, closed=false)
SEND: Resource(3, closed=false)
SENT: Resource(3, closed=false)
SEND: Resource(4, closed=false)
SEND: Resource(5, closed=false)
RECEIVE - Resource(0, closed=false)
CLOSE: Resource(4, closed=false)
RECEIVE - Resource(1, closed=false)
CLOSE: Resource(5, closed=false)
RECEIVE - Resource(2, closed=false)
RECEIVE - Resource(3, closed=false)
RECEIVE - Resource(4, closed=true)
RECEIVE - Resource(5, closed=true)
SENT: Resource(4, closed=true)
SENT: Resource(5, closed=true)
Expected result:
There should be no calls to onUndeliveredElement in such case
Env:
kotlinVersion=1.5.21
kotlinxCoroutinesVersion=1.5.1-native-mt