Extending
*********

The main direction for "asyncio" extending is writing custom *event
loop* classes. Asyncio has helpers that could be used to simplify this
task.

Note:

  Third-parties should reuse existing asyncio code with caution, a new
  Python version is free to break backward compatibility in *internal*
  part of API.


Writing a Custom Event Loop
===========================

"asyncio.AbstractEventLoop" declares very many methods.  Implementing
all them from scratch is a tedious job.

A loop can get many common methods implementation for free by
inheriting from "asyncio.BaseEventLoop".

In turn, the successor should implement a bunch of *private* methods
declared but not implemented in "asyncio.BaseEventLoop".

For example, "loop.create_connection()" checks arguments, resolves DNS
addresses, and calls "loop._make_socket_transport()" that should be
implemented by inherited class. The "_make_socket_transport()" method
is not documented and is considered as an *internal* API.


Future and Task private constructors
====================================

"asyncio.Future" and "asyncio.Task" should be never created directly,
please use corresponding "loop.create_future()" and
"loop.create_task()", or "asyncio.create_task()" factories instead.

However, third-party *event loops* may *reuse* built-in future and
task implementations for the sake of getting a complex and highly
optimized code for free.

For this purpose the following, *private* constructors are listed:

Future.__init__(*, loop=None)

   Create a built-in future instance.

   *loop* is an optional event loop instance.

Task.__init__(coro, *, loop=None, name=None, context=None)

   Create a built-in task instance.

   *loop* is an optional event loop instance. The rest of arguments
   are described in "loop.create_task()" description.

   Changed in version 3.11: *context* argument is added.

Task._check_future(future)

   Return "True" if *future* is attached to the same loop as the task,
   "False" otherwise.

   New in version 3.11.


Task lifetime support
=====================

A third party task implementation should call the following functions
to keep a task visible by "asyncio.get_tasks()" and
"asyncio.current_task()":

asyncio._register_task(task)

   Register a new *task* as managed by *asyncio*.

   Call the function from a task constructor.

asyncio._unregister_task(task)

   Unregister a *task* from *asyncio* internal structures.

   The function should be called when a task is about to finish.

asyncio._enter_task(loop, task)

   Switch the current task to the *task* argument.

   Call the function just before executing a portion of embedded
   *coroutine* ("coroutine.send()" or "coroutine.throw()").

asyncio._leave_task(loop, task)

   Switch the current task back from *task* to "None".

   Call the function just after "coroutine.send()" or
   "coroutine.throw()" execution.
