<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style id="owaParaStyle">P {
        MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
P {
        MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
</style>
</head>
<body fPStyle="1" ocsi="0">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">
<p>Possibly I should have selected a different code name, now I come to think of it, but we came up with such similar code that I don't think it'll stay separate for too long.</p>
<p> </p>
<div style="FONT-FAMILY: Times New Roman; COLOR: #000000; FONT-SIZE: 16px">
<hr tabindex="-1">
<div style="DIRECTION: ltr" id="divRpF326167"><font color="#000000" size="2" face="Tahoma"><b>From:</b> Python-ideas [python-ideas-bounces+steve.dower=microsoft.com@python.org] on behalf of Steve Dower [Steve.Dower@microsoft.com]<br>
<b>Sent:</b> Monday, October 29, 2012 6:40 PM<br>
<b>To:</b> python-ideas@python.org<br>
<b>Subject:</b> [Python-ideas] Async API: some more code to review<br>
</font><br>
</div>
<div></div>
<div>
<div style="FONT-FAMILY: Tahoma; DIRECTION: ltr; COLOR: #000000; FONT-SIZE: 10pt">
<p>To save people scrolling to get to the interesting parts, I'll lead with the links:</p>
<div style="FONT-FAMILY: Times New Roman; COLOR: #000000; FONT-SIZE: 16px">
<div>
<div style="FONT-FAMILY: Tahoma; DIRECTION: ltr; COLOR: #000000; FONT-SIZE: 10pt">
<p> </p>
<p>Detailed write-up: <a href="https://bitbucket.org/stevedower/tulip/wiki/Proposal" target="_blank">https://bitbucket.org/stevedower/tulip/wiki/Proposal</a></p>
<p> </p>
<p>Source code: <a href="https://bitbucket.org/stevedower/tulip/src" target="_blank">
https://bitbucket.org/stevedower/tulip/src</a></p>
<p> </p>
<p>(Yes, I renamed my repo after the code name was selected. That would have been far too much of a coincidence.)</p>
<p> </p>
<p>Practically all of the details are in the write-up linked first, so anything that's not is either something I didn't think of or something I decided is unimportant right now (for example, the optimal way to wait for ten thousand sockets simultaneously on
 every different platform).</p>
<p> </p>
<p>There's a reimplemented Future class in the code which is not essential, but it is drastically simplified from concurrent.futures.Future (CFF). It can't be directly replaced by CFF, but only because CFF requires more state management that the rest of the
 implementation does not perform ("set_running_or_notify_cancel"). CFF also includes cancellation, for which I've proposed a different mechanism.</p>
<p> </p>
<p>For the sake of a quick example, I've modified Guido's main.doit function (<a href="http://code.google.com/p/tulip/source/browse/main.py" target="_blank">http://code.google.com/p/tulip/source/browse/main.py</a>) to how it could be written with my proposal
 (apologies if I've butchered it, but I think it should behave the same):</p>
<p> </p>
<p>@async</p>
<p>def doit():<br>
    TIMEOUT = 2<br>
    cs = CancellationSource()<br>
    cs.cancel_after(TIMEOUT)</p>
<p> </p>
<p>    tasks = set()</p>
<p><br>
    task1 = urlfetch('localhost', 8080, path='/', cancel_source=cs)<br>
    tasks.add(task1)</p>
<p> </p>
<p>    task2 = urlfetch('127.0.0.1', 8080, path='/home', cancel_source=cs)<br>
    tasks.add(task2)</p>
<p> </p>
<p>    task3 = urlfetch('python.org', 80, path='/', cancel_source=cs)<br>
    tasks.add(task3)</p>
<p> </p>
<p>    task4 = urlfetch('xkcd.com', ssl=True, path='/', af=socket.AF_INET, cancel_source=cs)<br>
    tasks.add(task4)</p>
<p> </p>
<p>    ## for t in tasks: t.start()    # tasks start as soon as they are called - this function does not exist</p>
<p> </p>
<p>    yield delay(0.2)                # I believe this is equivalent to scheduling.with_timeout(0.2, ...)?<br>
    <br>
    winners = [t.result() for t in tasks if t.done()]<br>
    print('And the winners are:', [w for w in winners])<br>
    <br>
    results = []                    # This 'wait all' loop could easily be a helper function<br>
    for t in tasks:                 # Unfortunately, [(yield t) for t in tasks] does not work :(<br>
        results.append((yield t))<br>
    print('And the players were:', [r for r in results])<br>
    return results<br>
</p>
<p>This is untested code, and has a few differences. I don't have task names, so it will print the returned value from urlfetch (a tuple of (host, port, path, status, len(data), time_taken)). The cancellation approach is quite different, but IMO far more likely
 to avoid the finally-related issues discussed in other threads.</p>
<p> </p>
<p>However, I want to emphasise that unless you are already familiar with this exact style, it is near impossible to guess exactly what is going on from this little sample. Please read the write-up before assuming what is or is not possible with this approach.</p>
<p> </p>
<p>Cheers,</p>
<p>Steve</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>