|
| 1 | +.. currentmodule:: asyncio |
| 2 | + |
| 3 | + |
| 4 | +========= |
| 5 | +Extending |
| 6 | +========= |
| 7 | + |
| 8 | +The main direction for :mod:`asyncio` extending is writing custom *event loop* |
| 9 | +classes. Asyncio has helpers that could be used to simplify this task. |
| 10 | + |
| 11 | +.. note:: |
| 12 | + |
| 13 | + Third-parties should reuse existing asyncio code with caution, |
| 14 | + a new Python version is free to break backward compatibility |
| 15 | + in *internal* part of API. |
| 16 | + |
| 17 | + |
| 18 | +Writing a Custom Event Loop |
| 19 | +=========================== |
| 20 | + |
| 21 | +:class:`asyncio.AbstractEventLoop` declares very many methods. Implementing all them |
| 22 | +from scratch is a tedious job. |
| 23 | + |
| 24 | +A loop can get many common methods implementation for free by inheriting from |
| 25 | +:class:`asyncio.BaseEventLoop`. |
| 26 | + |
| 27 | +In turn, the successor should implement a bunch of *private* methods declared but not |
| 28 | +implemented in :class:`asyncio.BaseEventLoop`. |
| 29 | + |
| 30 | +For example, ``loop.create_connection()`` checks arguments, resolves DNS addresses, and |
| 31 | +calls ``loop._make_socket_transport()`` that should be implemented by inherited class. |
| 32 | +The ``_make_socket_transport()`` method is not documented and is considered as an |
| 33 | +*internal* API. |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +Future and Task private constructors |
| 38 | +==================================== |
| 39 | + |
| 40 | +:class:`asyncio.Future` and :class:`asyncio.Task` should be never created directly, |
| 41 | +please use corresponding :meth:`loop.create_future` and :meth:`loop.create_task`, |
| 42 | +or :func:`asyncio.create_task` factories instead. |
| 43 | + |
| 44 | +However, third-party *event loops* may *reuse* built-in future and task implementations |
| 45 | +for the sake of getting a complex and highly optimized code for free. |
| 46 | + |
| 47 | +For this purpose the following, *private* constructors are listed: |
| 48 | + |
| 49 | +.. method:: Future.__init__(*, loop=None) |
| 50 | + |
| 51 | +Create a built-in future instance. |
| 52 | + |
| 53 | +*loop* is an optional event loop instance. |
| 54 | + |
| 55 | +.. method:: Task.__init__(coro, *, loop=None, name=None, context=None) |
| 56 | + |
| 57 | +Create a built-in task instance. |
| 58 | + |
| 59 | +*loop* is an optional event loop instance. The rest of arguments are described in |
| 60 | +:meth:`loop.create_task` description. |
| 61 | + |
| 62 | + |
| 63 | +Task lifetime support |
| 64 | +===================== |
| 65 | + |
| 66 | +A third party task implementation should call the following functions to keep a task |
| 67 | +visible by :func:`asyncio.get_tasks` and :func:`asyncio.current_task`: |
| 68 | + |
| 69 | +.. function:: _register_task(task) |
| 70 | + |
| 71 | + Register a new *task* as managed by *asyncio*. |
| 72 | + |
| 73 | + Call the function from a task constructor. |
| 74 | + |
| 75 | +.. function:: _unregister_task(task) |
| 76 | + |
| 77 | + Unregister a *task* from *asyncio* internal structures. |
| 78 | + |
| 79 | + The function should be called when a task is about to finish. |
| 80 | + |
| 81 | +.. function:: _enter_task(loop, task) |
| 82 | + |
| 83 | + Switch the current task to the *task* argument. |
| 84 | + |
| 85 | + Call the function just before executing a portion of embedded *coroutine* |
| 86 | + (:meth:`coroutine.send` or :meth:`coroutine.throw`). |
| 87 | + |
| 88 | +.. function:: _leave_task(loop, task) |
| 89 | + |
| 90 | + Switch the current task back from *task* to ``None``. |
| 91 | + |
| 92 | + Call the function just after :meth:`coroutine.send` or :meth:`coroutine.throw` |
| 93 | + execution. |
0 commit comments