[Python-checkins] peps: Add some event loop methods returning Futures. Lots of TBD.

guido.van.rossum python-checkins at python.org
Thu Dec 13 20:05:58 CET 2012


http://hg.python.org/peps/rev/8d817ef8eadd
changeset:   4605:8d817ef8eadd
user:        Guido van Rossum <guido at google.com>
date:        Thu Dec 13 11:05:52 2012 -0800
summary:
  Add some event loop methods returning Futures.  Lots of TBD.

files:
  pep-3156.txt |  63 ++++++++++++++++++++++++++++++++-------
  1 files changed, 51 insertions(+), 12 deletions(-)


diff --git a/pep-3156.txt b/pep-3156.txt
--- a/pep-3156.txt
+++ b/pep-3156.txt
@@ -147,6 +147,7 @@
 ..
   Look for a better way to format method docs.  PEP 12 doesn't
   seem to have one.  PEP 418 uses ^^^, which makes sub-headings.
+  Also think of adding subheadings.
 
 - ``run()``.  Runs the event loop until there is nothing left to do.
   This means, in particular:
@@ -177,11 +178,53 @@
 - ``call_soon_threadsafe(callback, *args)``.  Like
   ``call_soon(callback, *args)``, but when called from another thread
   while the event loop is blocked waiting for I/O, unblocks the event
-  loop.  This is the _only_ method that is safe to call from another
+  loop.  This is the *only* method that is safe to call from another
   thread or from a signal handler.  (To schedule a callback for a
   later time in a threadsafe manner, you can use
   ``ev.call_soon_threadsafe(ev.call_later, when, callback, *args)``.)
 
+Some methods return Futures:
+
+- ``wrap_future(future)``.  This takes a PEP 3148 Future (i.e., an
+  instance of ``concurrent.futures.Future``) and returns a Future
+  compatible with this event loop.
+
+- ``run_in_executor(executor, function, *args)``.  Arrange to call
+  ``function(*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
+  ``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?)
+
+- ``getaddrinfo(host, port, family=0, type=0, proto=0, flags=0)``.
+  Similar to the ``socket.getaddrinfo()`` function but returns a
+  Future.  The Future's result on success will be a list of the same
+  format as returned by ``socket.getaddrinfo()``.  The default
+  implementation calls ``socket.getaddrinfo()`` using
+  ``run_in_executor()``, but other implementations may choose to
+  implement their own DNS lookup.
+
+- ``getnameinfo(sockaddr, flags)``.  Similar to
+  ``socket.getnameinfo()`` but returns a Future.  The Future's result
+  on success will be a tuple ``(host, port)``.  Same implementation
+  remarks as for ``getaddrinfo()``.
+
+- ``create_transport(...)``.  Creates a transport.  Returns a Future.
+  TBD: Signature.  Do we pass in a protocol or protocol class?
+
+- ``start_serving(...)``.  Enters a loop that accepts connections.
+  TBD: Signature.  This definitely takes a protocol class.  Do we pass
+  in a non-blocking socket that's already bound and listening, or do
+  we pass in arguments that let it create and configure the socket
+  properly?  (E.g. the event loop may know a better default backlog
+  value for ``listen()`` than the typical application developer.)
+  TBD: What does it return?  Something we can use to stop accepting
+  without stopping the event loop?  A Future that completes when the
+  socket is successfully accepting connections?
+
 The following methods for registering callbacks for file descriptors
 are optional.  If they are not implemented, accessing the method
 (without calling it) returns AttributeError.  The default
@@ -235,16 +278,12 @@
   socket must be in listening mode and bound to an address.  Returns a
   ``Future`` whose result on success will be a tuple ``(conn, peer)``
   where ``conn`` is a connected non-blocking socket and ``peer`` is
-  the peer address.
+  the peer address.  (TBD: People tell me that this style of API is
+  too slow for high-volume servers.  So there's also
+  ``start_serving()`` above.)
 
 Other TBD:
 
-- TBD: A method to submit a call to a PEP 3148 executor.  Or a method
-  to wait for a PEP 3148 Future.  Or both.
-
-- TBD: Methods that return ``Futures``, in particular to make a
-  connection and to set up a listener.
-
 - TBD: Do we need introspection APIs?  E.g. asking for the read
   callback given a file descriptor.  Or when the next scheduled call
   is.  Or the list of file descriptors registered with callbacks.
@@ -315,11 +354,11 @@
 ``foo()``, use ``ev.call_soon(foo)``.  This convention greatly reduces
 the number of small lambdas required in typical callback programming.
 
-This convention specifically does _not_ support keyword arguments.
+This convention specifically does *not* support keyword arguments.
 Keyword arguments are used to pass optional extra information about
 the callback.  This allows graceful evolution of the API without
 having to worry about whether a keyword might be significant to a
-callee somewhere.  If you have a callback that _must_ be called with a
+callee somewhere.  If you have a callback that *must* be called with a
 keyword argument, you can use a lambda or ``functools.partial``.  For
 example::
 
@@ -345,10 +384,10 @@
   will be called in the right context.)
 
 - Returning a Future is relatively expensive, and it is quite possible
-  that some types of calls _usually_ complete immediately
+  that some types of calls *usually* complete immediately
   (e.g. writing small amounts of data to a socket).  A trick used by
   Richard Oudkerk in the tulip project's proactor branch makes calls
-  like recv() either return a regular result or _raise_ a Future.  The
+  like recv() either return a regular result or *raise* a Future.  The
   caller (likely a transport) must then write code like this::
 
     try:

-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list