Further discussion where @jakobnissen points to a “best practices” implementation of the interface as:
function Base.iterate(node::AbstractNode)
state = Channel(c -> traverse(node, c))
iterate(node, state)
end
function Base.iterate(node::AbstractNode, state::Channel)
# This iterate call on the channel will block if there are no more elements,
# and will return `nothing` if there are no more elements AND the channel
# is closed, which happens when `traverse` has yielded all its elements.
y = iterate(state)
isnothing(y) ? y : (first(y), state)
end
And that the behavior found with my implementation is expected (or at least not unexpected):
Putting in
yieldiniterateseems to solve the problem, because it allows the scheduler to switch totraverse. But it’s not a real fix, because there is still no guarantee the scheduler will actually switch task.