Reputation: 1622
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
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