Julian A.
Julian A.

Reputation: 11450

What does consuming a Kotlin Channel mean?

The Kotlin docs use the term consume both to describe the behavior of such methods as Channel#first() and in the names of methods such as Channel#consumeEach().

I'm having difficulty understanding what it means for a channel to be consumed vs non-consumed.

What does non-consumption even look like?

Does the Channel API allow for accessing items in a channel without consumption?

Other than consumeEach(), does consumption always imply completely emptying a channel?

Upvotes: 5

Views: 2621

Answers (2)

Julian A.
Julian A.

Reputation: 11450

The output of the following code illustrates the meaning of "consuming" and the effect of consumeEach.

fun f1() = runBlocking {
    val numbers = produce {
        repeat(5) {
            send(it)
            delay(100)
        }
    }
    run {
        for (i in numbers) {
            trace(i)
            if (i == 2) return@run
        }
    }
    trace("after run")
    for (i in numbers) {
        trace(i)
    }
    trace("exiting f1")
}
f1()

println()

fun f2() = runBlocking {
    val numbers = produce {
        repeat(5) {
            send(it)
            delay(100)
        }
    }
    run {
        numbers.consumeEach {
            trace(it)
            if (it == 2) return@run
        }
    }
    trace("after run")
    for (i in numbers) {
        trace(i)
    }
    trace("exiting f2")
}
f2()

Output:

[main @coroutine#1]: 0
[main @coroutine#1]: 1
[main @coroutine#1]: 2
[main @coroutine#1]: after run
[main @coroutine#1]: 3
[main @coroutine#1]: 4
[main @coroutine#1]: exiting f1

[main @coroutine#3]: 0
[main @coroutine#3]: 1
[main @coroutine#3]: 2
[main @coroutine#3]: after run
[main @coroutine#3]: exiting f2

We see that (in f1) we can stop iterating over a channel, then later continue where we left off. However, when using consumeEach (in f2), we are unable to stop and continue, even though the channel was initially capable of producing numbers greater than 2.

Upvotes: 6

Jayson Minard
Jayson Minard

Reputation: 85946

The use of "consume" means that it is a terminal action, that nothing outside this command can read from the channel. You can see this clearer in the API documentation for first and consumeEach:

The operation is terminal. This function consumes all elements of the original ReceiveChannel.

Note that there are also warnings in the docs that this API will change in the future.

Read KT-167 for useful comments on this topic.

Upvotes: 3

Related Questions