Microthreads without Stackless?

David Mertz, Ph.D. groups.google at gnosis.cx
Sat Sep 18 14:39:28 EDT 2004


Let me follow up briefly on my last note.  I presented a
callstack-in-coroutines example a few moments ago.  The was something
like:

  from __future__ import generators
  cargo = None
  def grandma():
      yield (MOM, cargo)
  def mom():
      yield (DAUGHTER, cargo)
      yield (GRANDMA, cargo)
  def daughter():
      yield (MOM, cargo)
  GRANDMA, MOM, DAUGHTER = grandma(), mom(), daughter()
  scheduler(GRANDMA)

While this system indeed exhibits the desired flow:

  grandma -> mom -> daughter -> mom -> grandma -> EXIT

It is also certainly a brittle arrangement.  MOM always goes back to
GRANDMA, for example.  But in real programs, sometimes GRANDPA wants
to switch to MOM also, and still get control back afterwards (rather
than always giving it over, indirectly, to GRANDMA).

You can perfectly well add this flexibility.  It's just a matter of
yielding to "the procedure who passed me control" rather than to some
hardcoded next procedure.  Well, to know that info, you have to store
it somewhere.  Like, say, in 'cargo'.  For example:

  from __future__ import generators
  cargo = CargoClass()
  def grandma():
      cargo.MOM_CALLER.append(GRANDMA)
      yield MOM
  def grandpa():
      cargo.MOM_CALLER.append(GRANDPA)
      yield MOM
  def mom():
      yield DAUGHTER
      next_proc = cargo.MOM_CALLER.pop()
      yield next_proc
  def daughter():
      next_proc = cargo.DAUGHTER_CALLER.pop()
      yield next_proc
  GRANDMA, GRANDPA, MOM, DAUGHTER = grandma(), grandpa(), mom(),
daughter()
  if prefers_grandpa:
      scheduler(GRANDPA)
  else:
      scheduler(GRANDMA)

Since 'cargo' is now a mutable global, I don't bother passing it
around anymore.  Implementation of CargoClass() is left as an
exercise.  I'm sure you can make some convenience functions to
simplify the code, if you wish.

Yours, David...



More information about the Python-list mailing list