Stackless python and microthreads

Christian Tismer tismer at stackless.com
Sun May 16 11:51:13 EDT 2004


Donn Cave wrote:

> Quoth Peter Hansen <peter at engcorp.com>:
> | Mike C. Fletcher wrote:
> |
> | > continuations are the most awesome toys 
> | > you can imagine... we will all mourn their passing in time...
> |
> | Will that be _before_, or _after_ we understand what they are?  ;-)
> 
> I gave them a try, and I mourn them with a touch of relief, I guess.
> I'm the guy who won't bother to learn list comprehensions and generally
> despises cool gimmicks, but continuations were more than just cool,
> they were terribly powerful.

Yes. And terribly hard to maintain as well :-)

> I hooked them into a graphics toolkit wrapper with an event dispatching
> model where each window, network connection etc., ran in its own native
> thread.  No blocking, always ready to respond to a new message.  When a
> couple of these threads have to interact, they would queue messages back
> and forth, and the programming paradigm can get awkward - a lot of state
> can pile up as everyone's trying to keep track of their progress through
> some kind of procedure.
> 
> Well, suppose you send your message and save the whole function state
> somewhere, and return to the dispatcher.  When the response comes back,
> you pick up the function state and continue it, feeding the response in.

Ok, that's a nice pattern which I use as well, *with* current Stackless
and *without* continuations. Turning control flow inside out does not
depend upon continuations. You just need the ability to switch contexts,
which is in fact much less, but buys you a lot more.

A continuation is immutable. That means it can be activated multiple
times and it will not change state. How to explain this? Well, consider
a Python function, and you have several continuations captured from
that running function. Then you can jump at any continuation at any
time, as often as you like. This capability is incredible, but I never
saw an example of code that *really* had to have this feature.

Returning to some point in the running program and continuing there
is what most people need. This is less than a general continuation,
because the continuation is gone after resuming. You can call it
a one-shot continuation. On every context switch, the current
continuation is preserved, but it is never fired twice. This is very
much like threads.

Full continuations enforce that you have complete control over
the current program, especially you need to be able to track
all object references which must stay alive in a continuation.
This is not possible if your program state contains hidden
objects on the C stack, because we have no introspection feature
in the Python C implementation.
In other words: You cannot use continuations in the context of
C extensions.

Restricting ourselves to one-shot continuations, we don't need
to track any objects explicitly. This makes it possible to
deal with hidden objects just by saving and restoring parts of
the C stack.

And this makes tasklets more powerful that the old continuations:
it is possible to switch context all the time. The program
environment does not need to collaborate. Collaboration is more
efficient (i.e. trying to leave no state on the C stack), and
Stackless tries to do it almost everywhere. But that's not
a limitation. You can write ordinary C code and ask Stackless to
switch tasklets, and it will switch. I consider this more
valuable than continuations which pretend to be universal and
immportal, but only in a restricted context.

> Now instead of a tedious kind of state machine, you're writing an plain,
> ordinary function that sends messages to its peer and looks at the response,
> as though that were all synchronous, and it's so much simpler.  Yet the
> execution underneath that isn't synchronous at all, because your computation
> is suspended in between your send and the response.  It really does return
> every time it sends a message, it just starts up next time where it left
> off.

Exactly what I'm doing with Stackless. I have my own implementation
of sockets and files, which pretend to have synchronized calls
only, but under the hood they are asynchronous, dispatching over
a poll/select loop and optimizing throughput. The code is much
shorter than asyncore, and reasonably more effective if your server
is computation-bound. Unfortunately I can't publish this module,
yet, it was contract work.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer at stackless.com>
Mission Impossible 5oftware  :     Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a     :    *Starship* http://starship.python.net/
14109 Berlin                 :     PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34  home +49 30 802 86 56  mobile +49 173 24 18 776
PGP 0x57F3BF04       9064 F4E1 D754 C2FF 1619  305B C09C 5A3B 57F3 BF04
      whom do you want to sponsor today?   http://www.stackless.com/





More information about the Python-list mailing list