Hi all.

Lets start controversially: I don't like PEP 380, I think it's a kludge.

I think that CPython should have proper coroutines, rather than add more bits and pieces to generators in an attempt to make them more like coroutines.

I have mentioned this before, but this time I have done something about it :)

I have a working, portable, (asymmetric) coroutine implementation here:

https://bitbucket.org/markshannon/hotpy_coroutines

Its all standard C, no messing with the C stack, just using standard techniques to convert recursion to iteration (in the VM not at the Python level) and a revised internal calling convention to make CPython stackless:

https://bitbucket.org/markshannon/hotpy_stackless

Then I've added a Coroutine class and fiddled with the implementation of YIELD_VALUE to support it.

I think the stackless implementation is pretty solid, but the
coroutine stuff needs some refinement.
I've not tested it well (it passes the test suite, but I've added no new tests).
It is (surprisingly) a bit faster than tip (on my machine).
There are limitations: all calls must be Python-to-Python calls,
which rules out most __xxx__ methods. It might be worth special casing __iter__, but I've not done that yet.

To try it out:

>>> import coroutine
To send a value to a coroutine:
>>> co.send(val)
where co is a Coroutine()
To yield a value:
>>> coroutine.co_yield(val)
send() is a method, co_yield is a function.

Here's a little program to demonstrate:

import coroutine

class Node:
    def __init__(self, l, item, r):
        self.l = l
        self.item = item
        self.r = r

def make_tree(n):
    if n == 0:
        return Node(None, n, None)
    else:
        return Node(make_tree(n-1), n, make_tree(n-1))

def walk_tree(t, f):
    if t is not None:
        walk_tree(t.l, f)
        f(t)
        walk_tree(t.r, f)

def yielder(t):
    coroutine.co_yield(t.item)

def tree_yielder(t):
    walk_tree(t, yielder)

co = coroutine.Coroutine(tree_yielder, (make_tree(2),))

while True:
    print(co.send(None))

Which will output:

0
1
0
2
0
1
0
None
Traceback (most recent call last):
  File "co_demo.py", line 30, in <module>
    print(co.send(None))
TypeError: can't send to a halted coroutine


Cheers,
Mark.
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to