From b7ec5924929b4258017b0680a7682cec4054ebd9 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 8 Jan 2013 19:39:28 -0800 Subject: [PATCH] Allow Handlers as callbacks. Add EventLoop.close(). --- pep-3156.txt | 62 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/pep-3156.txt b/pep-3156.txt index 9a6e2cf10..590d92ed3 100644 --- a/pep-3156.txt +++ b/pep-3156.txt @@ -148,10 +148,18 @@ loop per thread. 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 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: @@ -173,15 +181,6 @@ A conforming event loop object has the following methods: 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_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 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 ``callback(*args)`` to be called approximately ``delay`` seconds in 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`` is received, arrange for ``callback(*args)`` to be called. Returns 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 previous handler (only one handler can be active per signal). The ``sig`` must be a valid sigal number defined in the ``signal`` 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 - signale (e.g. ``SIGKILL``), RuntimeError if this particular event + ``ValueError`` if it is not a valid signal or if it is an uncatchable + signale (e.g. ``SIGKILL``), ``RuntimeError`` if this particular event loop instance cannot handle signals (since signals are global per process, only an event loop associated with the main thread can handle signals). - ``remove_signal_handler(sig)``. Removes the handler for signal ``sig``, if one is set. Raises the same exceptions as - ``add_signal_handler()``. - -- TBD: A way to register a callback that is already wrapped in a - ``Handler``. Maybe ``call_soon()`` could just check - ``isinstance(callback, Handler)``? It should silently skip - a cancelled callback. + ``add_signal_handler()`` (except that it may return ``False`` + instead raising ``RuntimeError`` for uncatchable signals). Returns + ``True``e\ if a handler was removed successfully, ``False`` if no + handler was set. 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 compatible with the event loop (i.e., a ``tulip.Future`` instance). -- ``run_in_executor(executor, function, *args)``. Arrange to call - ``function(*args)`` in an executor (see PEP 3148). Returns a Future +- ``run_in_executor(executor, callback, *args)``. Arrange to call + ``callback(*args)`` in an executor (see PEP 3148). Returns a Future 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 threads is used. (TBD: Should the default executor be shared - between different event loops? Should we even have a default - executor? Should be be able to set its thread count? Shoul we even - have this method?) + between different event loops?) - ``set_default_executor(executor)``. Set the default executor used by ``run_in_executor()``.