Microthreads without Stackless?
David Pokorny
davebrok at soda.csua.berkeley.edu
Tue Sep 21 02:55:49 EDT 2004
"Bryan Olson":
> Michael Sparks:
> > [Try Greenlets]
> Finally, I think I understand the kind of stack-conjuring
> required to make coroutines work, and it's well outside standard
> Python's documented extension API. I've been burned on that
> kind of thing before.
Before sending people off to greenlets, I'm starting to understand why you
have to go check them out via CVS---they are somewhat dangerous in their
current form. Fortunately, they come with a test that illustrates the
problem (as long as you compile Python in debug mode, but everyone does
that, right ;). To get a handle on what is going on here, the following
"test5" will leak, but calling "test5('noleak')" will not. I haven't the
foggiest idea why, and gc.collect() cleans up some but not all of the
excess.
David Pokorny
P.S. is this a subtle bug or what? BTW the code included here is a slight
modification of that given in the greenlets folder. Subclassing greenlets
killed my python---this is another mystery. Now I'm getting visions of
envious Wizard-of-Oz-munchkin-proletariats hacking away at a giant snake.
Time for bed.
-----------------------------
class genlet:
def __iter__(self):
return self
def __init__(self,fn,args,kwargs):
self.gl = greenlet.greenlet(fn,args,kwargs)
def next(self):
self.gl.parent = greenlet.getcurrent()
result = self.gl.switch()
if self.gl:
return result
else:
raise StopIteration
def Yield(value):
h = greenlet.getcurrent()
h.parent.switch(value)
def generator(fn): #not used in this example
def runner(*args, **kwds):
return genlet(fn, args, kwds)
return runner
# ____________________________________________________________
#After running test5(), It turns out that frames of g
#have frame->f_back == frame (such frames are found in
#sys.getobjects(20)). Programs that leave
#data in local variables will leak furiously.
#Apparently gc.collect() doesn't want to clean it up.
def g(n):
for i in range(n):
Yield(i)
return None
def test5(kind='leak'):
def runner(*args, **kwds):
x = genlet(g,args,kwds)
return x
if(kind == 'leak'):
iteration = runner(10) #<--leaks!
else:
iteration = genlet(g,(10,),{}) #<--does not leak.
for j in iteration:
print j
iteration = None
return None
More information about the Python-list
mailing list