The following hangs forever. I would like the suspend function to just return somehow if the send cannot complete.
suspend fun main() = coroutineScope {
val channel = Channel<Int>()
//channel.close()
launch {
println("closing")
channel.close()
}
channel.send(0) // hangs forever!!
println("end")
}
So basically what I need is a version of SendChannel.send
that just throws or returns when the channel is closed while it's suspended.
You said that you would like the
send
function to throw or return if the send cannot complete.You have a rendezvous channel with no buffer, so
send
will always suspend until the channel'sreceive
function is called. But that doesn't mean that yoursend
call can't complete.Even though the channel is closed,
receive
can still be called to successfully deliver a value that is already "in flight". In that case, the suspendedsend
call will return normally.The channel's order of operations is the same as the order that you called its functions in. A consumer reading from the channel will first see the value
0
, and then will reach the end of the channel, becausesend
was called beforeclose
.This is mentioned explicitly in the documentation for the
send
function of a channel.The
close
function is part of theSendChannel
interface and is intended for the sender to indicate that it isn't going to send any more values. It doesn't drop values that have already been sent, or are already in the process of being sent.A channel also has a
cancel
function, which is part of theReceiveChannel
interface. Thecancel
function is intended for the receiver to indicate that it doesn't want to receive any more values. This will drop all the values that have already been sent, and will cause any ongoingsend
attempts to fail with an exception.In your example code, if you replace
channel.close()
withchannel.cancel()
, the in-flight call tosend
will fail with an exception.