[pypy-commit] pypy stacklet: Finish the emulation; now it should support all cases supported
arigo
noreply at buildbot.pypy.org
Sat Aug 20 11:18:26 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: stacklet
Changeset: r46661:2824b0cd4078
Date: 2011-08-20 09:59 +0200
http://bitbucket.org/pypy/pypy/changeset/2824b0cd4078/
Log: Finish the emulation; now it should support all cases supported by
greenlet.c for CPython.
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -50,17 +50,20 @@
"raise exception in greenlet, return value passed when switching back"
return self.__switch(_continulet.throw, typ, val, tb)
- def __switch(self, unbound_method, *args):
+ def __switch(target, unbound_method, *args):
current = getcurrent()
- target = self
- if not target:
+ #
+ while not target:
if not target.__started:
_continulet.__init__(target, _greenlet_start, *args)
args = ()
target.__started = True
- else:
- # already done, go to main instead... xxx later
- raise error("greenlet execution already finished")
+ break
+ # already done, go to the parent instead
+ # (NB. infinite loop possible, but unlikely, unless you mess
+ # up the 'parent' explicitly. Good enough, because a Ctrl-C
+ # will show that the program is caught in this loop here.)
+ target = target.parent
#
try:
if current.__main:
@@ -68,6 +71,7 @@
# switch from main to main
if unbound_method == _continulet.throw:
raise args[0], args[1], args[2]
+ (args,) = args
else:
# enter from main to target
args = unbound_method(target, *args)
@@ -95,6 +99,10 @@
def dead(self):
return self.__started and not self
+ @property
+ def gr_frame(self):
+ raise NotImplementedError("attribute 'gr_frame' of greenlet objects")
+
# ____________________________________________________________
# Internal stuff
diff --git a/pypy/module/test_lib_pypy/test_greenlet.py b/pypy/module/test_lib_pypy/test_greenlet.py
--- a/pypy/module/test_lib_pypy/test_greenlet.py
+++ b/pypy/module/test_lib_pypy/test_greenlet.py
@@ -136,7 +136,6 @@
def test_nondefault_parent(self):
from greenlet import greenlet
- gmain = greenlet.getcurrent()
#
def f1():
g2 = greenlet(f2)
@@ -153,7 +152,6 @@
def test_change_parent(self):
from greenlet import greenlet
- gmain = greenlet.getcurrent()
#
def f1():
res = g2.switch()
@@ -171,7 +169,6 @@
def test_raises_through_parent_chain(self):
from greenlet import greenlet
- gmain = greenlet.getcurrent()
#
def f1():
raises(IndexError, g2.switch)
@@ -184,3 +181,53 @@
g2 = greenlet(f2)
g2.parent = g1
raises(ValueError, g1.switch)
+
+ def test_switch_to_dead_1(self):
+ from greenlet import greenlet
+ #
+ def f1():
+ return "ok"
+ #
+ g1 = greenlet(f1)
+ res = g1.switch()
+ assert res == "ok"
+ res = g1.switch("goes to gmain instead")
+ assert res == "goes to gmain instead"
+
+ def test_switch_to_dead_2(self):
+ from greenlet import greenlet
+ #
+ def f1():
+ g2 = greenlet(f2)
+ return g2.switch()
+ #
+ def f2():
+ return "ok"
+ #
+ g1 = greenlet(f1)
+ res = g1.switch()
+ assert res == "ok"
+ res = g1.switch("goes to gmain instead")
+ assert res == "goes to gmain instead"
+
+ def test_switch_to_dead_3(self):
+ from greenlet import greenlet
+ gmain = greenlet.getcurrent()
+ #
+ def f1():
+ res = g2.switch()
+ assert res == "ok"
+ res = gmain.switch("next step")
+ assert res == "goes to f1 instead"
+ return "all ok"
+ #
+ def f2():
+ return "ok"
+ #
+ g1 = greenlet(f1)
+ g2 = greenlet(f2)
+ g2.parent = g1
+ res = g1.switch()
+ assert res == "next step"
+ res = g2.switch("goes to f1 instead")
+ assert res == "all ok"
More information about the pypy-commit
mailing list