1use core::future::Future;
2use core::pin::Pin;
3use core::ptr;
4use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
5
6static VTABLE: RawWakerVTable = RawWakerVTable::new(|_| RawWaker::new(ptr::null(), &VTABLE), |_| {}, |_| {}, |_| {});
7
8/// Run a future to completion using a busy loop.
9///
10/// This calls `.poll()` on the future in a busy loop, which blocks
11/// the current thread at 100% cpu usage until the future is done. The
12/// future's `Waker` mechanism is not used.
13///
14/// You can use this to run multiple futures concurrently with [`join`][crate::join].
15///
16/// It's suitable for systems with no or limited concurrency and without
17/// strict requirements around power consumption. For more complex use
18/// cases, prefer using a "real" executor like `embassy-executor`, which
19/// supports multiple tasks, and putting the core to sleep when no task
20/// needs to do work.
21pub fn block_on<F: Future>(mut fut: F) -> F::Output {
22 // safety: we don't move the future after this line.
23 let mut fut: Pin<&mut F> = unsafe { Pin::new_unchecked(&mut fut) };
24
25 let raw_waker: RawWaker = RawWaker::new(data:ptr::null(), &VTABLE);
26 let waker: Waker = unsafe { Waker::from_raw(raw_waker) };
27 let mut cx: Context<'_> = Context::from_waker(&waker);
28 loop {
29 if let Poll::Ready(res: ::Output) = fut.as_mut().poll(&mut cx) {
30 return res;
31 }
32 }
33}
34
35/// Poll a future once.
36pub fn poll_once<F: Future>(mut fut: F) -> Poll<F::Output> {
37 // safety: we don't move the future after this line.
38 let mut fut: Pin<&mut F> = unsafe { Pin::new_unchecked(&mut fut) };
39
40 let raw_waker: RawWaker = RawWaker::new(data:ptr::null(), &VTABLE);
41 let waker: Waker = unsafe { Waker::from_raw(raw_waker) };
42 let mut cx: Context<'_> = Context::from_waker(&waker);
43
44 fut.as_mut().poll(&mut cx)
45}
46