[pypy-svn] r22651 - in pypy/dist/pypy/module/stackless: . test

tismer at codespeak.net tismer at codespeak.net
Wed Jan 25 16:07:27 CET 2006


Author: tismer
Date: Wed Jan 25 16:07:21 2006
New Revision: 22651

Added:
   pypy/dist/pypy/module/stackless/   (props changed)
   pypy/dist/pypy/module/stackless/__init__.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/interp_coroutine.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/interp_stackless.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/test/   (props changed)
   pypy/dist/pypy/module/stackless/test/__init__.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/test/test_coroutine.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/test/test_stackless.py   (contents, props changed)
Log:
starting to expose coroutines at application level, providing the building blocks for greenlets and tasklets and whatsoever

Added: pypy/dist/pypy/module/stackless/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/__init__.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,15 @@
+# Package initialisation
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+    """
+    This module implements Stackless for applications.
+    """
+
+    appleveldefs = {
+    }
+
+    interpleveldefs = {
+        'tasklet'    : 'interp_stackless.tasklet',
+        'Coroutine'  : 'interp_coroutine.AppCoroutine',
+    }

Added: pypy/dist/pypy/module/stackless/interp_coroutine.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/interp_coroutine.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,89 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.argument import Arguments
+from pypy.interpreter.typedef import GetSetProperty, TypeDef
+from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
+from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root
+from pypy.interpreter.error import OperationError
+from pypy.rpython.rarithmetic import intmask
+
+from pypy.rpython.rstack import yield_current_frame_to_caller
+
+import sys
+
+class CoState(object):
+    def __init__(self):
+        self.last = self.current = self.main = Coroutine()
+
+costate = None
+
+class CoroutineDamage(SystemError):
+    pass
+
+class Coroutine(Wrappable):
+
+    def __init__(self):
+        self.frame = None
+        if costate is None:
+            self.parent = self
+        else:
+            self.parent = costate.main
+
+    def bind(self, thunk):
+        if self.frame is not None:
+            raise CoroutineDamage
+        self.frame = self._bind(thunk)
+
+    def _bind(self, thunk):
+        self.parent = costate.current
+        costate.last.frame = yield_current_frame_to_caller()
+        thunk.call()
+        if self.parent.frame is None:
+            self.parent = costate.main
+        return self._update_state(self.parent)
+
+    def switch(self):
+        if self.frame is None:
+            raise CoroutineDamage
+        costate.last.frame = self._update_state(self).switch()
+        # note that last gets updated before assignment!
+
+    def _update_state(new):
+        costate.last, costate.current = costate.current, new
+        frame, new.frame = new.frame, None
+        return frame
+    _update_state = staticmethod(_update_state)
+
+costate = CoState()
+
+
+class _AppThunk(object):
+
+    def __init__(self, space, w_callable, args):
+        self.space = space
+        self.w_func = w_callable
+        self.args = args
+
+    def call(self):
+        self.space.call_args(self.w_func, self.args)
+
+class AppCoroutine(Coroutine):
+
+    def descr_method__new__(space, w_subtype):
+        co = space.allocate_instance(AppCoroutine, w_subtype)
+        AppCoroutine.__init__(co)
+        co.space = space
+        return space.wrap(co)
+
+    def w_bind(self, w_func, __args__):
+        thunk = _AppThunk(self.space, w_func, __args__)
+        self.bind(thunk)
+
+    def w_switch(self):
+        self.switch()
+
+AppCoroutine.typedef = TypeDef("Coroutine",
+    __new__ = interp2app(AppCoroutine.descr_method__new__.im_func),
+    bind = interp2app(AppCoroutine.w_bind,
+                      unwrap_spec=['self', W_Root, Arguments]),
+    switch = interp2app(AppCoroutine.w_switch),
+)

Added: pypy/dist/pypy/module/stackless/interp_stackless.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/interp_stackless.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,31 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import GetSetProperty, TypeDef
+from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
+from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root
+from pypy.interpreter.error import OperationError
+from pypy.rpython.rarithmetic import intmask
+import os
+
+
+class tasklet(Wrappable):
+
+    def __init__(self, space):
+        self.space = space
+        self.flags = 0
+        self.state = None
+
+    def descr_method__new__(space, w_subtype):
+        t = space.allocate_instance(tasklet, w_subtype)
+        tasklet.__init__(t, space)
+        return space.wrap(t)
+
+    def w_demo(self):
+        output("42")
+
+tasklet.typedef = TypeDef("tasklet",
+    __new__ = interp2app(tasklet.descr_method__new__.im_func),
+    demo = interp2app(tasklet.w_demo),
+)
+
+def output(stuff):
+    os.write(2, stuff + '\n')

Added: pypy/dist/pypy/module/stackless/test/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/__init__.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,18 @@
+# Package initialisation
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+    """
+    This module implements marshal at interpreter level.
+    """
+
+    appleveldefs = {
+    }
+    
+    interpleveldefs = {
+        'dump'    : 'interp_marshal.dump',
+        'dumps'   : 'interp_marshal.dumps',
+        'load'    : 'interp_marshal.load',
+        'loads'   : 'interp_marshal.loads',
+        'version' : 'space.wrap(interp_marshal.Py_MARSHAL_VERSION)',
+    }

Added: pypy/dist/pypy/module/stackless/test/test_coroutine.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/test_coroutine.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,13 @@
+from pypy.conftest import gettestobjspace
+
+class AppTest_Coroutine:
+
+    def setup_class(cls):
+        space = gettestobjspace(usemodules=('stackless',))
+        cls.space = space
+
+    def test_one(self):
+        import stackless
+        print stackless.__file__
+        co = stackless.Coroutine()
+        print co

Added: pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,169 @@
+"""
+testing coroutines at interprepter level
+"""
+
+import os
+from pypy.module.stackless.interp_coroutine import costate, Coroutine
+
+def wrap_stackless_function(fn):
+    from pypy.translator.translator import TranslationContext
+    from pypy.translator.c.genc import CStandaloneBuilder
+    from pypy.annotation.model import SomeList, SomeString
+    from pypy.annotation.listdef import ListDef
+    from pypy.translator.backendopt.all import backend_optimizations
+
+    def entry_point(argv):
+        os.write(1, str(fn()))
+        return 0
+
+    s_list_of_strings = SomeList(ListDef(None, SomeString()))
+    s_list_of_strings.listdef.resize()
+    t = TranslationContext()
+    t.buildannotator().build_types(entry_point, [s_list_of_strings])
+    #t.view()
+    t.buildrtyper().specialize()
+    backend_optimizations(t)
+    cbuilder = CStandaloneBuilder(t, entry_point)
+    cbuilder.stackless = True
+    cbuilder.generate_source()
+    cbuilder.compile()
+    return cbuilder.cmdexec('')
+
+
+def output(stuff):
+    os.write(2, stuff + '\n')
+
+def test_coroutine():
+    
+    def g(lst, coros):
+        coro_f, coro_g, coro_h = coros
+        lst.append(2)
+        output('g appended 2')
+        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, arg1, arg2):
+            self.func = func
+            self.arg1 = arg1
+            self.arg2 = arg2
+        def call(self):
+            self.func(self.arg1, self.arg2)
+
+    def f():
+        lst = [1]
+        coro_f = costate.main
+        coro_g = Coroutine()
+        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(4)
+        output('f appended 4')
+        coro_g.switch()
+        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()) == 12345678
+
+def test_coroutine2():
+
+    class TBase:
+        def call(self):
+            pass
+        
+    class T(TBase):
+        def __init__(self, func, arg1, arg2):
+            self.func = func
+            self.arg1 = arg1
+            self.arg2 = arg2
+        def call(self):
+            self.res = self.func(self.arg1, self.arg2)
+
+    class T1(TBase):
+        def __init__(self, func, arg1):
+            self.func = func
+            self.arg1 = arg1
+        def call(self):
+            self.res = self.func(self.arg1)
+
+    def g(lst, coros):
+        coro_f1, coro_g, coro_h = coros
+        lst.append(2)
+        output('g appended 2')
+        coro_h.switch()
+        lst.append(5)
+        output('g appended 5')
+        output('exiting g')
+        
+    def h(lst, coros):
+        coro_f1, coro_g, coro_h = coros
+        lst.append(3)
+        output('h appended 3')
+        coro_f1.switch()
+        lst.append(7)
+        output('h appended 7')
+        output('exiting h')
+
+    def f1(coro_f1):
+        lst = [1]
+        coro_g = Coroutine()
+        coro_h = Coroutine()
+        coros = [coro_f1, coro_g, coro_h]
+        thunk_g = T(g, lst, coros)
+        output('binding g after f1 set 1')
+        coro_g.bind(thunk_g)
+        thunk_h = T(h, lst, coros)
+        output('binding h after f1 set 1')
+        coro_h.bind(thunk_h)
+        output('switching to g')
+        coro_g.switch()
+        lst.append(4)
+        output('f1 appended 4')
+        coro_g.switch()
+        lst.append(6)
+        output('f1 appended 6')
+        coro_h.switch()
+        lst.append(8)
+        output('f1 appended 8')
+        n = 0
+        for i in lst:
+            n = n*10 + i
+        output('exiting f1')
+        return n     
+
+    def f():
+        coro_f = costate.main
+        coro_f1 = Coroutine()
+        thunk_f1 = T1(f1, coro_f1)
+        output('binding f1 after f set 1')
+        coro_f1.bind(thunk_f1)
+        coro_f1.switch()        
+        output('return to main :-(')
+        return thunk_f1.res
+        
+    data = wrap_stackless_function(f)
+    assert int(data.strip()) == 12345678

Added: pypy/dist/pypy/module/stackless/test/test_stackless.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/test_stackless.py	Wed Jan 25 16:07:21 2006
@@ -0,0 +1,21 @@
+from pypy.conftest import gettestobjspace
+
+class AppTest_Stackless:
+
+    def setup_class(cls):
+        space = gettestobjspace(usemodules=('stackless',))
+        cls.space = space
+
+    def test_one(self):
+        import stackless
+        print stackless.__file__
+        t = stackless.tasklet()
+        t.demo()
+        class A(stackless.tasklet):
+            def __init__(self, name):
+                self.name = name
+            def __new__(subtype, *args):
+                return stackless.tasklet.__new__(subtype)
+        x = A("heinz")
+        x.demo()
+        print x.name



More information about the Pypy-commit mailing list