Run the following code
fun main(args: Array<String>) = runBlocking<Unit> {
val producer = produce<Int>(coroutineContext, capacity = 1) {
for(i in 1..2) {
send(i)
println("Sent: $i")
}
}
for (x in producer) {
println("Received: $x")
}
}
The output is:
Sent: 1
Sent: 2
Received: 1
while expected output is:
Sent: 1
Sent: 2
Received: 1
Received: 2
The problem shows up with any buffered chennel (ArrayChannel and LinkedListChannel) and does not show up with RendezvousChannel (capacity = 0). It only affects produce builder. Replacing produce with an "manual" code via launch works as expected:
val producer = Channel<Int>(1)
launch(coroutineContext) {
for(i in 1..2) {
producer.send(i)
println("Sent: $i")
}
producer.close()
}
I don't know if it helps, but I've notice that if we don't specify a context it succeed with ArrayChannel but still fails with LinkedListChannel and ConflatedChannel.
This code:
fun main(args: Array<String>) = runBlocking {
val producer = produce(capacity = 1) {
for(i in 1..2) {
send(i)
println("Sent: $i")
}
}
for (x in producer) {
println("Received: $x")
}
}
produce the following output:
Sent: 1
Sent: 2
Received: 1
Received: 2
But this code:
fun main(args: Array<String>) = runBlocking {
val producer = produce(capacity = Channel.UNLIMITED) { // same problem with Channel.CONFLATED
for(i in 1..2) {
send(i)
println("Sent: $i")
}
}
for (x in producer) {
println("Received: $x")
}
}
produce:
Sent: 1
Sent: 2
Received: 2
@jcornaz Try to run your first example several times. Sometimes it will return wrong result:
Sent: 1
Received: 1
Sent: 2
Thus I think ArrayChannel have the same problem.
@maxd Indeed, you're right! Haven't seen that.
However, I was already convinced of a problem when using ArrayChannel (as demonstrated by @elizarov). I just hoped that knowing the difference of behavior depending on the context could help to debug it. It seems that at the end it doesn't really help. sorry.
The problem is actually in produce. It cancels(sic!) the underlying channel (instead of closing) when producing coroutine returns. That's the bug. will be fixed soon.
@elizarov Is the only workaround not to use produce for now?
Most helpful comment
The problem is actually in
produce. It cancels(sic!) the underlying channel (instead of closing) when producing coroutine returns. That's the bug. will be fixed soon.