I'm wondering if my read of the overall design is correct:
Executor starts and polls all futures in the pool of tasks (one pass).
At the end of a pass of polling futures, if there's still tasks, the executor parks the thread.
When a future is ready to make progress, it wakes up the executor by unparking the thread through a waker.
Executor makes another pass of all futures in the pool of tasks.
When there's no more tasks in the pool, the executor returns.
I want to understand this properly, since I think that in a more sophisticated executor, there might be separate pools of awake and asleep tasks, and only awake tasks are polled.
So please let me know if I have any misconceptions about how executors work!
It sounds about right. Note that in more sophisticated executors such as Tokio, IO is typically implemented by replacing the thread parking with a sleep on an api such as epoll that waits for IO events in a list of IO resources to have any progress, and timers are implemented by putting a timeout on that epoll sleep.