[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