scope_lock/extended/
future.rs

1use core::future::Future;
2use core::marker::PhantomData;
3use core::pin::Pin;
4use core::ptr;
5use core::task;
6
7use crate::Extender;
8use crate::extended::sync::Reference;
9use crate::pointer_like::PointerPinUnforgotten;
10use crate::pointer_like::erased_static::{fn_drop, fn_poll_unforgotten};
11
12impl<'scope, 'env> Extender<'scope, 'env> {
13    // TODO: pointer width extended value like extend_future_box
14    pub fn future<'extended, P, O>(
15        &'scope self,
16        f: P,
17    ) -> impl Future<Output = O> + Send + Sync + 'extended
18    where
19        'extended: 'scope,
20        P: PointerPinUnforgotten + Send + 'scope,
21        P::Pointee: Future<Output = O>,
22        O: Send + 'extended,
23    {
24        let reference_guard = unsafe { self.rc.acquire() };
25
26        struct Fut<T> {
27            inner: T,
28            // drop last
29            _reference_guard: Reference,
30        }
31        unsafe impl<T> Send for Fut<T> {}
32        unsafe impl<T> Sync for Fut<T> {}
33        impl<T: Future> Future for Fut<T> {
34            type Output = T::Output;
35
36            fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
37                unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner).poll(cx) }
38            }
39        }
40
41        // It is sync since there's no way to interact with a reference to returned type
42        Fut {
43            inner: unsafe { extend_future_unchecked(f) },
44            _reference_guard: reference_guard,
45        }
46    }
47}
48
49pub unsafe fn extend_future_unchecked<'a, F, O>(f: F) -> impl Future<Output = O> + 'a
50where
51    F: PointerPinUnforgotten,
52    F::Pointee: Future<Output = O>,
53    O: 'a,
54{
55    unsafe {
56        ErasedFuture {
57            ptr: ptr::NonNull::new_unchecked(f.into_ptr() as *mut ()),
58            poll: fn_poll_unforgotten::<F, O>(),
59            drop: fn_drop::<F>(),
60            _marker: PhantomData,
61        }
62    }
63}
64
65struct ErasedFuture<P, O, D: Fn(*mut ())> {
66    ptr: ptr::NonNull<()>,
67    drop: D,
68    poll: P,
69    _marker: PhantomData<fn() -> task::Poll<O>>,
70}
71
72impl<P, O, D: Fn(*mut ())> Future for ErasedFuture<P, O, D>
73where
74    P: Fn(*mut (), &mut task::Context<'_>) -> task::Poll<O>,
75{
76    type Output = O;
77
78    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
79        (self.poll)(self.ptr.as_ptr(), cx)
80    }
81}
82
83impl<P, O, D: Fn(*mut ())> Drop for ErasedFuture<P, O, D> {
84    fn drop(&mut self) {
85        (self.drop)(self.ptr.as_ptr())
86    }
87}
88
89pub mod legacy {
90    use core::future::Future;
91    use core::pin::Pin;
92    use core::ptr;
93    use core::task;
94
95    #[doc(hidden)]
96    pub struct ExtendedFuture<O> {
97        // TODO: Could make a single dynamically sized struct
98        pub(crate) func: ptr::NonNull<dyn Future<Output = O> + Send>,
99    }
100
101    impl<O> Future for ExtendedFuture<O> {
102        type Output = O;
103
104        fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
105            unsafe { Pin::new_unchecked(self.get_unchecked_mut().func.as_mut()) }.poll(cx)
106        }
107    }
108
109    unsafe impl<O> Send for ExtendedFuture<O> where O: Send {}
110}