Per this post, the OP described his understanding of how futures::local_pool
works. Thanks to his insights, which helped me building up an basic understanding of it.
However, when I got more seriously digging into the code, I realized that the implementation of futures::local_pool
is actually more sophisticated than what the OP described - it is actually a very comprehensive implementation of a single-threaded executor not just for toy projects!
The implementation is not just polling all the (top-level) futures in a loop - the actual LocalPool::pool
is of type FuturesUnordered
, whose Stream::poll_next
method (StreamExt::poll_next_unpin
) interally does the magic of replacing the outer waker context (which simply unpark
s the thread) with an internal task waker context, which contains a waker from Task<Fut>
, whose ArcWake::wake_by_ref
method queues the future to the FuturesUnordered::ready_to_run_queue
, and then invokes the outter wake to unpark the thread to process the ready futures - so essentially, the local_pool executor only polls the ready futures, if any, at every top level LocalPool::poll_pool
method.
As to the IO/timers wakeup side, I think it's the "reactor" part of the executor that the local_pool executor doesn't (and probably wouldn't) address, which basically just uses the whatever waker reference to wakeup the future - though I'm pretty sure that the waker reference would be the Task::wake_by_ref
as mentioned above (actually queues the ready future to the ready_to_run_futures
queue.
Hopefully, this understanding of local_pool executor is correct?