There currently exists no safe way to construct a Waker
with custom behavior without allocating. To counter this, I propose a new trait in core::task
: RefWake
, which allows constructing a waker by an &'static
reference to a type which implements RefWake
.
For me, this largely comes up in working with firmware devices, where the tasks are statically-known at compile time, so the runtime and associated wakers can be statically allocated and placed in their corresponding spots, and for which dynamic memory allocation sometimes isn't allowed.
I'm imagining an API like this:
pub trait RefWake {
fn wake_by_ref(&self);
}
impl<W: RefWake + Sync> From<&'static W> for Waker {
fn from(waker: &'static W) -> Waker;
}
The implementation of the waker is simple, as clone
just copies the data and vtable pointers (since shared references can be copied), wake
and wake_by_ref
both cast the data pointer to W
and call RefWake::wake_by_ref
, and drop
doesn't have to do anything (we just have a reference, so we're not responsible for cleanup). I have a local implementation of this API (except I have to put the -> Waker
function on RefWake
instead because of the orphan rule), and it seems to work fine.
Noodling about with this design, it works for entirely safe and alloc-free definition of custom Waker
behavior.
What do people think about this proposal? Is it something anyone else would use?