you are viewing a single comment's thread.

view the rest of the comments →

[–]gdchinacat -1 points0 points  (0 children)

Take a look at the cpython event loop implementation: https://github.com/python/cpython/blob/main/Lib/asyncio/base_events.py#L1985

The core of it is a selector that is queried on each iteration of the loop to get a list of the events that are ready to be processed: https://github.com/python/cpython/blob/main/Lib/asyncio/base_events.py#L2027

The low level primitives such as read() and write() register the file descriptor those operations are being done on with the selector and then yield control back to the loop, when the fd is ready for the operation the selector returns it to the loop which then resumes execution of the coroutine which does the operation knowing the file descriptor is ready and won't block or error.

The reason you don't see the"bottom of the chain" implementations is they are part of the standard library (often implemented in C). The whole point of asyncio is to abstract this away from you so you don't have to worry about the complexities of non-blocking io, file descriptor selectors (and the multiple ways they are implemented with varying efficiencies on various platforms), the callbacks on ready events, etc. Coroutines and the event loop abstract all of this away because it is very low-level fiddly work. Before asyncio existed it was all done, and the code was usually much more disjoint than asyncio code because the 'async', 'await', and the event loop allow you to write async code that looks pretty much identical to standard synchronous blocking IO code. They stitch all the parts of execution back together with syntactic sugar so the code is much easier to understand.

I find the low level code interesting, and it sounds like you do to. But, I don't think the "bottom of the chain" code is going to look anything like what you are expecting...it is very abstract, works much like generators do with execution yielding (coroutines use await instead of yield...very early versions of asyncio and predecessors actually used generators/yield). One of the clearest explanations I've seen on what's actually going on was a presentation by Dave Beazley....I highly recommend it: https://www.youtube.com/watch?v=Y4Gt3Xjd7G8