Tokio interaction with Epoll object

When we say that for network sockets we have os level async sys calls which can help us achieve almost single threaded concurrency, how Tokio knows that the future is waiting on such network socket or waiting on file io ? What I understand by looking into the code in Tokio, functions just assume we have a future, meaning we just have poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> method, which will just return the state of the future (which does not give any information about the .await on which it is waiting). I am confused on who is calling the waker.wake() bit ? if it's Tokio then how Tokio is knowing about the epoll object which is having the events corresponding to the futures on which we are waiting ? If I am not wrong, rust does not provide that information to us. This is the only part which is not making sense in the whole rust async story.

poll_read on a TcpStream calls

which indirectly calls

which calls

This last function registers the fd with epoll and stores the waker. I haven't looked at the details, but I think the tokio runtime then calls epoll on every loop iteration running the registered waker for every fd that is ready and then polls all tasks for which the waker has been called.

2 Likes

Thanks @bjorn3 for the snippets, I went through them and I think this makes sense.