[pypy-svn] r34932 - in pypy/dist/pypy/module/_stackless: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Nov 24 14:00:41 CET 2006
Author: arigo
Date: Fri Nov 24 14:00:39 2006
New Revision: 34932
Modified:
pypy/dist/pypy/module/_stackless/coroutine.py
pypy/dist/pypy/module/_stackless/interp_coroutine.py
pypy/dist/pypy/module/_stackless/test/test_clonable.py
Log:
(pedronis, arigo)
Test and bug fix for an obscure problem in _execute(), where the local
'self' is not correct if the coroutine is a clone -- it still points to
the original. Reload it from costate.current instead.
Sidenotedly, 'ddd' is slightly less pain than 'gdb' to debug compiled
pypy-c's.
Modified: pypy/dist/pypy/module/_stackless/coroutine.py
==============================================================================
--- pypy/dist/pypy/module/_stackless/coroutine.py (original)
+++ pypy/dist/pypy/module/_stackless/coroutine.py Fri Nov 24 14:00:39 2006
@@ -86,9 +86,9 @@
if self.frame is None:
raise OperationError(space.w_ValueError, space.wrap(
"cannot switch to an unbound Coroutine"))
- self.switch()
- rstack.resume_point("w_switch", self, space)
state = self.costate
+ self.switch()
+ rstack.resume_point("w_switch", state, space)
w_ret, state.w_tempval = state.w_tempval, space.w_None
return w_ret
@@ -202,8 +202,8 @@
costate = self.costate
# now the big fun of recreating tiny things...
bottom = resume_state_create(None, "yield_current_frame_to_caller_1")
- # resume_point("coroutine__bind", self, state)
- _bind_frame = resume_state_create(bottom, "coroutine__bind", self, costate)
+ # resume_point("coroutine__bind", state)
+ _bind_frame = resume_state_create(bottom, "coroutine__bind", costate)
# rstack.resume_point("appthunk", costate, returns=w_result)
appthunk_frame = resume_state_create(_bind_frame, "appthunk", costate)
chain = appthunk_frame
@@ -231,10 +231,10 @@
call_frame = resume_state_create(dispatch_call_frame, 'call_function', frame)
chain = call_frame
- # rstack.resume_point("w_switch", self, space)
- w_switch_frame = resume_state_create(chain, 'w_switch', self, space)
- # resume_point("coroutine_switch", self, state, returns=incoming_frame)
- switch_frame = resume_state_create(w_switch_frame, "coroutine_switch", self, costate)
+ # rstack.resume_point("w_switch", state, space)
+ w_switch_frame = resume_state_create(chain, 'w_switch', costate, space)
+ # resume_point("coroutine_switch", state, returns=incoming_frame)
+ switch_frame = resume_state_create(w_switch_frame, "coroutine_switch", costate)
self.frame = switch_frame
# _mixin_ did not work
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 Nov 24 14:00:39 2006
@@ -217,11 +217,15 @@
thunk = self.thunk
self.thunk = None
thunk.call()
- resume_point("coroutine__bind", self, state)
+ resume_point("coroutine__bind", state)
except Exception, e:
exc = e
raise
finally:
+ # warning! we must reload the 'self' from the costate,
+ # because after a clone() the 'self' of both copies
+ # point to the original!
+ self = state.current
self.finish(exc)
except CoroutineExit:
# ignore a shutdown exception
@@ -242,7 +246,7 @@
raise CoroutineDamage
state = self.costate
incoming_frame = state.update(self).switch()
- resume_point("coroutine_switch", self, state, returns=incoming_frame)
+ resume_point("coroutine_switch", state, returns=incoming_frame)
syncstate.switched(incoming_frame)
def kill(self):
Modified: pypy/dist/pypy/module/_stackless/test/test_clonable.py
==============================================================================
--- pypy/dist/pypy/module/_stackless/test/test_clonable.py (original)
+++ pypy/dist/pypy/module/_stackless/test/test_clonable.py Fri Nov 24 14:00:39 2006
@@ -17,67 +17,96 @@
def test_solver(self):
- import new, sys
+ import _stackless
- mod = new.module('mod')
- sys.modules['mod'] = mod
- try:
- exec '''
-import _stackless
-
-class Fail(Exception):
- pass
-
-class Success(Exception):
- pass
-
-def first_solution(func):
- global next_answer
- co = _stackless.clonable()
- co.bind(func)
- pending = [(co, None)]
- while pending:
- co, next_answer = pending.pop()
- try:
- co.switch()
- except Fail:
+ class Fail(Exception):
pass
- except Success, e:
- return e.args[0]
- else:
- # zero_or_one() called, clone the coroutine
- co2 = co.clone()
- pending.append((co2, 1))
- pending.append((co, 0))
- raise Fail("no solution")
-
-pending = []
-main = _stackless.clonable.getcurrent()
-
-def zero_or_one():
- main.switch()
- return next_answer
-
-# ____________________________________________________________
-
-invalid_prefixes = {
- (0, 0): True,
- (0, 1, 0): True,
- (0, 1, 1): True,
- (1, 0): True,
- (1, 1, 0, 0): True,
- }
-
-def example():
- test = []
- for n in range(5):
- test.append(zero_or_one())
- if tuple(test) in invalid_prefixes:
- raise Fail
- raise Success(test)
-
-res = first_solution(example)
-assert res == [1, 1, 0, 1, 0]
-''' in mod.__dict__
- finally:
- del sys.modules['mod']
+
+ class Success(Exception):
+ pass
+
+ def first_solution(func):
+ global next_answer
+ co = _stackless.clonable()
+ co.bind(func)
+ pending = [(co, None)]
+ while pending:
+ co, next_answer = pending.pop()
+ try:
+ co.switch()
+ except Fail:
+ pass
+ except Success, e:
+ return e.args[0]
+ else:
+ # zero_or_one() called, clone the coroutine
+ co2 = co.clone()
+ pending.append((co2, 1))
+ pending.append((co, 0))
+ raise Fail("no solution")
+
+ pending = []
+ main = _stackless.clonable.getcurrent()
+
+ def zero_or_one():
+ main.switch()
+ return next_answer
+
+ # ____________________________________________________________
+
+ invalid_prefixes = {
+ (0, 0): True,
+ (0, 1, 0): True,
+ (0, 1, 1): True,
+ (1, 0): True,
+ (1, 1, 0, 0): True,
+ }
+
+ def example():
+ test = []
+ for n in range(5):
+ test.append(zero_or_one())
+ if tuple(test) in invalid_prefixes:
+ raise Fail
+ raise Success(test)
+
+ res = first_solution(example)
+ assert res == [1, 1, 0, 1, 0]
+
+
+ def test_myself_may_not_be_me_any_more(self):
+ import gc
+ from _stackless import clonable
+
+ counter = [0]
+
+ def runner():
+ while 1:
+ assert clonable.getcurrent() is coro
+ counter[0] += 1
+ main.switch()
+
+ main = clonable.getcurrent()
+ coro = clonable()
+ coro.bind(runner)
+
+ coro.switch()
+ assert counter == [1]
+
+ assert clonable.getcurrent() is main
+ coro1 = coro.clone()
+ assert counter == [1]
+ assert clonable.getcurrent() is main
+ coro.switch()
+ assert counter == [2]
+ coro.switch()
+ assert counter == [3]
+ assert clonable.getcurrent() is main
+ del coro1
+ gc.collect()
+ #print "collected!"
+ assert clonable.getcurrent() is main
+ assert counter == [3]
+ coro.switch()
+ assert clonable.getcurrent() is main
+ assert counter == [4]
More information about the Pypy-commit
mailing list