Repository: Kotlin/kotlinx.coroutines
File: kotlinx-coroutines-core/common/src/channels/Channels.common.kt (Kotlin)

Code before:
 * // Launch the exclusive consumer
 * val result = run {
 *     channel.consumeEach {
 *         if (it == 42) {
 *             println("Found the answer")
 *             return@run it // forcibly stop collection
 *         }
 *     }
 *     // *Note*: some elements could be lost in the channel!
 * }
 * check(result == 42)
 * ```
 *
 * In this example, several coroutines put elements into a single channel, and a single consumer processes the elements.
 * Once it finds the elements it's looking for, it stops [consumeEach] by making an early return.
 *
 * **Pitfall**: even though the name says "each", some elements could be left unprocessed if they are added after
 * this function decided to close the channel.
 * In this case, the elements will simply be lost.
 * If the elements of the channel are resources that must be closed (like file handles, sockets, etc.),
 * an `onUndeliveredElement` must be passed to the [Channel] on construction.
 * It will be called for each element left in the channel at the point of cancellation.
 */
public suspend inline fun <E> ReceiveChannel<E>.consumeEach(action: (E) -> Unit): Unit =
    consume {
        for (e in this) action(e)
    }

/**
 * [Consumes][consume] the elements of this channel into a list, preserving their order.
 *
 * This is a convenience function equivalent to calling [consumeAsFlow] followed by [kotlinx.coroutines.flow.toList].
 * It is useful for testing code that uses channels to observe the elements the channel contains at the end of the test.
 *
 * There is no way to recover channel elements if the channel gets closed with an exception
 * or to apply additional transformations to the elements before building the resulting collection.
 * Please use [consumeAsFlow] and [kotlinx.coroutines.flow.toCollection] for such advanced use-cases.
 *
 * [toList] attempts to receive elements and put them into the list until the channel is
 * [closed][SendChannel.close].
 * Calling [toList] on channels that are not eventually closed is always incorrect:
 * - It will suspend indefinitely if the channel is not closed, but no new elements arrive.
 * - If new elements do arrive and the channel is not eventually closed, [toList] will use more and more memory
 *   until exhausting it.
 *
 * If the channel is [closed][SendChannel.close] with a cause, [toList] will rethrow that cause.
 *
 * Since this function is implemented using [consume], the function is _terminal_.
 * In practice, this means that if adding new elements to the list fails with an exception,
 * that exception will be used for [cancelling][ReceiveChannel.cancel] the channel and rethrown.
 *

Review comment (suggestion):
```suggestion
 * It is useful for testing to observe the elements the channel contains at the end of the test.
```

Code after:
 * // Launch the exclusive consumer
 * val result = run {
 *     channel.consumeEach {
 *         if (it == 42) {
 *             println("Found the answer")
 *             return@run it // forcibly stop collection
 *         }
 *     }
 *     // *Note*: some elements could be lost in the channel!
 * }
 * check(result == 42)
 * ```
 *
 * In this example, several coroutines put elements into a single channel, and a single consumer processes the elements.
 * Once it finds the elements it's looking for, it stops [consumeEach] by making an early return.
 */
public suspend inline fun <E> ReceiveChannel<E>.consumeEach(action: (E) -> Unit): Unit =
    consume {
        for (e in this) action(e)
    }

/**
 * [Consumes][consume] the elements of this channel into a list, preserving their order.
 *
 * This is a convenience function equivalent to calling [consumeAsFlow] followed by [kotlinx.coroutines.flow.toList].
 * It is useful for testing code that uses channels to observe the elements the channel contains at the end of the test.
 *
 * There is no way to recover channel elements if the channel gets closed with an exception
 * or to apply additional transformations to the elements before building the resulting collection.
 * Please use [consumeAsFlow] and [kotlinx.coroutines.flow.toCollection] for such advanced use-cases.
 *
 * [toList] attempts to receive elements and put them into the list until the channel is
 * [closed][SendChannel.close].
 * Calling [toList] on channels that are not eventually closed is always incorrect:
 * - It will suspend indefinitely if the channel is not closed, but no new elements arrive.
 * - If new elements do arrive and the channel is not eventually closed, [toList] will use more and more memory
 *   until exhausting it.
 *
 * If the channel is [closed][SendChannel.close] with a cause, [toList] will rethrow that cause.
 *
 * Since this function is implemented using [consume], it is _terminal_,
 * meaning that [toList] will [cancel][ReceiveChannel.cancel] the channel before exiting.
 * A [toList] call can finish before the sender closes the channel
 * if it gets cancelled while waiting for the next element,
 * or if [MutableList.add] fails with an exception.
 * In both cases, the exception will be used for cancelling the channel and then rethrown.
 *
 * Example:
 * ```
 * val values = listOf(1, 5, 2, 9, 3, 3, 1)
 * // start a new coroutine that creates a channel,