Replace par() with wait() and as_completed(),

This commit is contained in:
Guido van Rossum 2012-12-21 22:10:48 -08:00
parent 97a7a2a0cd
commit c1e111fd11
1 changed files with 30 additions and 15 deletions

View File

@ -514,6 +514,8 @@ user code that returns a Future?)
A ``tulip.Future`` object is not acceptable to the ``wait()`` and A ``tulip.Future`` object is not acceptable to the ``wait()`` and
``as_completed()`` functions in the ``concurrent.futures`` package. ``as_completed()`` functions in the ``concurrent.futures`` package.
However, there are similar APIs ``tulip.wait()`` and
``tulip.as_completed()``, described below.
A ``tulip.Future`` object is acceptable to a ``yield from`` expression A ``tulip.Future`` object is acceptable to a ``yield from`` expression
when used in a coroutine. This is implemented through the when used in a coroutine. This is implemented through the
@ -752,18 +754,40 @@ Things a coroutine can do:
produce a result (or raise an exception, which will be propagated). produce a result (or raise an exception, which will be propagated).
The ``coroutine`` expression must be a *call* to another coroutine. The ``coroutine`` expression must be a *call* to another coroutine.
- ``results = yield from tulip.par(futures_and_coroutines)`` -- Wait
for a list of futures and/or coroutines to complete and return a
list of their results. If one of the futures or coroutines raises
an exception, that exception is propagated, after attempting to
cancel all other futures and coroutines in the list.
- ``return result`` -- produce a result to the coroutine that is - ``return result`` -- produce a result to the coroutine that is
waiting for this one using ``yield from``. waiting for this one using ``yield from``.
- ``raise exception`` -- raise an exception in the coroutine that is - ``raise exception`` -- raise an exception in the coroutine that is
waiting for this one using ``yield from``. waiting for this one using ``yield from``.
To wait for multiple coroutines, two APIs similar to the ``wait()``
and ``as_completed()`` APIs in the ``concurrent.futures`` package are
provided:
- ``tulip.wait(fs, ...)``. Wait for the Futures or coroutines given
by ``fs`` to complete. This is a coroutine whose result on success
is a tuple of two sets of Futures, ``(done, not_done)``. Optional
arguments ``timeout`` and ``return_when`` have the same meaning and
defaults as for ``concurrent.futures.wait()``. The constants
``FIRST_COMPLETED``, ``FIRST_EXCEPTION``, ``ALL_COMPLETED`` are
defined with the same values and the same meanings as in PEP 3148.
- ``as_completed(fs, ...)``. Return an iterator whose values are
coroutines; waiting for successive values waits until the next
Future or coroutine from the set ``fs`` completes, and returns its
result (or raises its exception). The optional argument ``timeout``
has the same meaning and default as it does for
``concurrent.futures.wait()``; if the timeout is reached, the next
coroutine will raise ``concurrent.futures.TimeoutError`` when waited
for. Example of use::
for f in as_completed(fs):
result = yield from f
(TBD: should ``as_completed()`` return an iterator of coroutines or an
iterator of Futures? For ``wait()`` it's clear that the sets should
only contain Futures; but less so for ``as_completed()``.)
Calling a coroutine does not start its code running -- it is just a Calling a coroutine does not start its code running -- it is just a
generator, and the coroutine object returned by the call is really a generator, and the coroutine object returned by the call is really a
generator object, which doesn't do anything until you iterate over it. generator object, which doesn't do anything until you iterate over it.
@ -789,10 +813,6 @@ that it may catch to further handle cancellation, but it doesn't have
to (this is done using the standard ``close()`` method on generators, to (this is done using the standard ``close()`` method on generators,
described in PEP 342). described in PEP 342).
The ``par()`` function described above runs coroutines in parallel by
converting them to Tasks. (Arguments that are already Tasks or
Futures are not converted.)
Tasks are also useful for interoperating between coroutines and Tasks are also useful for interoperating between coroutines and
callback-based frameworks like Twisted. After converting a coroutine callback-based frameworks like Twisted. After converting a coroutine
into a Task, callbacks can be added to the Task. into a Task, callbacks can be added to the Task.
@ -819,11 +839,6 @@ Sleeping
TBD: ``yield sleep(seconds)``. Can use ``sleep(0)`` to suspend to TBD: ``yield sleep(seconds)``. Can use ``sleep(0)`` to suspend to
poll for I/O. poll for I/O.
Wait for First
--------------
TBD: Need an interface to wait for the first of a collection of Futures.
Coroutines and Protocols Coroutines and Protocols
------------------------ ------------------------