From 764ee3b72cc8770f7c398ba1aee41fbd34f07764 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 28 Aug 2022 22:51:52 +0200 Subject: [PATCH] futures: add block_on --- embassy-futures/src/block_on.rs | 31 +++++++++++++++++++++++++++++++ embassy-futures/src/lib.rs | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 embassy-futures/src/block_on.rs diff --git a/embassy-futures/src/block_on.rs b/embassy-futures/src/block_on.rs new file mode 100644 index 00000000..749fa67f --- /dev/null +++ b/embassy-futures/src/block_on.rs @@ -0,0 +1,31 @@ +use core::future::Future; +use core::pin::Pin; +use core::ptr; +use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; + +static VTABLE: RawWakerVTable = RawWakerVTable::new(|_| RawWaker::new(ptr::null(), &VTABLE), |_| {}, |_| {}, |_| {}); + +/// Run a future to completion using a busy loop. +/// +/// This calls `.poll()` on the future in a busy loop, which blocks +/// the current thread at 100% cpu usage until the future is done. The +/// future's `Waker` mechanism is not used. +/// +/// It's suitable for systems with no or limited concurrency and without +/// strict requirements around power consumption. For more complex use +/// cases, prefer using a "real" executor like `embassy-executor`, which +/// supports multiple tasks, and putting the core to sleep when no task +/// needs to do work. +pub fn block_on(mut fut: F) -> F::Output { + // safety: we don't move the future after this line. + let mut fut = unsafe { Pin::new_unchecked(&mut fut) }; + + let raw_waker = RawWaker::new(ptr::null(), &VTABLE); + let waker = unsafe { Waker::from_raw(raw_waker) }; + let mut cx = Context::from_waker(&waker); + loop { + if let Poll::Ready(res) = fut.as_mut().poll(&mut cx) { + return res; + } + } +} diff --git a/embassy-futures/src/lib.rs b/embassy-futures/src/lib.rs index 45bea252..41e27047 100644 --- a/embassy-futures/src/lib.rs +++ b/embassy-futures/src/lib.rs @@ -5,8 +5,10 @@ // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; +mod block_on; mod select; mod yield_now; +pub use block_on::*; pub use select::*; pub use yield_now::*;