1use alloc::boxed::Box;
2use alloc::sync::Arc;
3use alloc::task::Wake;
4use core::mem::MaybeUninit;
5use core::pin::pin;
6use core::sync::atomic::Ordering;
7use core::task::{Context, Poll, Waker};
8use log::{debug, trace};
9use crate::threading::{ThreadMeta, ThreadState};
10
11impl Wake for ThreadMeta {
12 fn wake(self: Arc<Self>) {
13 self.wake_by_ref();
14 }
15
16 fn wake_by_ref(self: &Arc<Self>) {
17 trace!("wake thread {:?}", self.thread_id);
18 self.state.store(ThreadState::Ready, Ordering::SeqCst);
19 crate::bridge::threading::unblock_thread(self);
20 }
21}
22
23#[cfg(not(feature = "use_std"))]
25pub fn block_on<T, F: Future<Output = T>>(f: F) -> T {
26 let mut f = pin!(f);
27
28 let val = loop {
29 let waker = {
30 let mut meta = MaybeUninit::<Arc<ThreadMeta>>::uninit();
31 crate::bridge::threading::with_current_thread(meta.as_mut_ptr().cast(), |meta, ptr| {
32 let ptr = ptr.cast::<Arc<ThreadMeta>>();
33 meta.state.store(ThreadState::NearlyParked, Ordering::SeqCst);
34 unsafe { ptr.write(Arc::clone(meta)) };
35 });
36 let meta = unsafe { meta.assume_init() };
37 Waker::from(meta)
38 };
39
40 let mut ctx = Context::from_waker(&waker);
41
42 match f.as_mut().poll(&mut ctx) {
43 Poll::Ready(val) => {
44 debug!("future ready!");
45 crate::bridge::threading::with_current_thread(core::ptr::null_mut(), |meta, _| {
46 let _ = meta.state
47 .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |val| {
48 debug!("block_on replace state {val:?}");
49 match val {
50 ThreadState::Ready => Some(ThreadState::Running),
51 ThreadState::Parked => Some(ThreadState::Running),
52 ThreadState::NearlyParked => Some(ThreadState::Running),
53 _ => None,
54 }
55 });
56 });
57
58 break val;
59 },
60 Poll::Pending => {
61 debug!("future pending :(");
62 crate::bridge::executor::yield_from_async_block();
63 }
64 }
65 };
66
67 val
68}
69
70pub fn spawn(f: impl Future<Output = ()> + 'static) {
77 crate::bridge::executor::spawn_task(Box::pin(f));
78}