Add time(), call_at(). Remove call_repeatedly(). Get rid of add_*_handler() return value.

This commit is contained in:
Guido van Rossum 2013-05-02 14:11:08 -07:00
parent d223705ffc
commit 26e00e21ac
1 changed files with 43 additions and 37 deletions

View File

@ -252,13 +252,12 @@ implementations. (However, in some cases a partially-conforming
implementation may choose not to implement the internet/socket implementation may choose not to implement the internet/socket
methods, and still conform to the other methods.) methods, and still conform to the other methods.)
- Resource management: ``close()``. - Miscellaneous: ``close()``, ``time()``.
- Starting and stopping: ``run_forever()``, ``run_until_complete()``, - Starting and stopping: ``run_forever()``, ``run_until_complete()``,
``stop()``, ``is_running()``. ``stop()``, ``is_running()``.
- Basic callbacks: ``call_soon()``, ``call_later()``, - Basic callbacks: ``call_soon()``, ``call_later()``, ``call_at()``.
``call_repeatedly()``.
- Thread interaction: ``call_soon_threadsafe()``, - Thread interaction: ``call_soon_threadsafe()``,
``wrap_future()``, ``run_in_executor()``, ``wrap_future()``, ``run_in_executor()``,
@ -303,8 +302,8 @@ of this choice. Better read the docs for the stdandard library
Required Event Loop Methods Required Event Loop Methods
--------------------------- ---------------------------
Resource Management Miscellaneous
''''''''''''''''''' '''''''''''''
- ``close()``. Closes the event loop, releasing any resources it may - ``close()``. Closes the event loop, releasing any resources it may
hold, such as the file descriptor used by ``epoll()`` or hold, such as the file descriptor used by ``epoll()`` or
@ -313,6 +312,12 @@ Resource Management
again. It may be called multiple times; subsequent calls are again. It may be called multiple times; subsequent calls are
no-ops. no-ops.
- ``time()``. Returns the current time according to the event loop's
clock. This may be ``time.time()`` or ``time.monotonic()`` or some
other system-specific clock, but it must return a float expressing
the time in units of approximately one second since some epoch.
(No clock is perfect -- see PEP 418.)
Starting and Stopping Starting and Stopping
''''''''''''''''''''' '''''''''''''''''''''
@ -362,17 +367,27 @@ Basic Callbacks
``callback(*args)`` to be called approximately ``delay`` seconds in ``callback(*args)`` to be called approximately ``delay`` seconds in
the future, once, unless cancelled. Returns a Handle representing the future, once, unless cancelled. Returns a Handle representing
the callback, whose ``cancel()`` method can be used to cancel the the callback, whose ``cancel()`` method can be used to cancel the
callback. If ``delay`` is <= 0, this acts like ``call_soon()`` callback. Callbacks scheduled in the past or at exactly the same
instead. Otherwise, callbacks scheduled for exactly the same time time will be called in an undefined order.
will be called in an undefined order.
- ``call_repeatedly(interval, callback, **args)``. Like - ``call_at(when, callback, *args)``. This is like ``call_later()``,
``call_later()`` but calls the callback repeatedly, every (approximately) but the time is expressed as an absolute time. There is a simple
``interval`` seconds, until the Handle returned is cancelled or equivalency: ``loop.call_later(delay, callback, *args)`` is the same
the callback raises an exception. The first call is in as ``loop.call_at(loop.time() + delay, callback, *args)``.
approximately ``interval`` seconds. If for whatever reason the
callback happens later than scheduled, subsequent callbacks will be Note: A previous version of this PEP defined a method named
delayed for (at least) the same amount. The ``interval`` must be > 0. ``call_repeatedly()``, which promised to call a callback at regular
intervals. This has been withdrawn because the design of such a
function is overspecified. On the one hand, a simple timer loop can
easily be emulated using a callback that reschedules itself using
``call_later()``; it is also easy to write coroutine containing a loop
and a ``sleep()`` call (a toplevel function in the module, see below).
On the other hand, due to the complexities of accurate timekeeping
there are many traps and pitfalls here for the unaware (see PEP 418),
and different use cases require different behavior in edge cases. It
is impossible to offer an API for this purpose that is bullet-proof in
all cases, so it is deemed better to let application designers decide
for themselves what kind of timer loop to implement.
Thread interaction Thread interaction
'''''''''''''''''' ''''''''''''''''''
@ -656,12 +671,9 @@ one kind of pseudo-tty on OSX that is supported by ``select`` and
- ``add_reader(fd, callback, *args)``. Arrange for - ``add_reader(fd, callback, *args)``. Arrange for
``callback(*args)`` to be called whenever file descriptor ``fd`` is ``callback(*args)`` to be called whenever file descriptor ``fd`` is
deemed ready for reading. Returns a Handle object which can be used deemed ready for reading. Calling ``add_reader()`` again for the
to cancel the callback. (However, it is strongly preferred to use same file descriptor implies a call to ``remove_reader()`` for the
``remove_reader()`` instead.) Calling ``add_reader()`` again for same file descriptor.
the same file descriptor implies a call to ``remove_reader()`` for
the same file descriptor. (TBD: Since cancelling the Handle is not
recommended, perhaps we should return None instead?)
- ``add_writer(fd, callback, *args)``. Like ``add_reader()``, - ``add_writer(fd, callback, *args)``. Like ``add_reader()``,
but registers the callback for writing instead of for reading. but registers the callback for writing instead of for reading.
@ -669,8 +681,7 @@ one kind of pseudo-tty on OSX that is supported by ``select`` and
- ``remove_reader(fd)``. Cancels the current read callback for file - ``remove_reader(fd)``. Cancels the current read callback for file
descriptor ``fd``, if one is set. If no callback is currently set descriptor ``fd``, if one is set. If no callback is currently set
for the file descriptor, this is a no-op and returns ``False``. for the file descriptor, this is a no-op and returns ``False``.
Otherwise, it removes the callback arrangement, cancels the Otherwise, it removes the callback arrangement and returns ``True``.
corresponding Handle, and returns ``True``.
- ``remove_writer(fd)``. This is to ``add_writer()`` as - ``remove_writer(fd)``. This is to ``add_writer()`` as
``remove_reader()`` is to ``add_reader()``. ``remove_reader()`` is to ``add_reader()``.
@ -704,11 +715,7 @@ Signal callbacks
'''''''''''''''' ''''''''''''''''
- ``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.
a Handle which can be used to cancel the signal callback.
(Cancelling the handle 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``
@ -777,11 +784,12 @@ most other exceptions.)
Handles Handles
------- -------
The various methods for registering callbacks (e.g. ``call_soon()`` The various methods for registering one-off callbacks
and ``add_reader()``) all return an object representing the (``call_soon()``, ``call_later()`` and ``call_at()``) all return an
registration that can be used to cancel the callback. This object is object representing the registration that can be used to cancel the
called a Handle (although its class name is not necessarily callback. This object is called a Handle (although its class name is
``Handle``). Handles are opaque and have only one public method: not necessarily ``Handle``). Handles are opaque and have only one
public method:
- ``cancel()``. Cancel the callback. - ``cancel()``. Cancel the callback.
@ -1354,10 +1362,6 @@ off the coroutine when ``connection_made()`` is called.
Open Issues Open Issues
=========== ===========
- A ``time()`` method that returns the time according to the function
used by the scheduler (e.g. ``time.monotonic()`` in Tulip's case)?
What's the use case?
- A fuller public API for Handle? What's the use case? - A fuller public API for Handle? What's the use case?
- Should we require all event loops to implement ``sock_recv()`` and - Should we require all event loops to implement ``sock_recv()`` and
@ -1410,6 +1414,8 @@ References
- PEP 3153, while rejected, has a good write-up explaining the need - PEP 3153, while rejected, has a good write-up explaining the need
to separate transports and protocols. to separate transports and protocols.
- PEP 418 discusses the issues of timekeeping.
- Tulip repo: http://code.google.com/p/tulip/ - Tulip repo: http://code.google.com/p/tulip/
- Nick Coghlan wrote a nice blog post with some background, thoughts - Nick Coghlan wrote a nice blog post with some background, thoughts