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

Code before:
/**
 * [Consumes][consume] the elements of this channel into the provided mutable collection.
 *
 * This is a convenience function equivalent to calling [consumeAsFlow]
 * followed by [kotlinx.coroutines.flow.toCollection].
 * Please use [consumeAsFlow] directly in scenarios where elements should undergo additional transformations
 * before being added to the resulting collection.
 *
 * [consumeTo] attempts to receive elements and put them into the collection until the channel is
 * [closed][SendChannel.close].
 *
 * If the channel is [closed][SendChannel.close] with a cause, [consumeTo] will rethrow that cause.
 * However, the elements already received up to that point will remain in the collection.
 *
 * Since this function is implemented using [consume], the function is _terminal_.
 * In practice, this means that if adding new elements to the collection fails with an exception,
 * that exception will be used for [cancelling][ReceiveChannel.cancel] the channel and rethrown.
 *
 * The intended use case for this function is collecting the remaining elements of a closed channel
 * and processing them in a single batch.
 *
 * Example:
 * ```
 * val doContinue = AtomicBoolean(true)
 *
 * // Start the sender
 * val channel = produce {
 *     var i = 0
 *     while (doContinue.load()) {
 *         send(i++)
 *         delay(10.milliseconds)
 *         if (i == 42) break
 *     }
 * }
 *
 * // Start the consumer
 * launch {
 *     // Read elements until we suddenly decide to stop
 *     // or until the channel is closed.
 *     while (Random.nextInt() % 100 != 42) {
 *         val nextElement = channel.receiveCatching()
 *         if (nextElement.isClosed) return@launch
 *         println("Received ${nextElement.getOrNull()}")
 *     }
 *     doContinue.store(false)
 *     delay(100.milliseconds)
 *     val remainingElements = mutableListOf<Int>()
 *     try {
 *         channel.consumeTo(remainingElements)
 *     } finally {
 *         println("Remaining elements: $remainingElements")

Review comment (refactor):
Re using produce - could you confirm if our undestanding matches?

In theory we may want to avoid using `@ExperimentalCoroutinesApi` in samples, but the channels are the same level of lower-level abstractions, so if someone uses the channels, it's ok to make them aware of produce.

And also because our `@ExperimentalCoroutinesApi` annotations do not always precisely indicate the state of API.

Same for `AtomicBoolean`, but I can see how it's not as easy to substitute for a stable API.

Code after:
 * followed by [kotlinx.coroutines.flow.toCollection].
 * Please use [consumeAsFlow] directly in scenarios where elements should undergo additional transformations
 * before being added to the resulting collection.
 *
 * [consumeTo] attempts to receive elements and put them into the collection until the channel is
 * [closed][SendChannel.close].
 *
 * If the channel is [closed][SendChannel.close] with a cause, [consumeTo] will rethrow that cause.
 * However, the elements already received up to that point will remain in the collection.
 *
 * Since this function is implemented using [consume], it is _terminal_,
 * meaning that [consumeTo] will [cancel][ReceiveChannel.cancel] the channel before exiting.
 * A [consumeTo] call can finish before the sender closes the channel
 * if it gets cancelled while waiting for the next element,
 * or if [MutableCollection.add] fails with an exception.
 * In both cases, the exception will be used for cancelling the channel and then rethrown.
 *
 * The intended use case for this function is collecting the remaining elements of a closed channel
 * and processing them in a single batch.
 *
 * Example:
 * ```
 * val doContinue = AtomicBoolean(true)
 *
 * // Start the sender
 * val channel = produce {
 *     var i = 0
 *     while (doContinue.load()) {
 *         send(i++)
 *         delay(10.milliseconds)
 *         if (i == 42) break
 *     }
 * }
 *
 * // Start the consumer
 * launch {
 *     // Read elements until we suddenly decide to stop
 *     // or until the channel is closed.
 *     while (Random.nextInt(100) != 0) {
 *         val nextElement = channel.receiveCatching()
 *         if (nextElement.isClosed) return@launch
 *         println("Received ${nextElement.getOrNull()}")
 *     }
 *     delay(100.milliseconds)
 *     doContinue.store(false)
 *     delay(100.milliseconds)
 *     val remainingElements = mutableListOf<Int>()
 *     try {
 *         channel.consumeTo(remainingElements)
 *     } finally {
 *         println("Remaining elements: $remainingElements")