[pypy-svn] r28597 - in pypy/dist/pypy/module/stackless: . test
tismer at codespeak.net
tismer at codespeak.net
Fri Jun 9 19:25:16 CEST 2006
Author: tismer
Date: Fri Jun 9 19:25:15 2006
New Revision: 28597
Modified:
pypy/dist/pypy/module/stackless/interp_coroutine.py
pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py
Log:
WAAAAAAHHHH now coroutines seem to work on top of CPython
Modified: pypy/dist/pypy/module/stackless/interp_coroutine.py
==============================================================================
--- pypy/dist/pypy/module/stackless/interp_coroutine.py (original)
+++ pypy/dist/pypy/module/stackless/interp_coroutine.py Fri Jun 9 19:25:15 2006
@@ -36,35 +36,46 @@
try:
from py.magic import greenlet
main_greenlet = greenlet.getcurrent()
- class MyGreenlet(object):
- def __init__(self, thunk=None, curr=False):
- if curr:
- self.greenlet = greenlet.getcurrent()
- else:
+
+ class FrameChain(object):
+
+ def __init__(self, thunk=None):
+ if thunk:
self.greenlet = greenlet(thunk)
+ else:
+ self.greenlet = greenlet.getcurrent()
+
def switch(self):
- last = MyGreenlet(curr=True)
-# XXX unclear what to do there
-# self.greenlet.parent = greenlet.getcurrent()
+ last = FrameChain()
return self.greenlet.switch(last)
- GreenletExit = greenlet.GreenletExit
+
+ def shutdown(self):
+ current = FrameChain()
+ target = current.greenlet.parent
+ target.switch(None)
+
except ImportError:
def greenlet(*args, **kwargs):
raise NotImplementedError("need either greenlets or a translated version of pypy")
- class GreenletExit(Exception):
- pass
import sys, os
+
class BaseCoState(object):
def __init__(self):
self.current = self.main = self.last = None
+ def __repr__(self):
+ "NOT_RPYTHON"
+ # for debugging only
+ return '<%s last=%r current=%r>' % (self.__class__.__name__,
+ self.last, self.current)
def update(self, new):
self.last, self.current = self.current, new
frame, new.frame = new.frame, None
return frame
+
class CoState(BaseCoState):
def __init__(self):
BaseCoState.__init__(self)
@@ -78,18 +89,20 @@
check_for_zombie = staticmethod(check_for_zombie)
def postpone_deletion(obj):
- main_coroutine_getter._get_default_costate().to_delete.append(obj)
- main_coroutine_getter._get_default_costate().things_to_do = True
+ main_costate = main_costate_getter._get_default_costate()
+ main_costate.to_delete.append(obj)
+ main_costate.things_to_do = True
postpone_deletion = staticmethod(postpone_deletion)
def do_things_to_do():
# inlineable stub
- if main_coroutine_getter._get_default_costate().things_to_do:
- main_coroutine_getter._get_default_costate()._do_things_to_do()
+ main_costate = main_costate_getter._get_default_costate()
+ if main_costate.things_to_do:
+ main_costate._do_things_to_do()
do_things_to_do = staticmethod(do_things_to_do)
def _do_things_to_do():
- main_costate = main_coroutine_getter._get_default_costate()
+ main_costate = main_costate_getter._get_default_costate()
if main_costate.temp_exc is not None:
# somebody left an unhandled exception and switched to us.
# this both provides default exception handling and the
@@ -110,7 +123,8 @@
class CoroutineDamage(SystemError):
pass
-class MainCoroutineGetter(object):
+
+class MainCostateGetter(object):
def __init__(self):
self.costate = None
def _get_default_costate(self):
@@ -119,34 +133,39 @@
self.costate = costate
return costate
return self.costate
-
-main_coroutine_getter = MainCoroutineGetter()
+
+main_costate_getter = MainCostateGetter()
+
class CoroutineExit(SystemExit):
# XXX SystemExit's __init__ creates problems in bookkeeper.
def __init__(self):
pass
-def get_exit_class(): # XXX hum
- if we_are_translated():
- return CoroutineExit
- else:
- return GreenletExit
-
class AbstractThunk(object):
def call(self):
raise NotImplementedError("abstract base class")
+
class Coroutine(Wrappable):
def __init__(self, state=None):
self.frame = None
if state is None:
- state = main_coroutine_getter._get_default_costate()
+ state = main_costate_getter._get_default_costate()
self.costate = state
self.parent = None
+ self.thunk = None
+
+ def __repr__(self):
+ 'NOT_RPYTHON'
+ # just for debugging
+ if hasattr(self, '__name__'):
+ return '<Coro %s frame=%r %s>' % (self.__name__, self.frame, self.thunk is not None)
+ else:
+ return '<coro frame=%r %s>' % (self.frame, self.thunk is not None)
def _get_default_parent(self):
- return main_coroutine_getter._get_default_costate().current
+ return main_costate_getter._get_default_costate().current
def bind(self, thunk):
assert isinstance(thunk, AbstractThunk)
@@ -155,37 +174,45 @@
if self.parent is None:
self.parent = self._get_default_parent()
assert self.parent is not None
+ self.thunk = thunk
if we_are_translated():
- self.frame = self._bind(thunk)
+ self.frame = self._bind()
else:
- self.frame = self._greenlet_bind(thunk)
+ self.frame = self._greenlet_bind()
- def _greenlet_bind(self, thunk):
+ def _greenlet_bind(self):
state = self.costate
self.parent = state.current
assert self.parent is not None
+ weak = [self]
def _greenlet_execute(incoming_frame):
- return self._execute(thunk, state, incoming_frame)
- return MyGreenlet(_greenlet_execute)
+ try:
+ return weak[0]._execute(incoming_frame)
+ finally:
+ del weak[0]
+ chain.shutdown()
+ chain = FrameChain(_greenlet_execute)
+ return chain
- def _bind(self, thunk):
+ def _bind(self):
state = self.costate
self.parent = state.current
incoming_frame = yield_current_frame_to_caller()
- return self._execute(thunk, state, incoming_frame)
+ return self._execute(incoming_frame)
- def _execute(self, thunk, state, incoming_frame):
+ def _execute(self, incoming_frame):
+ state = self.costate
left = state.last
left.frame = incoming_frame
left.goodbye()
self.hello()
try:
- main_coroutine_getter._get_default_costate().do_things_to_do()
- thunk.call()
+ main_costate_getter._get_default_costate().do_things_to_do()
+ try:
+ self.thunk.call()
+ finally:
+ self.thunk = None
resume_point("coroutine__bind", self, state)
- except GreenletExit:
- # ignore a shutdown exception
- pass
except CoroutineExit:
# ignore a shutdown exception
pass
@@ -210,13 +237,13 @@
left.frame = incoming_frame
left.goodbye()
self.hello()
- main_coroutine_getter._get_default_costate().do_things_to_do()
+ main_costate_getter._get_default_costate().do_things_to_do()
def kill(self):
if self.frame is None:
return
- main_coroutine_getter._get_default_costate().things_to_do = True
- main_coroutine_getter._get_default_costate().temp_exc = get_exit_class()()
+ main_costate_getter._get_default_costate().things_to_do = True
+ main_costate_getter._get_default_costate().temp_exc = CoroutineExit()
state = self.costate
self.parent = state.current
self.switch()
@@ -228,7 +255,7 @@
pass # maybe print a warning?
self.kill()
- def X__del__(self):
+ def __del__(self):
# provide the necessary clean-up if this coro is left
# with a frame.
# note that AppCoroutine has to take care about this
@@ -237,7 +264,7 @@
# not in the position to issue a switch.
# we defer it completely.
if self.frame is not None:
- main_coroutine_getter._get_default_costate().postpone_deletion(self)
+ main_costate_getter._get_default_costate().postpone_deletion(self)
def _userdel(self):
# override this for exposed coros
@@ -247,14 +274,14 @@
return self.frame is not None or self is self.costate.current
def is_zombie(self):
- return self.frame is not None and main_coroutine_getter._get_default_costate().check_for_zombie(self)
+ return self.frame is not None and main_costate_getter._get_default_costate().check_for_zombie(self)
def getcurrent():
- return main_coroutine_getter._get_default_costate().current
+ return main_costate_getter._get_default_costate().current
getcurrent = staticmethod(getcurrent)
def getmain():
- return main_coroutine_getter._get_default_costate().main
+ return main_costate_getter._get_default_costate().main
getmain = staticmethod(getmain)
def hello(self):
Modified: pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py (original)
+++ pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py Fri Jun 9 19:25:15 2006
@@ -3,27 +3,27 @@
"""
import os
-from pypy.module.stackless.interp_coroutine import main_coroutine_getter, Coroutine, AbstractThunk
+from pypy.module.stackless.interp_coroutine import main_costate_getter, Coroutine, AbstractThunk
from pypy.translator.c.test.test_stackless import StacklessTest
from pypy.translator.c import gc
def output(stuff):
os.write(2, stuff + '\n')
-class TestCoroutine(StacklessTest):
+class _TestCoroutine(StacklessTest):
backendopt = True
stacklessmode = True
gcpolicy = gc.BoehmGcPolicy
Coroutine = Coroutine
def setup_method(self, method):
- main_coroutine_getter.costate = None
- main_coroutine_getter.costate = None
+ main_costate_getter.costate = None
+ main_costate_getter.costate = None
def _freeze_(self): # for 'self.Coroutine'
return True
- def test_coroutine(self):
+ def test_coroutine1(self):
def g(lst, coros):
coro_f, coro_g, coro_h = coros
@@ -121,7 +121,9 @@
def f1(coro_f1):
lst = [1]
coro_g = self.Coroutine()
+ coro_g.__name__ = 'coro_g'
coro_h = self.Coroutine()
+ coro_h.__name__ = 'coro_h'
coros = [coro_f1, coro_g, coro_h]
thunk_g = T(g, lst, coros)
output('binding g after f1 set 1')
@@ -147,11 +149,13 @@
def f():
coro_f = Coroutine.getcurrent()
+ coro_f.__name__ = 'coro_f'
coro_f1 = self.Coroutine()
+ coro_f1.__name__ = 'coro_f1'
thunk_f1 = T1(f1, coro_f1)
output('binding f1 after f set 1')
coro_f1.bind(thunk_f1)
- coro_f1.switch()
+ coro_f1.switch()
output('return to main :-(')
return thunk_f1.res
@@ -159,7 +163,6 @@
assert data == 12345678
def test_kill_raise_del_coro(self):
- py.test.skip("does not work :-(")
class T(AbstractThunk):
def __init__(self, func, arg):
self.func = func
@@ -178,6 +181,7 @@
def f():
assert Coroutine.getmain().frame is None
coro_g = self.Coroutine()
+ coro_g.__name__ = 'coro_g'
thunk_g = T(g, 42)
coro_g.bind(thunk_g)
coro_g.switch()
@@ -189,6 +193,7 @@
res *= 10
res |= coro_g.frame is None
coro_g = self.Coroutine()
+ # see what happens if we __del__
thunk_g = T(g, -42)
coro_g.bind(thunk_g)
try:
@@ -273,7 +278,8 @@
output = self.wrap_stackless_function(ep)
assert output == int('0110')
-class TestCoroutineOnCPython(TestCoroutine):
+TestCoroutine = _TestCoroutine # to activate
+class TestCoroutineOnCPython(_TestCoroutine):
def wrap_stackless_function(self, func):
return func()
More information about the Pypy-commit
mailing list