On Sun, Nov 6, 2011 at 5:20 PM, Ron Adam email@example.com wrote:
What is needed is a different path out (and back) to the coroutine that doesn't interfere with the standard yield behavior. Or as you describe it here.
Did my post of the thread+queue based implementation of a coroutine API design concept not go through? It demonstrated exactly the need for a separate I/O channel independent of the call/return and next/send/throw/yield channels.
Yes, I'm leaning back towards a completely separate protocol now. We seem to need a number of new protocol features in any case, and allowing the two protocols to overlap is just creating needless confusion, I think.
I think adding a .resume() method to all generators would be good. That keeps it simple. It would just raise an exception in the case of a non-suspended generator. Which may be useful in a loop as well.
Looking at ceval.c, I think Nick's suggestion of adding a new WHY_SUSPEND would be good. And along with it, a TARGET(GEN_SUSPEND) block that sets up a SuspendIteration exception, and returns WHY_SUSPEND to the generator object.
The whole point of a separate WHY_SUSPEND is that you *wouldn't* unwind the stack at all - you'd just leave it in place and return to the point that called into the coroutine in the first place.
Exceptions are too destructive to the stack to be usable for this task (as soon as you hit an except or finally clause, the execution state in the frame gets modified to invoke them, thus meaning you can no longer resume that stack correctly)