Allow Handlers as callbacks. Add EventLoop.close().

This commit is contained in:
Guido van Rossum 2013-01-08 19:39:28 -08:00
parent b9c08eaf8f
commit b7ec592492
1 changed files with 37 additions and 25 deletions

View File

@ -148,10 +148,18 @@ loop per thread.
Event Loop Interface Event Loop Interface
-------------------- --------------------
(A note about times: as usual in Python, all timeouts, intervals and A note about times: as usual in Python, all timeouts, intervals and
delays are measured in seconds, and may be ints or floats. The delays are measured in seconds, and may be ints or floats. The
accuracy and precision of the clock are up to the implementation; the accuracy and precision of the clock are up to the implementation; the
default implementation uses ``time.monotonic()``.) default implementation uses ``time.monotonic()``.
A note about callbacks and Handlers: any function that takes a
callback and a variable number of arguments for it can also be given a
Handler object instead of the callback. Then no arguments should be
given, and the Handler should represent an immediate callback (as
returned from ``call_soon()``), not a delayed callback (as returned
from ``call_later()``). If the Handler is already cancelled, the
call is a no-op.
A conforming event loop object has the following methods: A conforming event loop object has the following methods:
@ -173,15 +181,6 @@ A conforming event loop object has the following methods:
TBD: How many variants of this do we really need? TBD: How many variants of this do we really need?
- ``stop()``. Stops the event loop as soon as it is convenient. It
is fine to restart the loop with ``run()`` (or one of its variants)
subsequently.
Note: How soon exactly is up to the implementation. All immediate
callbacks that were already scheduled to run before ``stop()`` is
called must still be run, but callbacks scheduled after it is called
(or scheduled to be run later) will not be run.
- ``run_forever()``. Runs the event loop until ``stop()`` is called. - ``run_forever()``. Runs the event loop until ``stop()`` is called.
- ``run_until_complete(future, timeout=None)``. Runs the event loop - ``run_until_complete(future, timeout=None)``. Runs the event loop
@ -205,6 +204,20 @@ A conforming event loop object has the following methods:
``call_soon()``, causing an infinite loop, ``run_once()`` should ``call_soon()``, causing an infinite loop, ``run_once()`` should
still return. still return.
- ``stop()``. Stops the event loop as soon as it is convenient. It
is fine to restart the loop with ``run()`` (or one of its variants)
subsequently.
Note: How soon exactly is up to the implementation. All immediate
callbacks that were already scheduled to run before ``stop()`` is
called must still be run, but callbacks scheduled after it is called
(or scheduled to be run later) will not be run.
- ``close()``. Closes the event loop, releasing any resources it may
hold, such as the file descriptor used by ``epoll()`` or
``kqueue()``. This should not be called while the event loop is
running. It may be called multiple times.
- ``call_later(delay, callback, *args)``. Arrange for - ``call_later(delay, callback, *args)``. Arrange for
``callback(*args)`` to be called approximately ``delay`` seconds in ``callback(*args)`` to be called approximately ``delay`` seconds in
the future, once, unless cancelled. Returns the future, once, unless cancelled. Returns
@ -232,24 +245,25 @@ A conforming event loop object has the following methods:
- ``add_signal_handler(sig, callback, *args). Whenever signal ``sig`` - ``add_signal_handler(sig, callback, *args). Whenever signal ``sig``
is received, arrange for ``callback(*args)`` to be called. Returns is received, arrange for ``callback(*args)`` to be called. Returns
a ``Handler`` which can be used to cancel the signal callback. a ``Handler`` which can be used to cancel the signal callback.
(Cancelling the handler causes ``remove_signal_handler()`` to be
called the next time the signal arrives. Explicitly calling
``remove_signal_handler()`` is preferred.)
Specifying another callback for the same signal replaces the Specifying another callback for the same signal replaces the
previous handler (only one handler can be active per signal). The previous handler (only one handler can be active per signal). The
``sig`` must be a valid sigal number defined in the ``signal`` ``sig`` must be a valid sigal number defined in the ``signal``
module. If the signal cannot be handled this raises an exception: module. If the signal cannot be handled this raises an exception:
ValueError if it is not a valid signal or if it is an uncatchable ``ValueError`` if it is not a valid signal or if it is an uncatchable
signale (e.g. ``SIGKILL``), RuntimeError if this particular event signale (e.g. ``SIGKILL``), ``RuntimeError`` if this particular event
loop instance cannot handle signals (since signals are global per loop instance cannot handle signals (since signals are global per
process, only an event loop associated with the main thread can process, only an event loop associated with the main thread can
handle signals). handle signals).
- ``remove_signal_handler(sig)``. Removes the handler for signal - ``remove_signal_handler(sig)``. Removes the handler for signal
``sig``, if one is set. Raises the same exceptions as ``sig``, if one is set. Raises the same exceptions as
``add_signal_handler()``. ``add_signal_handler()`` (except that it may return ``False``
instead raising ``RuntimeError`` for uncatchable signals). Returns
- TBD: A way to register a callback that is already wrapped in a ``True``e\ if a handler was removed successfully, ``False`` if no
``Handler``. Maybe ``call_soon()`` could just check handler was set.
``isinstance(callback, Handler)``? It should silently skip
a cancelled callback.
Some methods in the standard conforming interface return Futures: Some methods in the standard conforming interface return Futures:
@ -257,15 +271,13 @@ Some methods in the standard conforming interface return Futures:
instance of ``concurrent.futures.Future``) and returns a Future instance of ``concurrent.futures.Future``) and returns a Future
compatible with the event loop (i.e., a ``tulip.Future`` instance). compatible with the event loop (i.e., a ``tulip.Future`` instance).
- ``run_in_executor(executor, function, *args)``. Arrange to call - ``run_in_executor(executor, callback, *args)``. Arrange to call
``function(*args)`` in an executor (see PEP 3148). Returns a Future ``callback(*args)`` in an executor (see PEP 3148). Returns a Future
whose result on success is the return value that call. This is whose result on success is the return value that call. This is
equivalent to ``wrap_future(executor.submit(function, *args))``. If equivalent to ``wrap_future(executor.submit(callback, *args))``. If
``executor`` is ``None``, a default ``ThreadPoolExecutor`` with 5 ``executor`` is ``None``, a default ``ThreadPoolExecutor`` with 5
threads is used. (TBD: Should the default executor be shared threads is used. (TBD: Should the default executor be shared
between different event loops? Should we even have a default between different event loops?)
executor? Should be be able to set its thread count? Shoul we even
have this method?)
- ``set_default_executor(executor)``. Set the default executor used - ``set_default_executor(executor)``. Set the default executor used
by ``run_in_executor()``. by ``run_in_executor()``.