[pypy-commit] pypy stacklet: Use _continuation.permute() at the end of _greenlet_start()
arigo
noreply at buildbot.pypy.org
Sat Aug 20 11:18:25 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: stacklet
Changeset: r46660:577ea1cac4e2
Date: 2011-08-20 09:43 +0200
http://bitbucket.org/pypy/pypy/changeset/577ea1cac4e2/
Log: Use _continuation.permute() at the end of _greenlet_start() in order
to put the parent's continuation in place. It is enough to
implement parents without giving up on the model that greenlet
objects, as continulets, are not nested.
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -34,9 +34,12 @@
__main = False
__started = False
- def __init__(self, run=None):
+ def __init__(self, run=None, parent=None):
if run is not None:
self.run = run
+ if parent is None:
+ parent = getcurrent()
+ self.parent = parent
def switch(self, *args):
"Switch execution to this greenlet, optionally passing the values "
@@ -92,14 +95,6 @@
def dead(self):
return self.__started and not self
- @property
- def parent(self):
- # Don't support nesting for now.
- if self.__main:
- return None
- else:
- return _tls.main
-
# ____________________________________________________________
# Internal stuff
@@ -116,10 +111,15 @@
gmain = greenlet.__new__(greenlet)
gmain._greenlet__main = True
gmain._greenlet__started = True
+ gmain.parent = None
_tls.main = gmain
_tls.current = gmain
def _greenlet_start(greenlet, args):
_tls.current = greenlet
- res = greenlet.run(*args)
+ try:
+ res = greenlet.run(*args)
+ finally:
+ if greenlet.parent is not _tls.main:
+ _continuation.permute(greenlet, greenlet.parent)
return (res,)
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
@@ -133,3 +133,54 @@
g2.switch()
res = g1.switch()
assert res == "ok"
+
+ def test_nondefault_parent(self):
+ from greenlet import greenlet
+ gmain = greenlet.getcurrent()
+ #
+ def f1():
+ g2 = greenlet(f2)
+ res = g2.switch()
+ assert res == "from 2"
+ return "from 1"
+ #
+ def f2():
+ return "from 2"
+ #
+ g1 = greenlet(f1)
+ res = g1.switch()
+ assert res == "from 1"
+
+ def test_change_parent(self):
+ from greenlet import greenlet
+ gmain = greenlet.getcurrent()
+ #
+ def f1():
+ res = g2.switch()
+ assert res == "from 2"
+ return "from 1"
+ #
+ def f2():
+ return "from 2"
+ #
+ g1 = greenlet(f1)
+ g2 = greenlet(f2)
+ g2.parent = g1
+ res = g1.switch()
+ assert res == "from 1"
+
+ def test_raises_through_parent_chain(self):
+ from greenlet import greenlet
+ gmain = greenlet.getcurrent()
+ #
+ def f1():
+ raises(IndexError, g2.switch)
+ raise ValueError
+ #
+ def f2():
+ raise IndexError
+ #
+ g1 = greenlet(f1)
+ g2 = greenlet(f2)
+ g2.parent = g1
+ raises(ValueError, g1.switch)
More information about the pypy-commit
mailing list