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// }