[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