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

ambee/giterated

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

Structure refactoring

Amber - ⁨1⁩ year ago

parent: tbd commit: ⁨a8f41ac

⁨giterated-plugin/src/future.rs⁩ - ⁨4152⁩ 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 #[repr(C)]
13 pub struct RuntimeWakerCallback {
14 callback: PluginState,
15 waker_func: unsafe extern "C" fn(PluginState),
16 }
17
18 pub struct WakerState {
19 waker: Waker,
20 }
21
22 unsafe extern "C" fn wake(_waker: PluginState) {}
23
24 pub struct LocalRuntimeFuture<Output> {
25 inner: BoxFuture<'static, Output>,
26 runtime_future: UnsafeCell<FfiFuture<Output>>,
27 }
28
29 unsafe impl<Output> Send for LocalRuntimeFuture<Output> where Output: Send {}
30 unsafe impl<Output> Sync for LocalRuntimeFuture<Output> where Output: Sync {}
31
32 impl<Output> LocalRuntimeFuture<Output> {
33 pub fn finalize(self) {}
34
35 pub fn into_runtime(&self) -> FfiFuture<Output> {
36 todo!()
37 }
38 }
39
40 pub trait RuntimeFuturesExt {
41 fn spawn_future<Output, F: Future<Output = Output> + Send + Sync + 'static>(
42 &self,
43 future: F,
44 ) -> RuntimeFuture<Output>;
45 }
46
47 impl RuntimeFuturesExt for RuntimeState {
48 fn spawn_future<Output, F: Future<Output = Output> + Send + Sync + 'static>(
49 &self,
50 future: F,
51 ) -> RuntimeFuture<Output> {
52 // let type_eraser = async move {
53 // let result = future.await;
54
55 // FFIBox::from_box(Box::new(result)).untyped()
56 // };
57
58 // let runtime_future = unsafe { FfiFuture::from_raw(poll_local, type_eraser.boxed()) };
59
60 // RuntimeFuture(runtime_future)
61
62 todo!()
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