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
methods, and still conform to the other methods.)
- Resource management: ``close()``.
- Miscellaneous: ``close()``, ``time()``.
- Starting and stopping: ``run_forever()``, ``run_until_complete()``,
``stop()``, ``is_running()``.
- Basic callbacks: ``call_soon()``, ``call_later()``,
``call_repeatedly()``.
- Basic callbacks: ``call_soon()``, ``call_later()``, ``call_at()``.
- Thread interaction: ``call_soon_threadsafe()``,
``wrap_future()``, ``run_in_executor()``,
@ -303,8 +302,8 @@ of this choice. Better read the docs for the stdandard library
Required Event Loop Methods
---------------------------
Resource Management
'''''''''''''''''''
Miscellaneous
'''''''''''''
- ``close()``. Closes the event loop, releasing any resources it may
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
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
'''''''''''''''''''''
@ -362,17 +367,27 @@ Basic Callbacks
``callback(*args)`` to be called approximately ``delay`` seconds in
the future, once, unless cancelled. Returns a Handle representing
the callback, whose ``cancel()`` method can be used to cancel the
callback. If ``delay`` is <= 0, this acts like ``call_soon()``
instead. Otherwise, callbacks scheduled for exactly the same time
will be called in an undefined order.
callback. Callbacks scheduled in the past or at exactly the same
time will be called in an undefined order.
- ``call_repeatedly(interval, callback, **args)``. Like
``call_later()`` but calls the callback repeatedly, every (approximately)
``interval`` seconds, until the Handle returned is cancelled or
the callback raises an exception. The first call is in
approximately ``interval`` seconds. If for whatever reason the
callback happens later than scheduled, subsequent callbacks will be
delayed for (at least) the same amount. The ``interval`` must be > 0.
- ``call_at(when, callback, *args)``. This is like ``call_later()``,
but the time is expressed as an absolute time. There is a simple
equivalency: ``loop.call_later(delay, callback, *args)`` is the same
as ``loop.call_at(loop.time() + delay, callback, *args)``.
Note: A previous version of this PEP defined a method named
``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
''''''''''''''''''
@ -656,12 +671,9 @@ one kind of pseudo-tty on OSX that is supported by ``select`` and
- ``add_reader(fd, callback, *args)``. Arrange for
``callback(*args)`` to be called whenever file descriptor ``fd`` is
deemed ready for reading. Returns a Handle object which can be used
to cancel the callback. (However, it is strongly preferred to use
``remove_reader()`` instead.) Calling ``add_reader()`` again for
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?)
deemed ready for reading. Calling ``add_reader()`` again for the
same file descriptor implies a call to ``remove_reader()`` for the
same file descriptor.
- ``add_writer(fd, callback, *args)``. Like ``add_reader()``,
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
descriptor ``fd``, if one is set. If no callback is currently set
for the file descriptor, this is a no-op and returns ``False``.
Otherwise, it removes the callback arrangement, cancels the
corresponding Handle, and returns ``True``.
Otherwise, it removes the callback arrangement and returns ``True``.
- ``remove_writer(fd)``. This is to ``add_writer()`` as
``remove_reader()`` is to ``add_reader()``.
@ -704,11 +715,7 @@ Signal callbacks
''''''''''''''''
- ``add_signal_handler(sig, callback, *args). Whenever signal ``sig``
is received, arrange for ``callback(*args)`` to be called. Returns
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.)
is received, arrange for ``callback(*args)`` to be called.
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``
@ -777,11 +784,12 @@ most other exceptions.)
Handles
-------
The various methods for registering callbacks (e.g. ``call_soon()``
and ``add_reader()``) all return an object representing the
registration that can be used to cancel the callback. This object is
called a Handle (although its class name is not necessarily
``Handle``). Handles are opaque and have only one public method:
The various methods for registering one-off callbacks
(``call_soon()``, ``call_later()`` and ``call_at()``) all return an
object representing the registration that can be used to cancel the
callback. This object is called a Handle (although its class name is
not necessarily ``Handle``). Handles are opaque and have only one
public method:
- ``cancel()``. Cancel the callback.
@ -1354,10 +1362,6 @@ off the coroutine when ``connection_made()`` is called.
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?
- 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
to separate transports and protocols.
- PEP 418 discusses the issues of timekeeping.
- Tulip repo: http://code.google.com/p/tulip/
- Nick Coghlan wrote a nice blog post with some background, thoughts