awaitClose

suspend fun ProducerScope<*>.awaitClose(block: () -> Unit = {})(source)

Suspends the current coroutine until the channel is either closed or cancelled.

The given block will be executed unconditionally before this function returns. awaitClose { cleanup() } is a convenient shorthand for the often useful form try { awaitClose() } finally { cleanup() }.

This function can only be invoked directly inside the same coroutine that is its receiver. Specifying the receiver of awaitClose explicitly is most probably a mistake.

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 this function is ready to return, but was cancelled while suspended, CancellationException will be thrown. See suspendCancellableCoroutine for low-level details.

Example of usage:

val callbackEventsStream = produce {
val disposable = registerChannelInCallback(channel)
awaitClose { disposable.dispose() }
}

Internally, awaitClose is implemented using SendChannel.invokeOnClose. Currently, every channel can have at most one SendChannel.invokeOnClose handler. This means that calling awaitClose several times in a row or combining it with other SendChannel.invokeOnClose invocations is prohibited. An IllegalStateException will be thrown if this rule is broken.

Pitfall: when used in produce, if the channel is cancelled, awaitClose can either return normally or throw a CancellationException due to a race condition. The reason is that, for produce, cancelling the channel and cancelling the coroutine of the ProducerScope is done simultaneously.

Throws

if this channel already has a SendChannel.invokeOnClose handler registered.