<p dir="ltr"><br>
On 3 May 2013 08:34, "guido.van.rossum" <<a href="mailto:python-checkins@python.org">python-checkins@python.org</a>> wrote:<br>
><br>
> <a href="http://hg.python.org/peps/rev/26947623fc5d">http://hg.python.org/peps/rev/26947623fc5d</a><br>
> changeset:   4870:26947623fc5d<br>
> user:        Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>><br>
> date:        Thu May 02 14:11:08 2013 -0700<br>
> summary:<br>
>   Add time(), call_at(). Remove call_repeatedly(). Get rid of add_*_handler() return value.<br>
><br>
> files:<br>
>   pep-3156.txt |  80 +++++++++++++++++++++------------------<br>
>   1 files changed, 43 insertions(+), 37 deletions(-)<br>
><br>
><br>
> diff --git a/pep-3156.txt b/pep-3156.txt<br>
> --- a/pep-3156.txt<br>
> +++ b/pep-3156.txt<br>
> @@ -252,13 +252,12 @@<br>
>  implementation may choose not to implement the internet/socket<br>
>  methods, and still conform to the other methods.)<br>
><br>
> -- Resource management: ``close()``.<br>
> +- Miscellaneous: ``close()``, ``time()``.<br>
><br>
>  - Starting and stopping: ``run_forever()``, ``run_until_complete()``,<br>
>    ``stop()``, ``is_running()``.<br>
><br>
> -- Basic callbacks: ``call_soon()``, ``call_later()``,<br>
> -  ``call_repeatedly()``.<br>
> +- Basic callbacks: ``call_soon()``, ``call_later()``, ``call_at()``.<br>
><br>
>  - Thread interaction: ``call_soon_threadsafe()``,<br>
>    ``wrap_future()``, ``run_in_executor()``,<br>
> @@ -303,8 +302,8 @@<br>
>  Required Event Loop Methods<br>
>  ---------------------------<br>
><br>
> -Resource Management<br>
> -'''''''''''''''''''<br>
> +Miscellaneous<br>
> +'''''''''''''<br>
><br>
>  - ``close()``.  Closes the event loop, releasing any resources it may<br>
>    hold, such as the file descriptor used by ``epoll()`` or<br>
> @@ -313,6 +312,12 @@<br>
>    again.  It may be called multiple times; subsequent calls are<br>
>    no-ops.<br>
><br>
> +- ``time()``.  Returns the current time according to the event loop's<br>
> +  clock.  This may be ``time.time()`` or ``time.monotonic()`` or some<br>
> +  other system-specific clock, but it must return a float expressing<br>
> +  the time in units of approximately one second since some epoch.<br>
> +  (No clock is perfect -- see PEP 418.)</p>
<p dir="ltr">Should the PEP allow event loops that use decimal.Decimal?</p>
<p dir="ltr">> +<br>
>  Starting and Stopping<br>
>  '''''''''''''''''''''<br>
><br>
> @@ -362,17 +367,27 @@<br>
>    ``callback(*args)`` to be called approximately ``delay`` seconds in<br>
>    the future, once, unless cancelled.  Returns a Handle representing<br>
>    the callback, whose ``cancel()`` method can be used to cancel the<br>
> -  callback.  If ``delay`` is <= 0, this acts like ``call_soon()``<br>
> -  instead.  Otherwise, callbacks scheduled for exactly the same time<br>
> -  will be called in an undefined order.<br>
> +  callback.  Callbacks scheduled in the past or at exactly the same<br>
> +  time will be called in an undefined order.<br>
><br>
> -- ``call_repeatedly(interval, callback, **args)``.  Like<br>
> -  ``call_later()`` but calls the callback repeatedly, every (approximately)<br>
> -  ``interval`` seconds, until the Handle returned is cancelled or<br>
> -  the callback raises an exception.  The first call is in<br>
> -  approximately ``interval`` seconds.  If for whatever reason the<br>
> -  callback happens later than scheduled, subsequent callbacks will be<br>
> -  delayed for (at least) the same amount.  The ``interval`` must be > 0.<br>
> +- ``call_at(when, callback, *args)``.  This is like ``call_later()``,<br>
> +  but the time is expressed as an absolute time.  There is a simple<br>
> +  equivalency: ``loop.call_later(delay, callback, *args)`` is the same<br>
> +  as ``loop.call_at(loop.time() + delay, callback, *args)``.</p>
<p dir="ltr">It may be worth explicitly noting the time scales where floating point's dynamic range starts to significantly limit granularity.</p>
<p dir="ltr">Cheers,<br>
Nick.</p>
<p dir="ltr">> +<br>
> +Note: A previous version of this PEP defined a method named<br>
> +``call_repeatedly()``, which promised to call a callback at regular<br>
> +intervals.  This has been withdrawn because the design of such a<br>
> +function is overspecified.  On the one hand, a simple timer loop can<br>
> +easily be emulated using a callback that reschedules itself using<br>
> +``call_later()``; it is also easy to write coroutine containing a loop<br>
> +and a ``sleep()`` call (a toplevel function in the module, see below).<br>
> +On the other hand, due to the complexities of accurate timekeeping<br>
> +there are many traps and pitfalls here for the unaware (see PEP 418),<br>
> +and different use cases require different behavior in edge cases.  It<br>
> +is impossible to offer an API for this purpose that is bullet-proof in<br>
> +all cases, so it is deemed better to let application designers decide<br>
> +for themselves what kind of timer loop to implement.<br>
><br>
>  Thread interaction<br>
>  ''''''''''''''''''<br>
> @@ -656,12 +671,9 @@<br>
><br>
>  - ``add_reader(fd, callback, *args)``.  Arrange for<br>
>    ``callback(*args)`` to be called whenever file descriptor ``fd`` is<br>
> -  deemed ready for reading.  Returns a Handle object which can be used<br>
> -  to cancel the callback.  (However, it is strongly preferred to use<br>
> -  ``remove_reader()`` instead.)  Calling ``add_reader()`` again for<br>
> -  the same file descriptor implies a call to ``remove_reader()`` for<br>
> -  the same file descriptor.  (TBD: Since cancelling the Handle is not<br>
> -  recommended, perhaps we should return None instead?)<br>
> +  deemed ready for reading.  Calling ``add_reader()`` again for the<br>
> +  same file descriptor implies a call to ``remove_reader()`` for the<br>
> +  same file descriptor.<br>
><br>
>  - ``add_writer(fd, callback, *args)``.  Like ``add_reader()``,<br>
>    but registers the callback for writing instead of for reading.<br>
> @@ -669,8 +681,7 @@<br>
>  - ``remove_reader(fd)``.  Cancels the current read callback for file<br>
>    descriptor ``fd``, if one is set.  If no callback is currently set<br>
>    for the file descriptor, this is a no-op and returns ``False``.<br>
> -  Otherwise, it removes the callback arrangement, cancels the<br>
> -  corresponding Handle, and returns ``True``.<br>
> +  Otherwise, it removes the callback arrangement and returns ``True``.<br>
><br>
>  - ``remove_writer(fd)``.  This is to ``add_writer()`` as<br>
>    ``remove_reader()`` is to ``add_reader()``.<br>
> @@ -704,11 +715,7 @@<br>
>  ''''''''''''''''<br>
><br>
>  - ``add_signal_handler(sig, callback, *args).  Whenever signal ``sig``<br>
> -  is received, arrange for ``callback(*args)`` to be called.  Returns<br>
> -  a Handle which can be used to cancel the signal callback.<br>
> -  (Cancelling the handle causes ``remove_signal_handler()`` to be<br>
> -  called the next time the signal arrives.  Explicitly calling<br>
> -  ``remove_signal_handler()`` is preferred.)<br>
> +  is received, arrange for ``callback(*args)`` to be called.<br>
>    Specifying another callback for the same signal replaces the<br>
>    previous handler (only one handler can be active per signal).  The<br>
>    ``sig`` must be a valid sigal number defined in the ``signal``<br>
> @@ -777,11 +784,12 @@<br>
>  Handles<br>
>  -------<br>
><br>
> -The various methods for registering callbacks (e.g. ``call_soon()``<br>
> -and ``add_reader()``) all return an object representing the<br>
> -registration that can be used to cancel the callback.  This object is<br>
> -called a Handle (although its class name is not necessarily<br>
> -``Handle``).  Handles are opaque and have only one public method:<br>
> +The various methods for registering one-off callbacks<br>
> +(``call_soon()``, ``call_later()`` and ``call_at()``) all return an<br>
> +object representing the registration that can be used to cancel the<br>
> +callback.  This object is called a Handle (although its class name is<br>
> +not necessarily ``Handle``).  Handles are opaque and have only one<br>
> +public method:<br>
><br>
>  - ``cancel()``.  Cancel the callback.<br>
><br>
> @@ -1354,10 +1362,6 @@<br>
>  Open Issues<br>
>  ===========<br>
><br>
> -- A ``time()`` method that returns the time according to the function<br>
> -  used by the scheduler (e.g. ``time.monotonic()`` in Tulip's case)?<br>
> -  What's the use case?<br>
> -<br>
>  - A fuller public API for Handle?  What's the use case?<br>
><br>
>  - Should we require all event loops to implement ``sock_recv()`` and<br>
> @@ -1410,6 +1414,8 @@<br>
>  - PEP 3153, while rejected, has a good write-up explaining the need<br>
>    to separate transports and protocols.<br>
><br>
> +- PEP 418 discusses the issues of timekeeping.<br>
> +<br>
>  - Tulip repo: <a href="http://code.google.com/p/tulip/">http://code.google.com/p/tulip/</a><br>
><br>
>  - Nick Coghlan wrote a nice blog post with some background, thoughts<br>
><br>
> --<br>
> Repository URL: <a href="http://hg.python.org/peps">http://hg.python.org/peps</a><br>
><br>
> _______________________________________________<br>
> Python-checkins mailing list<br>
> <a href="mailto:Python-checkins@python.org">Python-checkins@python.org</a><br>
> <a href="http://mail.python.org/mailman/listinfo/python-checkins">http://mail.python.org/mailman/listinfo/python-checkins</a><br>
><br>
</p>