1use core::task::Context;
16
17use crate::enums::IDeterminantProvider;
18use crate::option::Option;
19use crate::vtable::HasDropVt;
20use crate::{IPtrMut, IPtrOwned, IStable};
21
22pub use stable_waker::StableWaker;
23#[cfg(stabby_unsafe_wakers = "true")]
24mod stable_waker {
25 use core::task::Waker;
26
27 use crate::StableLike;
28 #[crate::stabby]
35 pub struct StableWaker<'a>(StableLike<&'a Waker, &'a ()>);
36 impl StableWaker<'_> {
37 pub fn with_waker<'a, F: FnOnce(&'a Waker) -> U, U>(&'a self, f: F) -> U {
41 f(unsafe { self.0.as_ref_unchecked() })
42 }
43 }
44 impl<'a> From<&'a Waker> for StableWaker<'a> {
45 fn from(value: &'a Waker) -> Self {
46 Self(StableLike::new(value))
47 }
48 }
49}
50#[cfg(any(not(stabby_unsafe_wakers), stabby_unsafe_wakers = "false"))]
51mod stable_waker {
52 use core::{
53 mem::ManuallyDrop,
54 ptr::NonNull,
55 task::{RawWaker, RawWakerVTable, Waker},
56 };
57
58 use crate::alloc::{sync::Arc, AllocPtr, IAlloc};
59 use crate::StableLike;
60
61 mod seal {
62 use super::*;
63 use crate::Tuple as Tuple2;
64 #[crate::stabby]
65 pub struct StableWakerInner {
66 pub waker: StableLike<ManuallyDrop<Waker>, Tuple2<*const (), &'static ()>>,
67 pub wake_by_ref: StableLike<for<'b> unsafe extern "C" fn(&'b Waker), &'static ()>,
68 pub drop: StableLike<unsafe extern "C" fn(&mut ManuallyDrop<Waker>), &'static ()>,
69 }
70 unsafe impl Send for StableWakerInner where core::task::Waker: Send {}
72 unsafe impl Sync for StableWakerInner where core::task::Waker: Sync {}
74 impl Drop for StableWakerInner {
75 fn drop(&mut self) {
76 unsafe { (self.drop.as_mut_unchecked())(self.waker.as_mut_unchecked()) }
77 }
78 }
79 #[crate::stabby]
80 pub struct SharedStableWaker<Alloc: IAlloc>(pub Arc<StableWakerInner, Alloc>);
81 impl<Alloc: IAlloc> SharedStableWaker<Alloc> {
82 unsafe fn clone(this: *const ()) -> RawWaker {
83 Arc::<_, Alloc>::increment_strong_count(this);
84 RawWaker::new(this, &Self::VTABLE)
85 }
86 unsafe fn drop(this: *const ()) {
87 let this = AllocPtr {
88 ptr: NonNull::new(this as *mut _).unwrap(),
89 marker: core::marker::PhantomData,
90 };
91 let this = Arc::from_raw(this);
92 Self(this);
93 }
94 unsafe fn wake(this: *const ()) {
95 Self::wake_by_ref(this);
96 Self::drop(this);
97 }
98 unsafe fn wake_by_ref(this: *const ()) {
99 let this = unsafe { &*(this as *const StableWakerInner) };
100 (this.wake_by_ref.as_ref_unchecked())(this.waker.as_ref_unchecked())
101 }
102 const VTABLE: RawWakerVTable =
103 RawWakerVTable::new(Self::clone, Self::wake, Self::wake_by_ref, Self::drop);
104 pub fn into_raw_waker(self) -> RawWaker {
105 RawWaker::new(
106 Arc::into_raw(self.0).ptr.as_ptr() as *const _,
107 &Self::VTABLE,
108 )
109 }
110 }
111 }
112 use seal::*;
113 #[crate::stabby]
121 pub struct StableWaker<'a, Alloc: IAlloc = crate::alloc::DefaultAllocator> {
122 waker: StableLike<&'a Waker, &'a ()>,
123 #[allow(improper_ctypes_definitions)]
124 clone: unsafe extern "C" fn(StableLike<&'a Waker, &'a ()>) -> SharedStableWaker<Alloc>,
125 wake_by_ref: StableLike<unsafe extern "C" fn(&Waker), &'a ()>,
126 }
127 impl<Alloc: IAlloc + Default> StableWaker<'_, Alloc> {
128 pub fn with_waker<F: FnOnce(&Waker) -> U, U>(&self, f: F) -> U {
130 const VTABLE: RawWakerVTable =
131 RawWakerVTable::new(clone, wake_by_ref, wake_by_ref, drop);
132 unsafe fn clone(this: *const ()) -> RawWaker {
133 let this = unsafe { &*(this as *const StableWaker) };
134 (this.clone)(this.waker).into_raw_waker()
135 }
136 unsafe fn wake_by_ref(this: *const ()) {
137 let this = unsafe { &*(this as *const StableWaker) };
138 (this.wake_by_ref.as_ref_unchecked())(this.waker.as_ref_unchecked())
139 }
140 const unsafe fn drop(_: *const ()) {}
141 let waker = RawWaker::new(self as *const Self as *const _, &VTABLE);
142 let waker = unsafe { Waker::from_raw(waker) };
143 f(&waker)
144 }
145 unsafe extern "C" fn waker_drop(waker: &mut ManuallyDrop<Waker>) {
146 ManuallyDrop::drop(waker)
147 }
148 unsafe extern "C" fn waker_wake_by_ref(waker: &Waker) {
149 waker.wake_by_ref()
150 }
151 unsafe extern "C" fn clone_borrowed(
152 borrowed_waker: StableLike<&Waker, &()>,
153 ) -> SharedStableWaker<Alloc> {
154 let borrowed_waker = *borrowed_waker.as_ref_unchecked();
155 let waker = borrowed_waker.clone();
156 let waker = StableWakerInner {
157 waker: StableLike::new(ManuallyDrop::new(waker)),
158 wake_by_ref: StableLike::new(Self::waker_wake_by_ref),
159 drop: StableLike::new(Self::waker_drop),
160 };
161 let shared = Arc::new_in(waker, Default::default());
162 SharedStableWaker(shared)
163 }
164 }
165 impl<'a, Alloc: IAlloc + Default> From<&'a Waker> for StableWaker<'a, Alloc> {
166 fn from(value: &'a Waker) -> Self {
167 StableWaker {
168 waker: StableLike::new(value),
169 clone: Self::clone_borrowed,
170 wake_by_ref: StableLike::new(Self::waker_wake_by_ref),
171 }
172 }
173 }
174}
175
176#[crate::stabby]
178pub trait Future {
179 type Output: IDeterminantProvider<()>;
181 extern "C" fn poll<'a>(&'a mut self, waker: StableWaker<'a>) -> Option<Self::Output>;
183}
184impl<T: core::future::Future> Future for T
185where
186 T::Output: IDeterminantProvider<()>,
187{
188 type Output = T::Output;
189 #[allow(improper_ctypes_definitions)]
190 extern "C" fn poll(&mut self, waker: StableWaker) -> Option<Self::Output> {
191 waker.with_waker(|waker| {
192 match core::future::Future::poll(
193 unsafe { core::pin::Pin::new_unchecked(self) },
194 &mut Context::from_waker(waker),
195 ) {
196 core::task::Poll::Ready(v) => Option::Some(v),
197 core::task::Poll::Pending => Option::None(),
198 }
199 })
200 }
201}
202
203impl<Vt: HasDropVt, P: IPtrOwned + IPtrMut, Output: IDeterminantProvider<()>> core::future::Future
204 for crate::Dyn<'_, P, crate::vtable::VTable<StabbyVtableFuture<'_, Output>, Vt>>
205{
206 type Output = Output;
207 fn poll(
208 self: core::pin::Pin<&mut Self>,
209 cx: &mut Context<'_>,
210 ) -> core::task::Poll<Self::Output> {
211 unsafe {
212 let this = core::pin::Pin::get_unchecked_mut(self);
213 (this.vtable().head.poll.as_ref_unchecked())(
214 this.ptr_mut().as_mut(),
215 core::marker::PhantomData,
216 cx.waker().into(),
217 )
218 .match_owned(|v| core::task::Poll::Ready(v), || core::task::Poll::Pending)
219 }
220 }
221}
222
223impl<Vt: HasDropVt, P: IPtrOwned + IPtrMut, Output: IDeterminantProvider<()>> core::future::Future
224 for crate::Dyn<
225 '_,
226 P,
227 crate::vtable::VtSend<crate::vtable::VTable<StabbyVtableFuture<'_, Output>, Vt>>,
228 >
229{
230 type Output = Output;
231 fn poll(
232 self: core::pin::Pin<&mut Self>,
233 cx: &mut Context<'_>,
234 ) -> core::task::Poll<Self::Output> {
235 unsafe {
236 let this = core::pin::Pin::get_unchecked_mut(self);
237 (this.vtable().0.head.poll.as_ref_unchecked())(
238 this.ptr_mut().as_mut(),
239 core::marker::PhantomData,
240 cx.waker().into(),
241 )
242 .match_owned(|v| core::task::Poll::Ready(v), || core::task::Poll::Pending)
243 }
244 }
245}
246
247impl<Vt: HasDropVt, P: IPtrOwned + IPtrMut, Output: IDeterminantProvider<()>> core::future::Future
248 for crate::Dyn<
249 '_,
250 P,
251 crate::vtable::VtSync<crate::vtable::VTable<StabbyVtableFuture<'_, Output>, Vt>>,
252 >
253{
254 type Output = Output;
255 fn poll(
256 self: core::pin::Pin<&mut Self>,
257 cx: &mut Context<'_>,
258 ) -> core::task::Poll<Self::Output> {
259 unsafe {
260 let this = core::pin::Pin::get_unchecked_mut(self);
261 (this.vtable().0.head.poll.as_ref_unchecked())(
262 this.ptr_mut().as_mut(),
263 core::marker::PhantomData,
264 cx.waker().into(),
265 )
266 .match_owned(|v| core::task::Poll::Ready(v), || core::task::Poll::Pending)
267 }
268 }
269}
270
271impl<Vt: HasDropVt, P: IPtrOwned + IPtrMut, Output: IDeterminantProvider<()>> core::future::Future
272 for crate::Dyn<
273 '_,
274 P,
275 crate::vtable::VtSync<
276 crate::vtable::VtSend<crate::vtable::VTable<StabbyVtableFuture<'_, Output>, Vt>>,
277 >,
278 >
279{
280 type Output = Output;
281 fn poll(
282 self: core::pin::Pin<&mut Self>,
283 cx: &mut Context<'_>,
284 ) -> core::task::Poll<Self::Output> {
285 unsafe {
286 let this = core::pin::Pin::get_unchecked_mut(self);
287 (this.vtable().0 .0.head.poll.as_ref_unchecked())(
288 this.ptr_mut().as_mut(),
289 core::marker::PhantomData,
290 cx.waker().into(),
291 )
292 .match_owned(|v| core::task::Poll::Ready(v), || core::task::Poll::Pending)
293 }
294 }
295}
296
297impl<Vt: HasDropVt, P: IPtrOwned + IPtrMut, Output: IDeterminantProvider<()>> core::future::Future
298 for crate::Dyn<
299 '_,
300 P,
301 crate::vtable::VtSend<
302 crate::vtable::VtSync<crate::vtable::VTable<StabbyVtableFuture<'_, Output>, Vt>>,
303 >,
304 >
305{
306 type Output = Output;
307 fn poll(
308 self: core::pin::Pin<&mut Self>,
309 cx: &mut Context<'_>,
310 ) -> core::task::Poll<Self::Output> {
311 unsafe {
312 let this = core::pin::Pin::get_unchecked_mut(self);
313 (this.vtable().0 .0.head.poll.as_ref_unchecked())(
314 this.ptr_mut().as_mut(),
315 core::marker::PhantomData,
316 cx.waker().into(),
317 )
318 .match_owned(|v| core::task::Poll::Ready(v), || core::task::Poll::Pending)
319 }
320 }
321}
322
323impl<'a, Output> crate::vtable::CompoundVt<'a> for dyn core::future::Future<Output = Output>
324where
325 dyn Future<Output = Output>: crate::vtable::CompoundVt<'a>,
326{
327 type Vt<T> = <dyn Future<Output = Output> as crate::vtable::CompoundVt<'a>>::Vt<T>;
328}
329
330#[crate::stabby]
332pub enum MaybeResolved<T, F>
333where
334 F: core::future::Future<Output = T>,
335{
336 Resolved(T),
338 Empty,
340 Pending(F),
342}
343impl<T: IStable + Unpin, F: IStable + core::future::Future<Output = T> + Unpin> core::future::Future
344 for MaybeResolved<T, F>
345where
346 F: crate::IStable,
347 crate::Result<(), F>: crate::IStable,
348 T: crate::IDeterminantProvider<crate::Result<(), F>>,
349 (): crate::IDeterminantProvider<F>,
350{
351 type Output = T;
352 fn poll(
353 self: core::pin::Pin<&mut Self>,
354 cx: &mut Context<'_>,
355 ) -> core::task::Poll<Self::Output> {
356 let this = self.get_mut();
357 let inner = this as *mut _;
358 this.match_mut(
359 |value| {
360 let value = unsafe {
361 let value = core::ptr::read(value);
362 core::ptr::write(inner, MaybeResolved::Empty());
363 value
364 };
365 core::task::Poll::Ready(value)
366 },
367 || core::task::Poll::Pending,
368 |future| match core::future::Future::poll(core::pin::Pin::new(future), cx) {
369 core::task::Poll::Ready(value) => {
370 unsafe {
371 core::ptr::replace(inner, MaybeResolved::Empty());
372 }
373 core::task::Poll::Ready(value)
374 }
375 core::task::Poll::Pending => core::task::Poll::Pending,
376 },
377 )
378 }
379}