Vencat
Vencat

Reputation: 1622

Understanding yield in kotlin sequence

I understand that the kotlin sequence is just a coroutine with a yield suspend function (correct me if I'm wrong). So the yield function sets the value and suspends the coroutine until the next value is requested.

yield source code

override suspend fun yield(value: T) {
    nextValue = value
    state = State_Ready
    return suspendCoroutineUninterceptedOrReturn { c ->
        nextStep = c
        COROUTINE_SUSPENDED
    }
}

Link to kotlin source code github

I see that it set the nextValue & state and suspends the coroutine by calling suspendCoroutineUninterceptedOrReturn.

Now I would like to know, where does this get resume?

I don't see any resume call inside next() function

override fun next(): T {
        when (state) {
            State_NotReady, State_ManyNotReady -> return nextNotReady()
            State_ManyReady -> {
                state = State_ManyNotReady
                return nextIterator!!.next()
            }
            State_Ready -> {
                state = State_NotReady
                @Suppress("UNCHECKED_CAST")
                val result = nextValue as T
                nextValue = null
                return result
            }
            else -> throw exceptionalState()
        }
    }

Upvotes: 0

Views: 392

Answers (1)

Tenfour04
Tenfour04

Reputation: 93639

Just from looking at the source code page you linked:

Calling next() first checks if hasNext() has already been called. If it has, it can immediately return the next value, which was queued in hasNext(). If hasNext() has not yet been called, nextNotReady() is called, which basically calls hasNext() to prepare that next value and then returns it.

So the real work all happens in hasNext(). It checks if the current continuation’s iterator (which exists if yieldAll() is called) has another value, in which case it can queue it without resuming the continuation. But if the current iterator is done or there was no iterator, then it calls resume on the continuation, which makes it run until the next yield() or yieldAll() call.

This description is a big simplification. There are different edge cases that it is handling based on the order of next/hasNext calls.

Upvotes: 1

Related Questions