From aea82293be0a56937fe807a0d2a44c7db392f155 Mon Sep 17 00:00:00 2001
From: Victor Stinner <victor.stinner@gmail.com>
Date: Tue, 8 Jul 2014 23:42:38 +0200
Subject: [PATCH] Issue #21680: Document asyncio event loops

---
 Doc/library/asyncio-eventloop.rst  |  82 +-------------
 Doc/library/asyncio-eventloops.rst | 176 +++++++++++++++++++++++++++++
 Doc/library/asyncio-subprocess.rst |  24 ++--
 Doc/library/asyncio.rst            |   1 +
 4 files changed, 195 insertions(+), 88 deletions(-)
 create mode 100644 Doc/library/asyncio-eventloops.rst

diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst
index 1a80921e15a..c82ea48f897 100644
--- a/Doc/library/asyncio-eventloop.rst
+++ b/Doc/library/asyncio-eventloop.rst
@@ -2,8 +2,8 @@
 
 .. _asyncio-event-loop:
 
-Event loops
-===========
+Base Event Loop
+===============
 
 The event loop is the central execution device provided by :mod:`asyncio`.
 It provides multiple facilities, amongst which:
@@ -18,78 +18,9 @@ It provides multiple facilities, amongst which:
 
 * Delegating costly function calls to a pool of threads.
 
-Event loop policies and the default policy
-------------------------------------------
+.. class:: BaseEventLoop
 
-Event loop management is abstracted with a *policy* pattern, to provide maximal
-flexibility for custom platforms and frameworks. Throughout the execution of a
-process, a single global policy object manages the event loops available to the
-process based on the calling context. A policy is an object implementing the
-:class:`AbstractEventLoopPolicy` interface.
-
-For most users of :mod:`asyncio`, policies never have to be dealt with
-explicitly, since the default global policy is sufficient.
-
-The default policy defines context as the current thread, and manages an event
-loop per thread that interacts with :mod:`asyncio`. The module-level functions
-:func:`get_event_loop` and :func:`set_event_loop` provide convenient access to
-event loops managed by the default policy.
-
-Event loop functions
---------------------
-
-The following functions are convenient shortcuts to accessing the methods of the
-global policy. Note that this provides access to the default policy, unless an
-alternative policy was set by calling :func:`set_event_loop_policy` earlier in
-the execution of the process.
-
-.. function:: get_event_loop()
-
-   Equivalent to calling ``get_event_loop_policy().get_event_loop()``.
-
-.. function:: set_event_loop(loop)
-
-   Equivalent to calling ``get_event_loop_policy().set_event_loop(loop)``.
-
-.. function:: new_event_loop()
-
-   Equivalent to calling ``get_event_loop_policy().new_event_loop()``.
-
-Event loop policy interface
----------------------------
-
-An event loop policy must implement the following interface:
-
-.. class:: AbstractEventLoopPolicy
-
-   .. method:: get_event_loop()
-
-   Get the event loop for the current context. Returns an event loop object
-   implementing the :class:`BaseEventLoop` interface, or raises an exception in case
-   no event loop has been set for the current context and the current policy
-   does not specify to create one. It should never return ``None``.
-
-   .. method:: set_event_loop(loop)
-
-   Set the event loop for the current context to *loop*.
-
-   .. method:: new_event_loop()
-
-   Create and return a new event loop object according to this policy's rules.
-   If there's need to set this loop as the event loop for the current context,
-   :meth:`set_event_loop` must be called explicitly.
-
-Access to the global loop policy
---------------------------------
-
-.. function:: get_event_loop_policy()
-
-   Get the current event loop policy.
-
-.. function:: set_event_loop_policy(policy)
-
-   Set the current event loop policy. If *policy* is ``None``, the default
-   policy is restored.
+   Base class of event loops.
 
 Run an event loop
 -----------------
@@ -375,7 +306,6 @@ Creating listening connections
    Availability: UNIX.
 
 
-
 Watch file descriptors
 ----------------------
 
@@ -624,7 +554,6 @@ Debug mode
 
    The :ref:`debug mode of asyncio <asyncio-debug-mode>`.
 
-
 Server
 ------
 
@@ -652,7 +581,8 @@ Handle
 
    .. method:: cancel()
 
-   Cancel the call.
+      Cancel the call.
+
 
 
 .. _asyncio-hello-world-callback:
diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst
new file mode 100644
index 00000000000..b530d3c889e
--- /dev/null
+++ b/Doc/library/asyncio-eventloops.rst
@@ -0,0 +1,176 @@
+.. currentmodule:: asyncio
+
+Event loops
+===========
+
+Event loop functions
+--------------------
+
+The following functions are convenient shortcuts to accessing the methods of the
+global policy. Note that this provides access to the default policy, unless an
+alternative policy was set by calling :func:`set_event_loop_policy` earlier in
+the execution of the process.
+
+.. function:: get_event_loop()
+
+   Equivalent to calling ``get_event_loop_policy().get_event_loop()``.
+
+.. function:: set_event_loop(loop)
+
+   Equivalent to calling ``get_event_loop_policy().set_event_loop(loop)``.
+
+.. function:: new_event_loop()
+
+   Equivalent to calling ``get_event_loop_policy().new_event_loop()``.
+
+
+Available event loops
+---------------------
+
+asyncio currently provides two implementations of event loops:
+:class:`SelectorEventLoop` and :class:`ProactorEventLoop`.
+
+.. class:: SelectorEventLoop
+
+   Event loop based on the :mod:`selectors` module. Subclass of
+   :class:`BaseEventLoop`.
+
+   Use the most efficient selector available on the platform.
+
+.. class:: ProactorEventLoop
+
+   Proactor event loop for Windows using "I/O Completion Ports" aka IOCP.
+   Subclass of :class:`BaseEventLoop`.
+
+   Availability: Windows.
+
+   .. seealso::
+
+      `MSDN documentation on I/O Completion Ports
+      <http://msdn.microsoft.com/en-us/library/windows/desktop/aa365198%28v=vs.85%29.aspx>`_.
+
+Example to use a :class:`ProactorEventLoop` on Windows::
+
+    import asyncio, os
+
+    if os.name == 'nt':
+        loop = asyncio.ProactorEventLoop()
+        asyncio.set_event_loop(loop)
+
+
+Platform support
+----------------
+
+The :mod:`asyncio` module has been designed to be portable, but each platform
+still has subtle differences and may not support all :mod:`asyncio` features.
+
+Windows
+^^^^^^^
+
+Common limits of Windows event loops:
+
+- :meth:`~BaseEventLoop.create_unix_server` and
+  :meth:`~BaseEventLoop.create_unix_server` are not supported: specific to UNIX
+- :meth:`~BaseEventLoop.add_signal_handler` and
+  :meth:`~BaseEventLoop.remove_signal_handler` are not supported
+- Pipes are not supported: :meth:`~BaseEventLoop.connect_read_pipe` and
+  :meth:`~BaseEventLoop.connect_write_pipe`
+- :meth:`EventLoopPolicy.set_child_watcher` is not supported
+
+:class:`SelectorEventLoop` specific limits:
+
+- :class:`~selectors.SelectSelector` is used but it only supports sockets,
+  see the `MSDN documentation of select
+  <http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx>`_.
+- it is not possible to execute subprocesses
+- :meth:`~BaseEventLoop.add_reader` and :meth:`~BaseEventLoop.add_writer` only
+  accept file descriptors of sockets
+
+:class:`ProactorEventLoop` specific limits:
+
+- SSL is not supported: :meth:`~BaseEventLoop.create_connection` and
+  :meth:`~BaseEventLoop.create_server` cannot be used with SSL for example
+- :meth:`~BaseEventLoop.create_datagram_endpoint` (UDP) is not supported
+- :meth:`~BaseEventLoop.add_reader` and :meth:`~BaseEventLoop.add_writer` are
+  not supported
+
+The resolution of the monotonic clock on Windows is usually around 15.6 msec.
+The best resolution is 0.5 msec. The exact resolution depends on the hardware
+(availability of HPET) and the Windows configuration. See :ref:`asyncio delayed
+calls <asyncio-delayed-calls>`.
+
+
+Mac OS X
+^^^^^^^^
+
+Character devices like PTY are only well supported since Mavericks (Mac OS
+10.9). They are not supported at all on Mac OS 10.5 and older.
+
+On Mac OS 10.6, 10.7 and 10.8, the default event loop is
+:class:`SelectorEventLoop` which uses :class:`selectors.KqueueSelector`.
+:class:`selectors.KqueueSelector` does not support character devices on these
+versions.  The :class:`SelectorEventLoop` can be used with
+:class:`~selectors.SelectSelector` or :class:`~selectors.PollSelector` to
+support character devices on these versions of Mac OS X. Example::
+
+    import asyncio
+    import selectors
+
+    selector = selectors.SelectSelector()
+    loop = asyncio.SelectorEventLoop(selector)
+    asyncio.set_event_loop(loop)
+
+
+Event loop policies and the default policy
+------------------------------------------
+
+Event loop management is abstracted with a *policy* pattern, to provide maximal
+flexibility for custom platforms and frameworks. Throughout the execution of a
+process, a single global policy object manages the event loops available to the
+process based on the calling context. A policy is an object implementing the
+:class:`AbstractEventLoopPolicy` interface.
+
+For most users of :mod:`asyncio`, policies never have to be dealt with
+explicitly, since the default global policy is sufficient.
+
+The default policy defines context as the current thread, and manages an event
+loop per thread that interacts with :mod:`asyncio`. The module-level functions
+:func:`get_event_loop` and :func:`set_event_loop` provide convenient access to
+event loops managed by the default policy.
+
+Event loop policy interface
+---------------------------
+
+An event loop policy must implement the following interface:
+
+.. class:: AbstractEventLoopPolicy
+
+   .. method:: get_event_loop()
+
+   Get the event loop for the current context. Returns an event loop object
+   implementing the :class:`BaseEventLoop` interface, or raises an exception in case
+   no event loop has been set for the current context and the current policy
+   does not specify to create one. It should never return ``None``.
+
+   .. method:: set_event_loop(loop)
+
+   Set the event loop for the current context to *loop*.
+
+   .. method:: new_event_loop()
+
+   Create and return a new event loop object according to this policy's rules.
+   If there's need to set this loop as the event loop for the current context,
+   :meth:`set_event_loop` must be called explicitly.
+
+Access to the global loop policy
+--------------------------------
+
+.. function:: get_event_loop_policy()
+
+   Get the current event loop policy.
+
+.. function:: set_event_loop_policy(policy)
+
+   Set the current event loop policy. If *policy* is ``None``, the default
+   policy is restored.
+
diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst
index 3f57a8211b5..3386bf5f5eb 100644
--- a/Doc/library/asyncio-subprocess.rst
+++ b/Doc/library/asyncio-subprocess.rst
@@ -3,18 +3,18 @@
 Subprocess
 ==========
 
-Operating system support
-------------------------
-
-On Windows, the default event loop uses :class:`selectors.SelectSelector`
-which only supports sockets. The :class:`ProactorEventLoop` should be used to
-support subprocesses. However, the latter does not support SSL.
-
-On Mac OS X older than 10.9 (Mavericks), :class:`selectors.KqueueSelector`
-does not support character devices like PTY, whereas it is used by the
-default event loop. The :class:`SelectorEventLoop` can be used with
-:class:`SelectSelector` or :class:`PollSelector` to handle character
-devices on Mac OS X 10.6 (Snow Leopard) and later.
+Windows event loop
+------------------
+
+On Windows, the default event loop is :class:`SelectorEventLoop` which does not
+support subprocesses. :class:`ProactorEventLoop` should be used instead.
+Example to use it on Windows::
+
+    import asyncio, os
+
+    if os.name == 'nt':
+        loop = asyncio.ProactorEventLoop()
+        asyncio.set_event_loop(loop)
 
 
 Create a subprocess: high-level API using Process
diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst
index 23731b13212..9857c932fde 100644
--- a/Doc/library/asyncio.rst
+++ b/Doc/library/asyncio.rst
@@ -45,6 +45,7 @@ Table of content:
    :maxdepth: 3
 
    asyncio-eventloop.rst
+   asyncio-eventloops.rst
    asyncio-task.rst
    asyncio-protocol.rst
    asyncio-stream.rst
-- 
2.30.9