Skip to main content

some_executor/
local.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::SomeLocalExecutor;
4use crate::observer::{ExecutorNotified, FinishedObservation, Observer, ObserverNotified};
5use crate::task::Task;
6use std::any::Any;
7use std::future::Future;
8use std::marker::PhantomData;
9use std::pin::Pin;
10//
11// /**
12// Erases the executor notifier type
13// */
14// pub(crate) struct SomeLocalExecutorErasingNotifier<
15//     'borrow,
16//     'underlying,
17//     UnderlyingExecutor: SomeLocalExecutor<'underlying> + ?Sized,
18// > {
19//     executor: &'borrow mut UnderlyingExecutor,
20//     _phantom: PhantomData<&'underlying ()>,
21// }
22//
23// impl<'borrow, 'underlying, UnderlyingExecutor: SomeLocalExecutor<'underlying> + ?Sized>
24//     SomeLocalExecutorErasingNotifier<'borrow, 'underlying, UnderlyingExecutor>
25// {
26//     pub(crate) fn new(executor: &'borrow mut UnderlyingExecutor) -> Self {
27//         Self {
28//             executor,
29//             _phantom: PhantomData,
30//         }
31//     }
32// }
33//
34// impl<'borrow, 'underlying, UnderlyingExecutor: SomeLocalExecutor<'underlying> + ?Sized>
35//     std::fmt::Debug for SomeLocalExecutorErasingNotifier<'borrow, 'underlying, UnderlyingExecutor>
36// {
37//     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38//         f.debug_struct("SomeLocalExecutorErasingNotifier")
39//             .field("executor", &"<executor>")
40//             .finish()
41//     }
42// }
43//
44// impl<'borrow, 'executor, UnderlyingExecutor: SomeLocalExecutor<'executor>>
45//     SomeLocalExecutor<'executor>
46//     for SomeLocalExecutorErasingNotifier<'borrow, 'executor, UnderlyingExecutor>
47// {
48//     type ExecutorNotifier = Box<dyn ExecutorNotified>;
49//
50//     fn spawn_local<F, Notifier: ObserverNotified<F::Output>>(
51//         &mut self,
52//         task: Task<F, Notifier>,
53//     ) -> impl Observer<Value = F::Output>
54//     where
55//         Self: Sized,
56//         F: Future + 'executor,
57//         /* I am a little uncertain whether this is really required */
58//         <F as Future>::Output: Unpin,
59//         <F as Future>::Output: 'static,
60//     {
61//         self.executor.spawn_local(task)
62//     }
63//
64//     async fn spawn_local_async<F, Notifier: ObserverNotified<F::Output>>(
65//         &mut self,
66//         task: Task<F, Notifier>,
67//     ) -> impl Observer<Value = F::Output>
68//     where
69//         Self: Sized,
70//         F: Future + 'executor,
71//         F::Output: 'static + Unpin,
72//     {
73//         self.executor.spawn_local_async(task).await
74//     }
75//
76//     fn spawn_local_objsafe(
77//         &mut self,
78//         task: Task<
79//             Pin<Box<dyn Future<Output = Box<dyn Any>>>>,
80//             Box<dyn ObserverNotified<dyn Any + 'static>>,
81//         >,
82//     ) -> Box<dyn Observer<Value = Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>> {
83//         self.executor.spawn_local_objsafe(task)
84//     }
85//
86//     fn spawn_local_objsafe_async<'s>(
87//         &'s mut self,
88//         task: Task<
89//             Pin<Box<dyn Future<Output = Box<dyn Any>>>>,
90//             Box<dyn ObserverNotified<dyn Any + 'static>>,
91//         >,
92//     ) -> Box<
93//         dyn Future<
94//                 Output = Box<
95//                     dyn Observer<Value = Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>,
96//                 >,
97//             > + 's,
98//     > {
99//         #[allow(clippy::async_yields_async)]
100//         Box::new(async {
101//             let objsafe_spawn_fut = self.executor.spawn_local_objsafe_async(task);
102//             Box::into_pin(objsafe_spawn_fut).await
103//         })
104//     }
105//
106//     fn executor_notifier(&mut self) -> Option<Self::ExecutorNotifier> {
107//         self.executor
108//             .executor_notifier()
109//             .map(|x| Box::new(x) as Self::ExecutorNotifier)
110//     }
111// }
112//
113/**
114Like `SomeLocalExecutorErasingNotifier`, but owns the underlying executor.
115*/
116pub(crate) struct OwnedSomeLocalExecutorErasingNotifier<'underlying, UnderlyingExecutor> {
117    executor: UnderlyingExecutor,
118    _phantom: PhantomData<&'underlying ()>,
119}
120
121impl<'underlying, UnderlyingExecutor>
122    OwnedSomeLocalExecutorErasingNotifier<'underlying, UnderlyingExecutor>
123{
124    pub(crate) fn new(executor: UnderlyingExecutor) -> Self {
125        Self {
126            executor,
127            _phantom: PhantomData,
128        }
129    }
130}
131
132impl<'underlying, UnderlyingExecutor: std::fmt::Debug> std::fmt::Debug
133    for OwnedSomeLocalExecutorErasingNotifier<'underlying, UnderlyingExecutor>
134{
135    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136        f.debug_struct("OwnedSomeLocalExecutorErasingNotifier")
137            .field("executor", &self.executor)
138            .finish()
139    }
140}
141
142impl<'underlying, UnderlyingExecutor: SomeLocalExecutor<'underlying>> SomeLocalExecutor<'underlying>
143    for OwnedSomeLocalExecutorErasingNotifier<'underlying, UnderlyingExecutor>
144{
145    type ExecutorNotifier = Box<dyn ExecutorNotified>;
146
147    fn spawn_local<F, Notifier: ObserverNotified<F::Output>>(
148        &mut self,
149        task: Task<F, Notifier>,
150    ) -> impl Observer<Value = F::Output>
151    where
152        Self: Sized,
153        F: Future + 'underlying,
154        /* I am a little uncertain whether this is really required */
155        <F as Future>::Output: Unpin,
156        <F as Future>::Output: 'static,
157    {
158        self.executor.spawn_local(task)
159    }
160
161    async fn spawn_local_async<F, Notifier: ObserverNotified<F::Output>>(
162        &mut self,
163        task: Task<F, Notifier>,
164    ) -> impl Observer<Value = F::Output>
165    where
166        Self: Sized,
167        F: Future + 'underlying,
168        F::Output: 'static + Unpin,
169    {
170        self.executor.spawn_local_async(task).await
171    }
172
173    fn spawn_local_objsafe(
174        &mut self,
175        task: Task<
176            Pin<Box<dyn Future<Output = Box<dyn Any>>>>,
177            Box<dyn ObserverNotified<dyn Any + 'static>>,
178        >,
179    ) -> Box<dyn Observer<Value = Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>> {
180        self.executor.spawn_local_objsafe(task)
181    }
182
183    fn spawn_local_objsafe_async<'s>(
184        &'s mut self,
185        task: Task<
186            Pin<Box<dyn Future<Output = Box<dyn Any>>>>,
187            Box<dyn ObserverNotified<dyn Any + 'static>>,
188        >,
189    ) -> Box<
190        dyn Future<
191                Output = Box<
192                    dyn Observer<Value = Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>,
193                >,
194            > + 's,
195    > {
196        #[allow(clippy::async_yields_async)]
197        Box::new(async {
198            let objsafe_spawn_fut = self.executor.spawn_local_objsafe_async(task);
199            Box::into_pin(objsafe_spawn_fut).await
200        })
201    }
202
203    fn executor_notifier(&mut self) -> Option<Self::ExecutorNotifier> {
204        self.executor
205            .executor_notifier()
206            .map(|x| Box::new(x) as Self::ExecutorNotifier)
207    }
208}
209
210// pub(crate) struct UnsafeErasedLocalExecutor {
211//     underlying: *mut dyn SomeLocalExecutor<'static, ExecutorNotifier = Box<dyn ExecutorNotified>>,
212// }
213//
214// impl std::fmt::Debug for UnsafeErasedLocalExecutor {
215//     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216//         f.debug_struct("UnsafeErasedLocalExecutor")
217//             .field("underlying", &"<executor ptr>")
218//             .finish()
219//     }
220// }
221//
222// impl UnsafeErasedLocalExecutor {
223//     /**
224//     Creates a new type.
225//
226//     # Safety
227//
228//     The underlying executor must be valid for the lifetime of this type.
229//     */
230//     pub unsafe fn new<'e>(
231//         underlying: &mut (dyn SomeLocalExecutor<ExecutorNotifier = Box<dyn ExecutorNotified>> + 'e),
232//     ) -> Self {
233//         Self {
234//             underlying: unsafe { std::mem::transmute(underlying) },
235//         }
236//     }
237//
238//     fn executor(
239//         &mut self,
240//     ) -> &mut (dyn SomeLocalExecutor<'_, ExecutorNotifier = Box<dyn ExecutorNotified>> + '_) {
241//         // Safety: `underlying` is assumed to be valid for the duration of `&mut self`
242//         unsafe {
243//             std::mem::transmute::<
244//                 &mut dyn SomeLocalExecutor<ExecutorNotifier = Box<dyn ExecutorNotified>>,
245//                 &mut dyn SomeLocalExecutor<ExecutorNotifier = Box<dyn ExecutorNotified>>,
246//             >(&mut *self.underlying)
247//         }
248//     }
249// }
250//
251// impl<'a> SomeLocalExecutor<'a> for UnsafeErasedLocalExecutor {
252//     type ExecutorNotifier = Box<dyn ExecutorNotified>;
253//
254//     fn spawn_local<F, Notifier: ObserverNotified<F::Output>>(
255//         &mut self,
256//         _task: Task<F, Notifier>,
257//     ) -> impl Observer<Value = F::Output>
258//     where
259//         Self: Sized,
260//         F: Future + 'a,
261//         /* I am a little uncertain whether this is really required */
262//         <F as Future>::Output: Unpin,
263//         <F as Future>::Output: 'static,
264//     {
265//         #[allow(unreachable_code)]
266//         {
267//             unimplemented!("Not implemented for erased executor; use objsafe method")
268//                 as TypedObserver<F::Output, Infallible>
269//         }
270//     }
271//
272//     fn spawn_local_async<F: Future, Notifier: ObserverNotified<F::Output>>(
273//         &mut self,
274//         _task: Task<F, Notifier>,
275//     ) -> impl Future<Output = impl Observer<Value = F::Output>>
276//     where
277//         Self: Sized,
278//         F::Output: 'static,
279//     {
280//         #[allow(unreachable_code)]
281//         #[allow(clippy::async_yields_async)]
282//         {
283//             async {
284//                 unimplemented!("Not implemented for erased executor; use objsafe method")
285//                     as TypedObserver<F::Output, Infallible>
286//             }
287//         }
288//     }
289//
290//     fn spawn_local_objsafe(
291//         &mut self,
292//         task: Task<
293//             Pin<Box<dyn Future<Output = Box<dyn Any>>>>,
294//             Box<dyn ObserverNotified<dyn Any + 'static>>,
295//         >,
296//     ) -> Box<dyn Observer<Value = Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>> {
297//         let ex = self.executor();
298//         ex.spawn_local_objsafe(task)
299//     }
300//
301//     fn spawn_local_objsafe_async<'s>(
302//         &'s mut self,
303//         task: Task<
304//             Pin<Box<dyn Future<Output = Box<dyn Any>>>>,
305//             Box<dyn ObserverNotified<dyn Any + 'static>>,
306//         >,
307//     ) -> Box<
308//         dyn Future<
309//                 Output = Box<
310//                     dyn Observer<Value = Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>,
311//                 >,
312//             > + 's,
313//     > {
314//         let ex = self.executor();
315//         ex.spawn_local_objsafe_async(task)
316//     }
317//
318//     fn executor_notifier(&mut self) -> Option<Self::ExecutorNotifier> {
319//         self.executor().executor_notifier()
320//     }
321// }