[pypy-commit] pypy stacklet: Implement switch(to=x).

arigo noreply at buildbot.pypy.org
Thu Aug 18 16:35:12 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: stacklet
Changeset: r46606:55a35a42eeca
Date: 2011-08-18 16:39 +0200
http://bitbucket.org/pypy/pypy/changeset/55a35a42eeca/

Log:	Implement switch(to=x).

diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -54,30 +54,27 @@
         if self.sthread.is_empty_handle(self.h):
             raise geterror(self.space, "continulet already finished")
         ec = self.check_sthread()
+        if self is to:    # double-switch to myself: no-op
+            return w_value
         saved_topframeref = ec.topframeref
         start_state.w_value = w_value
         #
+        start_state.origin = self
         if to is None:
-            start_state.origin = None
-            h = self.h      # simple switch: going to self.h
+            # simple switch: going to self.h
+            start_state.destination = self
         else:
-            start_state.origin = self
-            h = to.h        # double switch: the final destination is to.h
+            # double switch: the final destination is to.h
+            start_state.destination = to
         #
         try:
-            h = self.sthread.switch(h)
+            sthread = self.sthread
+            do_switch(sthread, start_state.destination.h)
         except MemoryError:
             start_state.clear()
             raise getmemoryerror(self.space)
         #
-        origin = start_state.origin
-        if origin is not None:
-            # double switch ('self' is now the final destination)
-            start_state.origin = None
-            h, origin.h = origin.h, h
-        self.h = h
-        #
-        ec = self.sthread.ec
+        ec = sthread.ec
         ec.topframeref = saved_topframeref
         if start_state.propagate_exception:
             e = start_state.propagate_exception
@@ -145,6 +142,7 @@
 class StartState:   # xxx a single global to pass around the function to start
     def clear(self):
         self.origin = None
+        self.destination = None
         self.w_callable = None
         self.args = None
         self.w_value = None
@@ -159,7 +157,7 @@
     args       = start_state.args
     start_state.clear()
     try:
-        self.h = self.sthread.switch(h)
+        do_switch(self.sthread, h)
     except MemoryError:
         return h       # oups!  do an early return in this case
     #
@@ -176,11 +174,21 @@
             raise OperationError(space.w_TypeError, space.wrap(
                 "can't send non-None value to a just-started continulet"))
 
-        args = args.prepend(space.wrap(self))
+        args = args.prepend(self.space.wrap(self))
         w_result = space.call_args(w_callable, args)
     except Exception, e:
         start_state.propagate_exception = e
-        return self.h
     else:
         start_state.w_value = w_result
-        return self.h
+    start_state.origin = self
+    start_state.destination = self
+    return self.h
+
+
+def do_switch(sthread, h):
+    h = sthread.switch(h)
+    origin = start_state.origin
+    self = start_state.destination
+    start_state.origin = None
+    start_state.destination = None
+    self.h, origin.h = origin.h, h
diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py
--- a/pypy/module/_continuation/test/test_stacklet.py
+++ b/pypy/module/_continuation/test/test_stacklet.py
@@ -429,7 +429,7 @@
         c2 = continulet(f2)
         res = c1.switch()
         assert res == 42
-        assert not c2.is_pending()
+        assert not c2.is_pending()    # finished by returning 42
         res = c1.switch('c')
         assert res == 41
 
@@ -449,10 +449,12 @@
         from _continuation import continulet
         #
         def f1(c1):
+            print 'in f1'
             return 'm'
         #
         def f2(c2):
             res = c2.switch('z')
+            print 'got there!'
             assert res == 'a'
             return None
         #
@@ -460,7 +462,11 @@
         c2 = continulet(f2)
         res = c2.switch()
         assert res == 'z'
+        assert c1.is_pending()
+        assert c2.is_pending()
+        print 'calling!'
         res = c1.switch('a', to=c2)
+        print 'back'
         assert res == 'm'
 
     def test_switch2_immediately_away_corner_case(self):


More information about the pypy-commit mailing list