1#![allow(dead_code, unused)]
2use std::{
3 sync::{Arc, Condvar, Mutex},
4 task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
5};
6
7use futures::Future;
8
9pub struct InlineWaker {
10 lock: Mutex<()>,
11 condvar: Condvar,
12}
13impl InlineWaker {
14 pub fn new() -> Arc<Self> {
15 Arc::new(Self {
16 lock: Mutex::new(()),
17 condvar: Condvar::new(),
18 })
19 }
20
21 fn wake_now(&self) {
22 #[cfg(not(feature = "js"))]
26 let _guard = self.lock.lock().unwrap();
27
28 self.condvar.notify_all();
29 }
30
31 pub fn as_waker(self: &Arc<Self>) -> Waker {
32 let s: *const Self = Arc::into_raw(Arc::clone(self));
33 let raw_waker = RawWaker::new(s as *const (), &VTABLE);
34 unsafe { Waker::from_raw(raw_waker) }
35 }
36
37 #[cfg(not(feature = "js"))]
38 pub fn block_on<'a, A>(task: impl Future<Output = A> + 'a) -> A {
39 futures::executor::block_on(task)
40 }
41
42 #[cfg(feature = "js")]
43 pub fn block_on<'a, A>(task: impl Future<Output = A> + 'a) -> A {
44 let inline_waker = Self::new();
46 let waker = inline_waker.as_waker();
47 let mut cx = Context::from_waker(&waker);
48
49 let mut task = Box::pin(task);
51 loop {
52 let lock = inline_waker.lock.lock().unwrap();
53 match task.as_mut().poll(&mut cx) {
54 Poll::Pending => {
55 inline_waker.condvar.wait(lock).ok();
56 }
57 Poll::Ready(ret) => {
58 return ret;
59 }
60 }
61 }
62 }
63}
64
65fn inline_waker_wake(s: &InlineWaker) {
66 let waker_arc = unsafe { Arc::from_raw(s) };
67 waker_arc.wake_now();
68}
69
70fn inline_waker_clone(s: &InlineWaker) -> RawWaker {
71 let arc = unsafe { Arc::from_raw(s) };
72 std::mem::forget(arc.clone());
73 RawWaker::new(Arc::into_raw(arc) as *const (), &VTABLE)
74}
75
76const VTABLE: RawWakerVTable = unsafe {
77 RawWakerVTable::new(
78 |s| inline_waker_clone(&*(s as *const InlineWaker)), |s| inline_waker_wake(&*(s as *const InlineWaker)), |s| (*(s as *const InlineWaker)).wake_now(), |s| drop(Arc::from_raw(s as *const InlineWaker)), )
83};