From 88a2ec393e45ee6ae469dfe9815c0a0bba779d34 Mon Sep 17 00:00:00 2001 From: Natasha Murashkina Date: Thu, 9 Oct 2025 11:39:22 +0100 Subject: [PATCH 1/4] add an example, stress that different coroutines *can* iterate over the channel, with their own iterator instance --- .../common/src/channels/Channel.kt | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 3e3c0f5fae..4be8142db8 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -1050,7 +1050,36 @@ public inline fun ChannelResult.onClosed(action: (exception: Throwable?) /** * Iterator for a [ReceiveChannel]. - * Instances of this interface are *not thread-safe* and shall not be used from concurrent coroutines. + * Instances of this interface are *not thread-safe*. + * Each iterator instance should be used by a single coroutine. + * + * An example usage: + * + * ``` + * val channel = Channel() + * launch { + * channel.send(1) + * channel.send(2) + * channel.send(3) + * channel.close() // NB: must close for iterators to finish + * } + * launch { + * for (element in channel) { + * println("Consumer A got $element") + * } + * } + * launch { + * for (element in channel) { + * println("Consumer B got $element") + * } + * } + * ``` + * Possible output: + * ```text + * Consumer A got 1 + * Consumer A got 2 + * Consumer B got 3 + * ``` */ public interface ChannelIterator { /** From 4ac51213bf36b7110735ce769e51c15f8ceb0bea Mon Sep 17 00:00:00 2001 From: Natasha Murashkina Date: Thu, 9 Oct 2025 11:47:09 +0100 Subject: [PATCH 2/4] add "created" --- kotlinx-coroutines-core/common/src/channels/Channel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 4be8142db8..5cdd19b4d0 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -1051,7 +1051,7 @@ public inline fun ChannelResult.onClosed(action: (exception: Throwable?) /** * Iterator for a [ReceiveChannel]. * Instances of this interface are *not thread-safe*. - * Each iterator instance should be used by a single coroutine. + * Each iterator instance should be created and used by a single coroutine. * * An example usage: * From 9d2c2732c5502f97a015ac30fb831a0003ed7c54 Mon Sep 17 00:00:00 2001 From: Natasha Murashkina Date: Fri, 7 Nov 2025 18:59:12 +0000 Subject: [PATCH 3/4] fix --- kotlinx-coroutines-core/common/src/channels/Channel.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 5cdd19b4d0..4995ea568e 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -1051,7 +1051,15 @@ public inline fun ChannelResult.onClosed(action: (exception: Throwable?) /** * Iterator for a [ReceiveChannel]. * Instances of this interface are *not thread-safe*. - * Each iterator instance should be created and used by a single coroutine. + * A coroutine is only allowed to call methods on the iterator instances which it instantiated. + * + * Typically, an iterator is used indirectly in the `for` loop and is not instantiated explicitly. + * + * ``` + * for (element in channel) { + * // process element + * } + * ``` * * An example usage: * From 742262d038cffb798f4064fdb7d45c46f84e002e Mon Sep 17 00:00:00 2001 From: Natasha Murashkina Date: Fri, 7 Nov 2025 19:10:49 +0000 Subject: [PATCH 4/4] add wording on hasNext/next --- kotlinx-coroutines-core/common/src/channels/Channel.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/channels/Channel.kt b/kotlinx-coroutines-core/common/src/channels/Channel.kt index 4995ea568e..8c4748e18d 100644 --- a/kotlinx-coroutines-core/common/src/channels/Channel.kt +++ b/kotlinx-coroutines-core/common/src/channels/Channel.kt @@ -1051,16 +1051,20 @@ public inline fun ChannelResult.onClosed(action: (exception: Throwable?) /** * Iterator for a [ReceiveChannel]. * Instances of this interface are *not thread-safe*. - * A coroutine is only allowed to call methods on the iterator instances which it instantiated. + * A coroutine is only allowed to call methods on those iterator instances which it instantiated. * * Typically, an iterator is used indirectly in the `for` loop and is not instantiated explicitly. * * ``` * for (element in channel) { - * // process element + * // process the element * } * ``` * + * If your use-case requires handling the iterator directly, + * you must call [hasNext] before each [next]. + * Refer to [hasNext] and [next] for more details. + * * An example usage: * * ```