Pre-RFC Idea: `RefWake` trait

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?

1 Like

Surely someone would have made this before!

(both for you to use now, and to show that it’s a design that could move into the stdlib eventually)

EDIT: oops, except they don’t have a no_std mode (yet?)

It's unconditionally #![no_std]. That's even better.

…but also unconditionally extern crate alloc. :frowning: