[pypy-svn] r21317 - pypy/dist/pypy/translator/c/test

tismer at codespeak.net tismer at codespeak.net
Mon Dec 19 17:34:12 CET 2005


Author: tismer
Date: Mon Dec 19 17:34:11 2005
New Revision: 21317

Modified:
   pypy/dist/pypy/translator/c/test/test_coroutine.py
Log:
a minimalist coroutine implementation which seems to work fine.
We explicitly avoid to put anything into the coro structure than a single
continuation. Anything else can be added via Greenlets, Tasklets, ...
Note that it is also not necessary to store a callable - it is passed in to bind()
as a thunk object.

Modified: pypy/dist/pypy/translator/c/test/test_coroutine.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_coroutine.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_coroutine.py	Mon Dec 19 17:34:11 2005
@@ -1,21 +1,7 @@
 """
-Hi Armin:
-When I set DEBUG to False, the program crashes. Maybe I'm doing something
-wrong and re-using some used continuation, don't know.
-So I was trying to set things to Nonw after becoming invalid, but
-that breaks the rtyper.
+minimalistic coroutine implementation
 """
 
-DEBUG = False
-# set to true and compilation crashes
-USE_NONE = False
-# set to true and rtyper crashes
-
-# the above are exclusive right now
-
-CHECKED_IN = True
-# set this to false to skip skipping :-)
-
 import os
 from pypy.rpython.rstack import yield_current_frame_to_caller
 
@@ -67,7 +53,7 @@
 caller of the current function. This frame serves as the
 entry point to the coroutine.
 
-On evetry entry to the coroutine, the return value of the
+On every entry to the coroutine, the return value of the
 point where we left off is the continuation of the caller.
 We need to update the caller's frame with it.
 This is not necessarily the caller which created ourself.
@@ -92,96 +78,85 @@
 
 class Coroutine(object):
 
-    if DEBUG:
-        def __init__(self):
-            self._switchable = False
-
-    if USE_NONE:
-        def __init__(self):
-            self.frame = None
+    def __init__(self):
+        self.frame = None
 
     def bind(self, thunk):
-        if USE_NONE:
-            assert self.frame is None
+        if self.frame is not None:
+            raise CoroutineDamage
         self.frame = self._bind(thunk)
 
     def _bind(self, thunk):
-        if self is costate.current or self is costate.main:
-            raise CoroutineDamage
-        frame = yield_current_frame_to_caller()
-        costate.current.frame = frame
-        if DEBUG:
-            costate.current.switchable = True
-            assert self._switchable == True
-            self._switchable = False
-        costate.current = self
+        costate.last.frame = yield_current_frame_to_caller()
         thunk.call()
-        return self.frame # just for the annotator
+        costate.last, costate.current = costate.current, costate.main
+        frame, costate.main.frame = costate.main.frame, None
+        return frame
 
     def switch(self):
-        if DEBUG:
-            assert self._switchable == True
-            assert costate.current._switchable == False
-        if USE_NONE:
-            assert costate.current.frame is None
-            assert self.frame is not None
-        frame = self.frame.switch()
-        if DEBUG:
-            assert costate.current._switchable == False
-            costate.current._switchable = True
-        if USE_NONE:
-            assert costate.current.frame is None
-        costate.current.frame = frame
-        costate.current = self
-        # XXX support: self.frame = None
+        if self.frame is None:
+            raise CoroutineDamage
+        costate.last, costate.current = costate.current, self
+        frame, self.frame = self.frame, None
+        costate.last.frame = frame.switch()
 
-costate.current = costate.main = Coroutine()
+costate.current = costate.last = costate.main = Coroutine()
 
 def output(stuff):
     os.write(2, stuff + '\n')
 
 def test_coroutine():
-    if CHECKED_IN:
-        import py.test
-        py.test.skip("in-progress")
     
-    def g(lst):
+    def g(lst, coros):
+        coro_f, coro_g, coro_h = coros
         lst.append(2)
         output('g appended 2')
-        costate.main.switch()
-        lst.append(4)
-        output('g appended 4')
-        costate.main.switch()
-        lst.append(6)
-        output('g appended 6')
+        coro_h.switch()
+        lst.append(5)
+        output('g appended 5')
+
+    def h(lst, coros):
+        coro_f, coro_g, coro_h = coros
+        lst.append(3)
+        output('h appended 3')
+        coro_f.switch()
+        lst.append(7)
+        output('h appended 7')
 
     class T:
-        def __init__(self, func, arg):
+        def __init__(self, func, arg1, arg2):
             self.func = func
-            self.arg = arg
+            self.arg1 = arg1
+            self.arg2 = arg2
         def call(self):
-            self.func(self.arg)
+            self.func(self.arg1, self.arg2)
 
     def f():
         lst = [1]
+        coro_f = costate.main
         coro_g = Coroutine()
-        t = T(g, lst)
-        output('binding after f set 1')
-        coro_g.bind(t)
-        output('switching')
-        coro_g.switch()
-        lst.append(3)
-        output('f appended 3')
+        coro_h = Coroutine()
+        coros = [coro_f, coro_g, coro_h]
+        thunk_g = T(g, lst, coros)
+        output('binding g after f set 1')
+        coro_g.bind(thunk_g)
+        thunk_h = T(h, lst, coros)
+        output('binding h after f set 1')
+        coro_h.bind(thunk_h)
+        output('switching to g')
         coro_g.switch()
-        lst.append(5)
-        output('f appended 5')
+        lst.append(4)
+        output('f appended 4')
         coro_g.switch()
-        lst.append(7)
-        output('f appended 7')
+        lst.append(6)
+        output('f appended 6')
+        coro_h.switch()
+        lst.append(8)
+        output('f appended 8')
         n = 0
         for i in lst:
             n = n*10 + i
         return n
 
     data = wrap_stackless_function(f)
-    assert int(data.strip()) == 1234567
+    assert int(data.strip()) == 12345678



More information about the Pypy-commit mailing list