I'm writing a Future
executor (crates.io, docs) for my single-threaded, embedded target. Unlike most other implementations, I have no threads or interrupts, so there is no need for synchronization. Currently, I'm using the unstable Wake
trait like this:
struct TaskWaker {
wake_marker: AtomicBool,
}
impl TaskWaker {
fn wake_task(&self) {
self.wake_marker.store(true, Ordering::Relaxed);
}
}
impl Wake for TaskWaker {
fn wake(self: Arc<Self>) {
self.wake_task();
}
fn wake_by_ref(self: &Arc<Self>) {
self.wake_task();
}
}
/// Spawns a task and blocks until the future resolves, returning its result.
pub fn block_on<T>(listeners: &AsyncListeners, task: impl Future<Output = T>) -> T {
let wake_marker = Arc::new(TaskWaker {
wake_marker: AtomicBool::new(true),
});
let waker = Waker::from(wake_marker.clone());
let mut context = Context::from_waker(&waker);
pin_mut!(task);
let mut task = task;
// Poll it, look at the GitHub for the full source
unimplemented!()
}
Is there a more efficient way to do this? My target, which is ARMv5TE, doesn't have atomic instructions. I don't know if this means that Arc
acts as an Rc
or if it emulates atomics itself, which would be unnecessary or slow.
I'm thinking that I should just reimplement this using RawWaker
and Rc
. Are there any examples or crates doing this? (I would assume not, I haven't seen any other executors that don't use threads or interrupts)