Fake threads (was [Python-Dev] ActiveState & fork & Perl)

Tim Peters tim_one@email.msn.com
Thu, 8 Jul 1999 01:59:18 -0400


>> Again, though, you never want to muck with continuations directly!
>> They're too wild.  You get an expert to use them in the bowels of an
>> implementation of something else.

[Christian]
> Maybe with one exception: With careful coding, you can use
> a continuation at the head of a very deep recursion and use
> it as an early break if the algorithm fails. The effect is
> the same as bailing out with an exception, despite the fact
> that no "finally" causes would be obeyed. It is just a
> incredibly fast jump out of something if you know what
> you are doing.

You don't need continuations for this, though; e.g., in Icon I've done this
often, by making the head of the deep recursion a co-expression, doing the
recursion via straight calls, and then doing a coroutine resumption of &main
when I want to break out.  At that point I set the coexp to &null, and GC
reclaims the stack frames (the coexp is no longer reachable from outside)
when it feels like it <wink>.

This is a particularly simple application of coroutines that could be
packaged up in a simpler way for its own sake; so, again, while
continuations may be used fruitfully under the covers here, there's still no
reason to make a poor end user wrestle with them.

> ... Well, I admit that the continuation approach is slightly too much
> for the coroutine/generator case,

It's good that you admit that, because generators alone could have been
implemented with a 20-line patch <wink>.  BTW, I expect that by far the bulk
of your changes *still* amount to what's needed for disentangling the C
stack, right?  The continuation implementation has been subtle, but so far
I've gotten the impression that it requires little code beyond that required
for stacklessness.

> ...
> How about "amb"? :-)
> (see "teach youself schem in fixnum days, chapter 14 at
> http://www.cs.rice.edu/~dorai/t-y-scheme/t-y-scheme-Z-H-15.html#%_chap_14)

That's the point at which I think continuations get insane:  it's an
unreasonably convoluted implementation of a straightforward (via other
means) backtracking framework.  In a similar vein, I've read 100 times that
continuations can be used to implement a notion of (fake) threads, but
haven't actually seen an implementation that wasn't depressingly subtle &
long-winded despite being just a feeble "proof of concept".

These have the *feeling* of e.g. implementing generators on top of real
threads:  ya, you can do it, but nobody in their right mind is fooled by it
<wink>.

> About my last problems:
> The hard decision is:
> - Either I just stop and I'm ready already, and loops are funny.

OK by me -- forgetting implementation, I still can't claim to know what's
the best semantic here.

> - Or I do the hidden register search, which makes things more
>   complicated and also voidens the pushback trick partially,
>   since then I would manage all stack stuff in one frame.

Bleech.

> - Or, and that's what I will do finally:
>   For now, I will really just correct the loops.
>
> Well, that *is* a change to Python again, but no semantic change.
> The internal loop counter will no longer be an integer object,
> but a mutable integer box. I will just create a one-element
> integer array and count with its zero element.
> This is correct, since the stack value isn't popped off,
> so all alive stack copies share this one element.

Ah, very clever!  Yes, that will fly -- the continuations will share a
reference to the value rather than the value itself.  Perfect!

> As a side effect, I save the Object/Integer conversion, so
> I guess it will be faster. *and* this solution does not involve
> any other change, since the stack layout is identical to before.

Right, no downside at all.  Except that Guido will hate it <wink>.

there's-a-disturbance-in-the-force-ly y'rs  - tim