Waker
Earlier, we saw that when RawTask::run
is called, run
creates a waker
which is used to poll
the user-provided Future
. In this section, we look at how the Waker
instance is created.
To create a waker
in Rust, we need to pass a RawWakerVTable
to the Waker
constructor.
Here is the vtable for the task:
impl<F, R, S> RawTask<F, R, S>
where
F: Future<Output = R>,
S: Fn(Task),
{
const RAW_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
Self::clone_waker,
Self::wake,
Self::wake_by_ref,
Self::drop_waker,
);
The most important method here is the wake
method, which is invoked when Waker::wake
is called.
The Waker::wake()
simply reschedules the task by pushing it onto the TaskQueue
. Here is the implementation of wake
and wake_by_ref
:
#![allow(unused)] fn main() { unsafe fn wake(ptr: *const ()) { Self::wake_by_ref(ptr); Self::drop_waker(ptr); } /// Wakes a waker. Ptr is the raw task. unsafe fn wake_by_ref(ptr: *const ()) { let raw = Self::from_ptr(ptr); let state = (*raw.header).state; // If the task is completed or closed, it can't be woken up. if state & (COMPLETED | CLOSED) == 0 { // If the task is already scheduled do nothing. if state & SCHEDULED == 0 { // Mark the task as scheduled. (*(raw.header as *mut Header)).state = state | SCHEDULED; if state & RUNNING == 0 { // Schedule the task. Self::schedule(ptr); } } } } }
The schedule method is passed to the task
when the task is created and it looks something like:
let schedule = move |task| {
let task_queue = tq.upgrade();
task_queue.local_queue.push(task);
};
create_task(executor_id, future, schedule)
Finally, here is the code that actually creates the waker
which is used to poll the user-defined future.
#![allow(unused)] fn main() { let waker = ManuallyDrop::new(Waker::from_raw(RawWaker::new(ptr, &Self::RAW_WAKER_VTABLE))); let cx = &mut Context::from_waker(&waker); let poll = <F as Future>::poll(Pin::new_unchecked(&mut *raw.future), cx); }
Code References
To check out my toy implementation or Glommio’s implementation, check out:
My Toy Implementation
Glommio