send
Sends the specified element to this channel.
This function suspends if it does not manage to pass the element to the channel's buffer (or directly the receiving side if there's no buffer), and it can be cancelled with or without having successfully passed the element. See the "Suspending and cancellation" section below for details. If the channel is closed, an exception is thrown (see below).
val channel = Channel<Int>()
launch {
check(channel.receive() == 5)
}
channel.send(5) // suspends until 5 is received
Suspending and cancellation
If the BufferOverflow strategy of this channel is BufferOverflow.SUSPEND, this function may suspend. The exact scenarios differ depending on the channel's capacity:
If the channel is rendezvous, the sender will be suspended until the receiver calls ReceiveChannel.receive.
If the channel is unlimited or conflated, the sender will never be suspended even with the BufferOverflow.SUSPEND strategy.
If the channel is buffered (either BUFFERED or uses a non-default buffer capacity), the sender will be suspended until the buffer has free space.
This suspending function is cancellable: if the Job of the current coroutine is cancelled while this suspending function is waiting, this function immediately resumes with CancellationException. There is a prompt cancellation guarantee: even if send managed to send the element, but was cancelled while suspended, CancellationException will be thrown. See suspendCancellableCoroutine for low-level details.
Because of the prompt cancellation guarantee, an exception does not always mean a failure to deliver the element. See the "Undelivered elements" section in the Channel documentation for details on handling undelivered elements.
Note that this function does not check for cancellation when it is not suspended. Use ensureActive or CoroutineScope.isActive to periodically check for cancellation in tight loops if needed:
// because of UNLIMITED, sending to this channel never suspends
val channel = Channel<Int>(Channel.UNLIMITED)
val job = launch {
while (isActive) {
channel.send(42)
}
// the loop exits when the job is cancelled
}
This isn't needed if other cancellable functions are called inside the loop, like delay.
Sending to a closed channel
If a channel was closed before send was called and no cause was specified, an ClosedSendChannelException will be thrown from send. If a channel was closed with a cause before send was called, then send will rethrow the same (in the ===
sense) exception that was passed to close.
In both cases, it is guaranteed that the element was not delivered to the consumer, and the onUndeliveredElement
callback will be called. See the "Undelivered elements" section in the Channel documentation for details on handling undelivered elements.
Closing a channel after this function suspends does not cause this suspended send invocation to abort: although subsequent invocations of send fail, the existing ones will continue to completion, unless the sending coroutine is cancelled.
Related
This function can be used in select invocations with the onSend clause. Use trySend to try sending to this channel without waiting and throwing.