[pypy-svn] r28549 - in pypy/dist/pypy/module/stackless: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Jun 8 18:30:04 CEST 2006
Author: cfbolz
Date: Thu Jun 8 18:30:03 2006
New Revision: 28549
Modified:
pypy/dist/pypy/module/stackless/interp_coroutine.py
pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py
Log:
(tismer, cfbolz): work in progress: make Coroutines run on top py.py, maybe.
there's a bug right now :-(
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 Thu Jun 8 18:30:03 2006
@@ -31,6 +31,28 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.rpython.rstack import yield_current_frame_to_caller, resume_point
+from pypy.rpython.objectmodel import we_are_translated
+
+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:
+ self.greenlet = greenlet(thunk)
+ def switch(self):
+ last = MyGreenlet(curr=True)
+# XXX unclear what to do there
+# self.greenlet.parent = greenlet.getcurrent()
+ return self.greenlet.switch(last)
+ GreenletExit = greenlet.GreenletExit
+except ImportError:
+ def greenlet(*args, **kwargs):
+ raise NotImplementedError("need either greenlets or a translated version of pypy")
+ class GreenletExit(Exception):
+ pass
import sys, os
@@ -56,57 +78,75 @@
check_for_zombie = staticmethod(check_for_zombie)
def postpone_deletion(obj):
- costate.to_delete.append(obj)
- costate.things_to_do = True
+ main_coroutine_getter._get_default_costate().to_delete.append(obj)
+ main_coroutine_getter._get_default_costate().things_to_do = True
postpone_deletion = staticmethod(postpone_deletion)
def do_things_to_do():
# inlineable stub
- if costate.things_to_do:
- costate._do_things_to_do()
+ if main_coroutine_getter._get_default_costate().things_to_do:
+ main_coroutine_getter._get_default_costate()._do_things_to_do()
do_things_to_do = staticmethod(do_things_to_do)
def _do_things_to_do():
- if costate.temp_exc is not None:
+ main_costate = main_coroutine_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
# way to inject an exception, like CoroutineExit.
- e, costate.temp_exc = costate.temp_exc, None
- costate.things_to_do = len(costate.to_delete)
+ e, main_costate.temp_exc = main_costate.temp_exc, None
+ main_costate.things_to_do = len(main_costate.to_delete)
raise e
- while costate.to_delete:
- delete, costate.to_delete = costate.to_delete, []
+ while main_costate.to_delete:
+ delete, main_costate.to_delete = main_costate.to_delete, []
for obj in delete:
obj.parent = obj.costate.current
obj._kill_finally()
else:
- costate.things_to_do = False
+ main_costate.things_to_do = False
_do_things_to_do = staticmethod(_do_things_to_do)
class CoroutineDamage(SystemError):
pass
+class MainCoroutineGetter(object):
+ def __init__(self):
+ self.costate = None
+ def _get_default_costate(self):
+ if self.costate is None:
+ costate = CoState()
+ self.costate = costate
+ return costate
+ return self.costate
+
+main_coroutine_getter = MainCoroutineGetter()
+
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 = costate
+ state = main_coroutine_getter._get_default_costate()
self.costate = state
self.parent = None
def _get_default_parent(self):
- return self.costate.current
+ return main_coroutine_getter._get_default_costate().current
def bind(self, thunk):
assert isinstance(thunk, AbstractThunk)
@@ -114,20 +154,38 @@
raise CoroutineDamage
if self.parent is None:
self.parent = self._get_default_parent()
- self.frame = self._bind(thunk)
+ assert self.parent is not None
+ if we_are_translated():
+ self.frame = self._bind(thunk)
+ else:
+ self.frame = self._greenlet_bind(thunk)
+
+ def _greenlet_bind(self, thunk):
+ state = self.costate
+ self.parent = state.current
+ assert self.parent is not None
+ def _greenlet_execute(incoming_frame):
+ return self._execute(thunk, state, incoming_frame)
+ return MyGreenlet(_greenlet_execute)
def _bind(self, thunk):
state = self.costate
self.parent = state.current
incoming_frame = yield_current_frame_to_caller()
+ return self._execute(thunk, state, incoming_frame)
+
+ def _execute(self, thunk, state, incoming_frame):
left = state.last
left.frame = incoming_frame
left.goodbye()
self.hello()
try:
- costate.do_things_to_do()
+ main_coroutine_getter._get_default_costate().do_things_to_do()
thunk.call()
resume_point("coroutine__bind", self, state)
+ except GreenletExit:
+ # ignore a shutdown exception
+ pass
except CoroutineExit:
# ignore a shutdown exception
pass
@@ -152,13 +210,13 @@
left.frame = incoming_frame
left.goodbye()
self.hello()
- costate.do_things_to_do()
+ main_coroutine_getter._get_default_costate().do_things_to_do()
def kill(self):
if self.frame is None:
return
- costate.things_to_do = True
- costate.temp_exc = CoroutineExit()
+ main_coroutine_getter._get_default_costate().things_to_do = True
+ main_coroutine_getter._get_default_costate().temp_exc = get_exit_class()()
state = self.costate
self.parent = state.current
self.switch()
@@ -170,7 +228,7 @@
pass # maybe print a warning?
self.kill()
- def __del__(self):
+ def X__del__(self):
# provide the necessary clean-up if this coro is left
# with a frame.
# note that AppCoroutine has to take care about this
@@ -179,7 +237,7 @@
# not in the position to issue a switch.
# we defer it completely.
if self.frame is not None:
- costate.postpone_deletion(self)
+ main_coroutine_getter._get_default_costate().postpone_deletion(self)
def _userdel(self):
# override this for exposed coros
@@ -189,19 +247,20 @@
return self.frame is not None or self is self.costate.current
def is_zombie(self):
- return self.frame is not None and costate.check_for_zombie(self)
+ return self.frame is not None and main_coroutine_getter._get_default_costate().check_for_zombie(self)
def getcurrent():
- return costate.current
+ return main_coroutine_getter._get_default_costate().current
getcurrent = staticmethod(getcurrent)
+ def getmain():
+ return main_coroutine_getter._get_default_costate().main
+ getmain = staticmethod(getmain)
+
def hello(self):
"Called when execution is transferred into this coroutine."
def goodbye(self):
"Called just after execution is transferred away from this coroutine."
-costate = None
-costate = CoState()
-
# _________________________________________________
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 Thu Jun 8 18:30:03 2006
@@ -3,22 +3,22 @@
"""
import os
-from pypy.module.stackless.interp_coroutine import costate, Coroutine, AbstractThunk
+from pypy.module.stackless.interp_coroutine import main_coroutine_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):
backendopt = True
stacklessmode = True
gcpolicy = gc.BoehmGcPolicy
Coroutine = Coroutine
- def setup_meth(self):
- costate.__init__()
+ def setup_method(self, method):
+ main_coroutine_getter.costate = None
+ main_coroutine_getter.costate = None
def _freeze_(self): # for 'self.Coroutine'
return True
@@ -51,7 +51,7 @@
def f():
lst = [1]
- coro_f = costate.main
+ coro_f = Coroutine.getcurrent()
coro_g = self.Coroutine()
coro_h = self.Coroutine()
coros = [coro_f, coro_g, coro_h]
@@ -146,7 +146,7 @@
return n
def f():
- coro_f = costate.main
+ coro_f = Coroutine.getcurrent()
coro_f1 = self.Coroutine()
thunk_f1 = T1(f1, coro_f1)
output('binding f1 after f set 1')
@@ -159,6 +159,7 @@
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
@@ -172,9 +173,10 @@
raise ValueError
if nrec:
g(nrec-1, t, count+1)
- costate.main.switch()
+ Coroutine.getmain().switch()
def f():
+ assert Coroutine.getmain().frame is None
coro_g = self.Coroutine()
thunk_g = T(g, 42)
coro_g.bind(thunk_g)
@@ -246,7 +248,7 @@
def call(self):
self.result = self.consume(self.tree)
- costate.main.switch()
+ Coroutine.getmain().switch()
def pre_order_eq(t1, t2):
objects = []
@@ -270,3 +272,8 @@
output = self.wrap_stackless_function(ep)
assert output == int('0110')
+
+class TestCoroutineOnCPython(TestCoroutine):
+ def wrap_stackless_function(self, func):
+ return func()
+
More information about the Pypy-commit
mailing list