[pypy-svn] r27026 - pypy/dist/pypy/module/stackless/test

stephan at codespeak.net stephan at codespeak.net
Wed May 10 10:16:01 CEST 2006


Author: stephan
Date: Wed May 10 10:15:58 2006
New Revision: 27026

Added:
   pypy/dist/pypy/module/stackless/test/coro1.py
   pypy/dist/pypy/module/stackless/test/stack1.py
   pypy/dist/pypy/module/stackless/test/stack2.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/test/stack3.py   (contents, props changed)
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
proof of concept implementation of stackless on top of coroutine.


Added: pypy/dist/pypy/module/stackless/test/coro1.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/coro1.py	Wed May 10 10:15:58 2006
@@ -0,0 +1,28 @@
+from stackless import coroutine
+
+d = {}
+
+def f():
+    print 'in f'
+
+def g(coro,t):
+    print 'in g %s' % t
+    coro.switch()
+
+def main():
+    cm = coroutine.getcurrent()
+    d[cm] = 'main'
+    cf = coroutine()
+    d[cf] = 'f'
+    print 'cf:',cf
+    cf.bind(f)
+    cg = coroutine()
+    d[cg] = 'g'
+    print 'cg:',cg
+    cg.bind(g,cf,'test')
+    cg.switch()
+    print 'back in main'
+    print d
+
+if __name__ == '__main__':
+    main()

Added: pypy/dist/pypy/module/stackless/test/stack1.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/stack1.py	Wed May 10 10:15:58 2006
@@ -0,0 +1,18 @@
+from stackless_ import *
+
+def f():
+    print 'in f'
+
+def g(t):
+    print 'in g %s' % t
+    schedule()
+
+def main():
+    cg = tasklet(g)('test')
+    cf = tasklet(f)()
+    schedule()
+    print 'in main'
+
+if __name__ == '__main__':
+    main()
+    

Added: pypy/dist/pypy/module/stackless/test/stack2.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/stack2.py	Wed May 10 10:15:58 2006
@@ -0,0 +1,20 @@
+from stackless_ import *
+
+def f(outchan):
+    for i in range(10):
+        print 'f send',i
+        outchan.send(i)
+    outchan.send(-1)
+
+def g(inchan):
+    while 1:
+        val = inchan.receive()
+        if val == -1:
+            break
+        print 'g received',val
+
+ch = channel()
+t1 = tasklet(f)(ch)
+t2 = tasklet(g)(ch)
+
+t1.run()

Added: pypy/dist/pypy/module/stackless/test/stack3.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/stack3.py	Wed May 10 10:15:58 2006
@@ -0,0 +1,43 @@
+def receiver(chan, name):
+    while 1:
+        try:
+            data = chan.receive()
+        except:
+            print name, "** Ouch!!! **"
+            raise
+        print name, "got:", data
+        if data == 42:
+            chan.send("%s says bye" % name)
+            return
+
+import sys
+import stackless
+if hasattr(stackless,'coroutine'):
+    import stackless_ as stackless
+
+chan = stackless.channel()
+t1 = stackless.tasklet(receiver)(chan, "inky")
+t2 = stackless.tasklet(receiver)(chan, "dinky")
+stackless.run()
+try:
+    for i in 2,3,5,7, 42:
+        print "sending", i
+        chan.send(i)
+        chan.send(i)
+        #if i==7:
+        #    print "sending Exception"
+        #    chan.send_exception(ValueError, i)
+except ValueError:
+    e, v, t = sys.exc_info()
+    print e, v
+    del e, v, t
+print "main done."
+#
+# trying to clean up things, until we have a real
+# channel deallocator:
+print "trying cleanup:"
+while chan.balance:
+    if chan.balance < 0:
+        chan.send(42)
+    else:
+        print chan.receive()

Added: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Wed May 10 10:15:58 2006
@@ -0,0 +1,148 @@
+from stackless import coroutine
+
+__all__ = 'run getcurrent getmain schedule tasklet channel'.split()
+
+main_tasklet = None
+next_tasklet = None
+scheduler = None
+
+coro_reg = {}
+
+def __init():
+    global maintasklet
+    mt = tasklet()
+    mt._coro = c = coroutine.getcurrent()
+    maintasklet = mt
+    coro_reg[c] = mt
+
+def run():
+    schedule()
+
+def getcurrent():
+    c = coroutine.getcurrent()
+    return coro_reg[c]
+
+def getmain():
+    return main_tasklet
+
+def schedule():
+    scheduler.schedule()
+
+class tasklet(object):
+    def __init__(self,func=None):
+        self._func = func
+
+    def __call__(self,*argl,**argd):
+        self._coro = c = coroutine()
+        c.bind(self._func,*argl,**argd)
+        coro_reg[c] = self
+        self.insert()
+        return self
+
+    def awake(self):pass
+
+    def sleep(self):pass
+
+    def run(self):
+        scheduler.setnexttask(self)
+        schedule()
+
+    def insert(self):
+        scheduler.insert(self)
+
+    def remove(self):
+        scheduler.remove(self)
+
+    def kill(self):pass
+
+class channel(object):
+    def __init__(self):
+        self.balance = 0
+        self._readq = []
+        self._writeq = []
+
+    def send(self, msg):
+        ct = getcurrent()
+        scheduler.remove(ct)
+        self._writeq.append((ct,msg))
+        self.balance += 1
+        if self._readq:
+            nt, self._readq = self._readq[0], self._readq[1:]
+            scheduler.priorityinsert(nt)
+        schedule()
+
+    def receive(self):
+        ct = getcurrent()
+        if self._writeq:
+            (wt,retval), self._writeq = self._writeq[0], self._writeq[1:]
+            scheduler.priorityinsert(wt)
+            self.balance -= 1
+            return retval
+        else:
+            self._readq.append(ct)
+            scheduler.remove(ct)
+            schedule()
+            return self.receive()
+
+class Scheduler(object):
+    def __init__(self):
+        self.tasklist = []
+        self.nexttask = None 
+
+    def empty(self):
+        return not self.tasklist
+
+    def __str__(self):
+        return repr(self.tasklist) + '/%s' % self.nexttask
+
+    def insert(self,task):
+        if (task not in self.tasklist) and task is not maintasklet:
+            self.tasklist.append(task)
+        if self.nexttask is None:
+            self.nexttask = 0
+
+    def priorityinsert(self,task):
+        if task in self.tasklist:
+            self.tasklist.remove(task)
+        if task is maintasklet:
+            return
+        if self.nexttask:
+            self.tasklist.insert(self.nexttask,task)
+        else:
+            self.tasklist.insert(0,task)
+            self.nexttask = 0
+
+    def remove(self,task):
+        try:
+            i = self.tasklist.index(task)
+            del(self.tasklist[i])
+            if self.nexttask > i:
+                self.nexttask -= 1
+            if len(self.tasklist) == 0:
+                self.nexttask = None
+        except ValueError:pass
+
+    def next(self):
+        if self.nexttask is not None:
+            task = self.tasklist[self.nexttask]
+            self.nexttask += 1
+            if self.nexttask == len(self.tasklist):
+                self.nexttask = 0
+            return task
+        else:
+            return maintasklet
+
+    def setnexttask(self,task):
+        if task not in self.tasklist:
+            self.tasklist.insert(task)
+        try:
+            i = self.tasklist.index(task)
+            self.nexttask = i
+        except IndexError:pass
+
+    def schedule(self):
+        n = self.next()
+        n._coro.switch()
+
+scheduler = Scheduler()
+__init()



More information about the Pypy-commit mailing list