1use std::future::Future;
2use std::pin::Pin;
3use std::sync::{Arc, Mutex};
4use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
5
6use crate::Error;
7
8#[derive(Default)]
10pub struct FrameFuture {
11 done: bool,
12}
13
14impl Future for FrameFuture {
15 type Output = ();
16
17 fn poll(mut self: Pin<&mut Self>, _context: &mut Context) -> Poll<Self::Output> {
18 if self.done {
19 Poll::Ready(())
23 } else {
24 self.done = true;
25 Poll::Pending
26 }
27 }
28}
29
30pub struct FileLoadingFuture {
31 pub contents: Arc<Mutex<Option<Result<Vec<u8>, Error>>>>,
32}
33
34impl Future for FileLoadingFuture {
35 type Output = Result<Vec<u8>, Error>;
36
37 fn poll(self: Pin<&mut Self>, _context: &mut Context) -> Poll<Self::Output> {
38 let mut contents = self.contents.lock().unwrap();
39 if let Some(contents) = contents.take() {
40 Poll::Ready(contents)
41 } else {
42 Poll::Pending
43 }
44 }
45}
46
47fn waker() -> Waker {
48 unsafe fn clone(data: *const ()) -> RawWaker {
49 RawWaker::new(data, &VTABLE)
50 }
51 unsafe fn wake(_data: *const ()) {
52 panic!(
53 "macroquad does not support waking futures, please use coroutines, \
54 otherwise your pending future will block until the next frame"
55 )
56 }
57 unsafe fn wake_by_ref(data: *const ()) {
58 wake(data);
59 }
60 unsafe fn drop(_data: *const ()) {
61 }
63 const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
64 let raw_waker = RawWaker::new(std::ptr::null(), &VTABLE);
65 unsafe { Waker::from_raw(raw_waker) }
66}
67
68pub(crate) fn resume<T>(future: &mut Pin<Box<dyn Future<Output = T>>>) -> Option<T> {
70 let waker = waker();
71 let mut futures_context = std::task::Context::from_waker(&waker);
72 match future.as_mut().poll(&mut futures_context) {
73 Poll::Ready(v) => Some(v),
74 Poll::Pending => None,
75 }
76}