JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Before

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨e432306

⁨giterated-plugin/src/future.rs⁩ - ⁨4214⁩ bytes
Raw
1 use futures_util::future::BoxFuture;
2 use futures_util::FutureExt;
3 use giterated_abi::{FfiFuture, FfiValue, FfiValueMut, RuntimeFuturePoll};
4 use std::{
5 cell::UnsafeCell,
6 future::Future,
7 marker::PhantomData,
8 mem::transmute,
9 task::{Context, RawWaker, RawWakerVTable, Waker},
10 };
11
12 use crate::{callback::RuntimeState, new_stack::PluginState};
13
14 #[repr(C)]
15 pub struct RuntimeWakerCallback {
16 callback: PluginState,
17 waker_func: unsafe extern "C" fn(PluginState),
18 }
19
20 pub struct WakerState {
21 waker: Waker,
22 }
23
24 unsafe extern "C" fn wake(_waker: PluginState) {}
25
26 pub struct LocalRuntimeFuture<Output> {
27 inner: BoxFuture<'static, Output>,
28 runtime_future: UnsafeCell<FfiFuture<Output>>,
29 }
30
31 unsafe impl<Output> Send for LocalRuntimeFuture<Output> where Output: Send {}
32 unsafe impl<Output> Sync for LocalRuntimeFuture<Output> where Output: Sync {}
33
34 impl<Output> LocalRuntimeFuture<Output> {
35 pub fn finalize(self) {}
36
37 pub fn into_runtime(&self) -> FfiFuture<Output> {
38 todo!()
39 }
40 }
41
42 pub trait RuntimeFuturesExt {
43 fn spawn_future<Output, F: Future<Output = Output> + Send + Sync + 'static>(
44 &self,
45 future: F,
46 ) -> RuntimeFuture<Output>;
47 }
48
49 impl RuntimeFuturesExt for RuntimeState {
50 fn spawn_future<Output, F: Future<Output = Output> + Send + Sync + 'static>(
51 &self,
52 future: F,
53 ) -> RuntimeFuture<Output> {
54 // let type_eraser = async move {
55 // let result = future.await;
56
57 // FFIBox::from_box(Box::new(result)).untyped()
58 // };
59
60 // let runtime_future = unsafe { FfiFuture::from_raw(poll_local, type_eraser.boxed()) };
61
62 // RuntimeFuture(runtime_future)
63
64 todo!()
65 }
66 }
67
68 unsafe extern "C" fn poll_local(
69 _future: FfiValueMut<FfiFuture<()>>,
70 mut future_state: FfiValueMut<()>,
71 ) -> RuntimeFuturePoll {
72 let mut future_state: FfiValueMut<BoxFuture<'static, FfiValue<()>>> = transmute(future_state);
73
74 let runtime_future = future_state.as_ref();
75
76 let raw_waker = RawWaker::new(
77 Box::into_raw(Box::new(runtime_future)) as *const (),
78 &RUNTIME_FUTURE_WAKER_VTABLE,
79 );
80
81 let waker = unsafe { Waker::from_raw(raw_waker) };
82
83 // SAFETY: Pretty sure this has to be static lol
84 let poll_result = future_state.poll_unpin(&mut Context::from_waker(&waker));
85
86 match poll_result {
87 std::task::Poll::Ready(result) => RuntimeFuturePoll::Ready(result),
88 std::task::Poll::Pending => RuntimeFuturePoll::Pending,
89 }
90 }
91
92 pub static RUNTIME_FUTURE_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
93 runtime_waker_vtable::waker_clone,
94 runtime_waker_vtable::waker_wake,
95 runtime_waker_vtable::waker_wake_by_ref,
96 runtime_waker_vtable::waker_drop,
97 );
98
99 mod runtime_waker_vtable {
100 use std::task::RawWaker;
101
102 pub unsafe fn waker_clone(_data: *const ()) -> RawWaker {
103 todo!()
104 }
105
106 pub unsafe fn waker_wake(_data: *const ()) {
107 todo!()
108 }
109
110 pub unsafe fn waker_wake_by_ref(_data: *const ()) {
111 todo!()
112 }
113
114 pub unsafe fn waker_drop(_data: *const ()) {
115 // no-op
116 }
117 }
118
119 #[repr(transparent)]
120 pub struct RuntimeFuture<Output>(FfiFuture<Output>);
121
122 /// Allows for a remote future to be polled on the target.
123 ///
124 /// The target can be the host or a plugin, but the future should only be polled by one
125 /// source.
126 impl<Output: Unpin> Future for RuntimeFuture<Output> {
127 type Output = Output;
128
129 fn poll(
130 mut self: std::pin::Pin<&mut Self>,
131 cx: &mut Context<'_>,
132 ) -> std::task::Poll<Self::Output> {
133 let waker_state = WakerState {
134 waker: cx.waker().clone(),
135 };
136
137 let waker_state = PluginState::from(waker_state);
138
139 unsafe { self.0.write_waker(wake_local, waker_state) };
140
141 match unsafe { self.0.poll() } {
142 RuntimeFuturePoll::Ready(result) => {
143 let result: FfiValue<Output> = unsafe { transmute(result) };
144
145 std::task::Poll::Ready(result.take())
146 }
147 RuntimeFuturePoll::Pending => std::task::Poll::Pending,
148 }
149 }
150 }
151
152 unsafe extern "C" fn wake_local(future: FfiValueMut<FfiFuture<()>>, state: FfiValueMut<()>) {
153 todo!()
154 }
155