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

ambee/giterated

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

MOre pre vtable changes

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨9cfa135

⁨giterated-plugin/src/future.rs⁩ - ⁨4187⁩ 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, FFIBox};
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 }
65
66 unsafe extern "C" fn poll_local(
67 _future: FfiValueMut<FfiFuture<()>>,
68 mut future_state: FfiValueMut<()>,
69 ) -> RuntimeFuturePoll {
70 let mut future_state: FfiValueMut<BoxFuture<'static, FfiValue<()>>> = transmute(future_state);
71
72 let runtime_future = future_state.as_ref();
73
74 let raw_waker = RawWaker::new(
75 Box::into_raw(Box::new(runtime_future)) as *const (),
76 &RUNTIME_FUTURE_WAKER_VTABLE,
77 );
78
79 let waker = unsafe { Waker::from_raw(raw_waker) };
80
81 // SAFETY: Pretty sure this has to be static lol
82 let poll_result = future_state.poll_unpin(&mut Context::from_waker(&waker));
83
84 match poll_result {
85 std::task::Poll::Ready(result) => RuntimeFuturePoll::Ready(result),
86 std::task::Poll::Pending => RuntimeFuturePoll::Pending,
87 }
88 }
89
90 pub static RUNTIME_FUTURE_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
91 runtime_waker_vtable::waker_clone,
92 runtime_waker_vtable::waker_wake,
93 runtime_waker_vtable::waker_wake_by_ref,
94 runtime_waker_vtable::waker_drop,
95 );
96
97 mod runtime_waker_vtable {
98 use std::task::RawWaker;
99
100 pub unsafe fn waker_clone(_data: *const ()) -> RawWaker {
101 todo!()
102 }
103
104 pub unsafe fn waker_wake(_data: *const ()) {
105 todo!()
106 }
107
108 pub unsafe fn waker_wake_by_ref(_data: *const ()) {
109 todo!()
110 }
111
112 pub unsafe fn waker_drop(_data: *const ()) {
113 // no-op
114 }
115 }
116
117 #[repr(transparent)]
118 pub struct RuntimeFuture<Output>(FfiFuture<Output>);
119
120 /// Allows for a remote future to be polled on the target.
121 ///
122 /// The target can be the host or a plugin, but the future should only be polled by one
123 /// source.
124 impl<Output: Unpin> Future for RuntimeFuture<Output> {
125 type Output = Output;
126
127 fn poll(
128 mut self: std::pin::Pin<&mut Self>,
129 cx: &mut Context<'_>,
130 ) -> std::task::Poll<Self::Output> {
131 let waker_state = WakerState {
132 waker: cx.waker().clone(),
133 };
134
135 let waker_state = PluginState::from(waker_state);
136
137 unsafe { self.0.write_waker(wake_local, waker_state) };
138
139 match unsafe { self.0.poll() } {
140 RuntimeFuturePoll::Ready(result) => {
141 let result: FfiValue<Output> = unsafe { transmute(result) };
142
143 std::task::Poll::Ready(result.take())
144 }
145 RuntimeFuturePoll::Pending => std::task::Poll::Pending,
146 }
147 }
148 }
149
150 unsafe extern "C" fn wake_local(future: FfiValueMut<FfiFuture<()>>, state: FfiValueMut<()>) {
151 todo!()
152 }
153