[pypy-svn] r35931 - in pypy/dist/pypy/lib: . app_test
stephan at codespeak.net
stephan at codespeak.net
Thu Dec 21 15:09:01 CET 2006
Author: stephan
Date: Thu Dec 21 15:09:00 2006
New Revision: 35931
Modified:
pypy/dist/pypy/lib/app_test/test_stackless.py
pypy/dist/pypy/lib/stackless_new.py
Log:
passing now all tests but one. But 'schedule' looks more and more
terrible. Sigh.... Anyway, stackless_new.py has less than half the lines
than stackless.py which I'd call an improvement
Modified: pypy/dist/pypy/lib/app_test/test_stackless.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/test_stackless.py (original)
+++ pypy/dist/pypy/lib/app_test/test_stackless.py Thu Dec 21 15:09:00 2006
@@ -69,7 +69,6 @@
stackless.run()
assert len(rlist) == 20
- print rlist
for i in range(10):
(s,r), rlist = rlist[:2], rlist[2:]
assert s == 's%s' % i
@@ -225,7 +224,6 @@
def test_simple_channel(self):
output = []
- #skip('')
def print_(*args):
output.append(args)
@@ -353,12 +351,6 @@
]
def test_schedule_callback(self):
- pypy_skip('not running correctly')
- # in stackless_new, a dead tasklet will be removed
- # and is not known anymore when scheduling happens.
- # Due to the applevel nature of stackless_new,
- # the schedule callback is done only on explicit schedule,
- # but not on implicit ones
res = []
cb = []
def schedule_cb(prev, next):
@@ -382,19 +374,17 @@
assert cb[4] == (t2, maintask)
def test_bomb(self):
- pypy_skip('not yet implemented in pypy')
try:
1/0
except:
import sys
b = stackless.bomb(*sys.exc_info())
assert b.type is ZeroDivisionError
- print type(b.value)
- assert str(b.value) == 'integer division or modulo by zero'
+ print str(b.value)
+ assert str(b.value).startswith('integer division')
assert b.traceback is not None
def test_send_exception(self):
- pypy_skip('not yet implemented in pypy')
def exp_sender(chan):
chan.send_exception(Exception, 'test')
@@ -411,7 +401,6 @@
stackless.run()
def test_send_sequence(self):
- pypy_skip('not yet implemented in pypy')
res = []
lst = [1,2,3,4,5,6,None]
iterable = iter(lst)
@@ -427,7 +416,6 @@
assert res == [1,2,3,4,5,6]
def test_getruncount(self):
- pypy_skip('not yet implemented in pypy')
assert stackless.getruncount() == 1
def with_schedule():
assert stackless.getruncount() == 2
@@ -442,7 +430,6 @@
stackless.run()
def test_schedule_return(self):
- pypy_skip('not yet implemented in pypy')
def f():pass
t1= stackless.tasklet(f)()
r = stackless.schedule()
Modified: pypy/dist/pypy/lib/stackless_new.py
==============================================================================
--- pypy/dist/pypy/lib/stackless_new.py (original)
+++ pypy/dist/pypy/lib/stackless_new.py Thu Dec 21 15:09:00 2006
@@ -22,36 +22,39 @@
__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \
TaskletExit greenlet'.split()
-global_task_id = 0
-squeue = None
-main_tasklet = None
-main_coroutine = None
-first_run = False
+_global_task_id = 0
+_squeue = None
+_main_tasklet = None
+_main_coroutine = None
+_last_task = None
_channel_callback = None
_schedule_callback = None
def _scheduler_remove(value):
try:
- del squeue[operator.indexOf(squeue, value)]
+ del _squeue[operator.indexOf(_squeue, value)]
except ValueError:pass
def _scheduler_append(value, normal=True):
if normal:
- squeue.append(value)
+ _squeue.append(value)
else:
- squeue.appendleft(value)
+ _squeue.appendleft(value)
def _scheduler_contains(value):
try:
- operator.indexOf(squeue, value)
+ operator.indexOf(_squeue, value)
return True
except ValueError:
return False
def _scheduler_switch(current, next):
+ global _last_task
+ _last_task = next
if _schedule_callback is not None:
_schedule_callback(current, next)
- return next.switch()
+ next.switch()
+ return current
class TaskletExit(Exception):pass
@@ -64,6 +67,18 @@
global _channel_callback
_channel_callback = callback
+def getruncount():
+ return len(_squeue)
+
+class bomb(object):
+ def __init__(self, exp_type=None, exp_value=None, exp_traceback=None):
+ self.type = exp_type
+ self.value = exp_value
+ self.traceback = exp_traceback
+
+ def raise_(self):
+ raise self.type(self.value)
+
class channel(object):
"""
A channel object is used for communication between tasklets.
@@ -125,8 +140,17 @@
receiver.blocked = True
schedule_remove()
msg = receiver.tempval
+ if isinstance(msg, bomb):
+ msg.raise_()
return msg
+ def send_exception(self, exp_type, msg):
+ self.send(bomb(exp_type, exp_type(msg)))
+
+ def send_sequence(self, iterable):
+ for item in iterable:
+ self.send(item)
+
def send(self, msg):
"""
channel.send(value) -- send a value over the channel.
@@ -168,16 +192,15 @@
self._init(func)
def _init(self, func=None):
- global global_task_id
+ global _global_task_id
self.tempval = func
self.alive = False
self.blocked = False
- self.task_id = global_task_id
- global_task_id += 1
+ self.task_id = _global_task_id
+ _global_task_id += 1
def __str__(self):
- return '<tasklet %s a:%s z:%s>' % \
- (self.task_id, self.is_alive, self.is_zombie)
+ return '<tasklet %s:%s>' % (self.task_id, self.is_alive)
__repr__ = __str__
@@ -235,7 +258,7 @@
"""
getmain() -- return the main tasklet.
"""
- return main_tasklet
+ return _main_tasklet
def getcurrent():
"""
@@ -243,8 +266,8 @@
"""
curr = coroutine.getcurrent()
- if curr is main_coroutine:
- return main_tasklet
+ if curr is _main_coroutine:
+ return _main_tasklet
else:
return curr
@@ -261,9 +284,12 @@
Please note that the 'timeout' feature is not yet implemented
"""
- schedule_remove()
- while squeue:
- schedule()
+ r = schedule_remove()
+ if _last_task and _schedule_callback is not None:
+ _schedule_callback(_last_task, getcurrent())
+ while _squeue:
+ r = schedule()
+ _scheduler_append(getcurrent())
def schedule_remove(retval=None):
"""
@@ -273,28 +299,28 @@
schedule_remove(retval=stackless.current) -- ditto, and remove self.
"""
_scheduler_remove(getcurrent())
- schedule()
+ r = schedule(retval)
+ return r
-def schedule(retval=None):
+def schedule(retval=None, prev=None):
"""
schedule(retval=stackless.current) -- switch to the next runnable tasklet.
The return value for this call is retval, with the current
tasklet as default.
schedule_remove(retval=stackless.current) -- ditto, and remove self.
"""
-
mtask = getmain()
- if squeue:
- task = squeue[0]
- squeue.rotate(-1)
- curr = getcurrent()
+ curr = getcurrent()
+ if _squeue:
+ task = _squeue[0]
+ _squeue.rotate(-1)
if task is not curr and task.is_alive:
- #r = task.switch()
- r = _scheduler_switch(curr, task)
+ c = prev or curr
+ r = _scheduler_switch(c, task)
curr = getcurrent()
if not task.is_alive:
- if squeue:
- pt = squeue.pop()
+ if _squeue:
+ pt = _squeue.pop()
if pt.is_alive:
_scheduler_append(pt)
else:
@@ -302,29 +328,36 @@
else:
if curr is not mtask:
r = _scheduler_switch(curr, mtask)
- #mtask.switch()
- schedule()
+ return retval or r
+ r = schedule(prev=task)
+ return retval or r
+ return r
elif task is curr:
- if len(squeue) > 1:
- if squeue[0] is squeue[-1]:
- squeue.pop()
- schedule()
+ if len(_squeue) > 1:
+ if _squeue[0] is _squeue[-1]:
+ _squeue.pop()
+ r = schedule()
+ return retval or r
+ return retval or curr
elif not task.is_alive:
_scheduler_remove(task)
- if not squeue:
+ if not _squeue:
_scheduler_append(mtask)
+ return retval or curr
+ return retval or curr
def _init():
- global main_tasklet
- global global_task_id
- global squeue
- global_task_id = 0
- main_tasklet = coroutine.getcurrent()
+ global _main_tasklet
+ global _global_task_id
+ global _squeue
+ global _last_task
+ _global_task_id = 0
+ _main_tasklet = coroutine.getcurrent()
try:
- main_tasklet.__class__ = tasklet
+ _main_tasklet.__class__ = tasklet
except TypeError: # we are running pypy-c
class TaskletProxy(object):
- """TaskletProxy is needed to give the main_coroutine tasklet behaviour"""
+ """TaskletProxy is needed to give the _main_coroutine tasklet behaviour"""
def __init__(self, coro):
self._coro = coro
@@ -341,12 +374,12 @@
__repr__ = __str__
- global main_coroutine
- main_coroutine = main_tasklet
- main_tasklet = TaskletProxy(main_tasklet)
- assert main_tasklet.is_alive and not main_tasklet.is_zombie
- tasklet._init(main_tasklet)
- squeue = deque()
- _scheduler_append(main_tasklet)
+ global _main_coroutine
+ _main_coroutine = _main_tasklet
+ _main_tasklet = TaskletProxy(_main_tasklet)
+ assert _main_tasklet.is_alive and not _main_tasklet.is_zombie
+ tasklet._init(_main_tasklet)
+ _squeue = deque()
+ _scheduler_append(_main_tasklet)
_init()
More information about the Pypy-commit
mailing list