On Sun, 2011-11-06 at 22:21 +1000, Nick Coghlan wrote:
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.
Ok, I found it and the link to the implantation.
Thanks for the reminder, I'll check it out tonight when I get back.
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.
Well, that was what I was trying for. In any event, I'm learning a lot more by trying to actually do it, than just speculate about it. I'm at the point of learning just how exceptions interact with the frames. And I'm pretty sure I'll just confirm what you say below, but with a much better understanding of how it all works.
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)