Reputation: 1465
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.
Upvotes: 0
Views: 152
Reputation: 9944
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's receive
function is called. But that doesn't mean that your send
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 suspended send
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, because send
was called before close
.
This is mentioned explicitly in the documentation for the send
function of a channel.
Closing a channel after this function has suspended does not cause this suspended send invocation to abort, because closing a channel is conceptually like sending a special "close token" over this channel. All elements sent over the channel are delivered in first-in first-out order. The sent element will be delivered to receivers before the close token.
The close
function is part of the SendChannel
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 the ReceiveChannel
interface. The cancel
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 ongoing send
attempts to fail with an exception.
In your example code, if you replace channel.close()
with channel.cancel()
, the in-flight call to send
will fail with an exception.
Upvotes: 2