[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