I'm new to asyncio and trying to understand how it actually works.
Lets say we have two corutines and one of them looks like this:
async def f():
asyncio.sleep() returns a
The future's value will be set after timeout expiring.
Every coroutine is executed by
asyncio.Task. The future is bubbled up to task runner (
The runner adds a callback to bubbled future for waking up itself when future will be done.
sleep() implementation is trivial:
@coroutine def sleep(delay, result=None, *, loop=None): """Coroutine that completes after a given time (in seconds).""" if delay == 0: yield return result if loop is None: loop = events.get_event_loop() future = loop.create_future() h = future._loop.call_later(delay, futures._set_result_unless_cancelled, future, result) try: return (yield from future) finally: h.cancel()
Task runner is much more complex beast but it's source code is still readable: https://github.com/python/asyncio/blob/master/asyncio/tasks.py#L223-L300
Every blocking IO returns a future too (maybe from very deep internal call). When IO waiting is done the given value (or exception) is assigned to the future, task runner is woken up and suspended coroutine is resumed.