some_executor/
local.rs

1//SPDX-License-Identifier: MIT OR Apache-2.0
2
3use std::any::Any;
4use std::convert::Infallible;
5use std::future::Future;
6use std::marker::PhantomData;
7use std::pin::Pin;
8use crate::observer::{ExecutorNotified, TypedObserver, ObserverNotified, Observer, FinishedObservation};
9use crate::{SomeLocalExecutor};
10use crate::task::Task;
11
12/**
13Erases the executor notifier type
14*/
15pub(crate) struct SomeLocalExecutorErasingNotifier<'borrow, 'underlying, UnderlyingExecutor: SomeLocalExecutor<'underlying> + ?Sized> {
16    executor: &'borrow mut UnderlyingExecutor,
17    _phantom: PhantomData<&'underlying ()>
18}
19
20impl <'borrow, 'underlying, UnderlyingExecutor: SomeLocalExecutor<'underlying> + ?Sized> SomeLocalExecutorErasingNotifier<'borrow, 'underlying, UnderlyingExecutor> {
21    pub(crate) fn new(executor: &'borrow mut UnderlyingExecutor) -> Self {
22        Self {
23            executor,
24            _phantom: PhantomData
25        }
26    }
27}
28
29impl<'borrow, 'executor, UnderlyingExecutor: SomeLocalExecutor<'executor>> SomeLocalExecutor<'executor> for SomeLocalExecutorErasingNotifier<'borrow, 'executor, UnderlyingExecutor> {
30    type ExecutorNotifier = Box<dyn ExecutorNotified>;
31
32    fn spawn_local<F: Future, Notifier: ObserverNotified<F::Output>>(&mut self, task: Task<F, Notifier>) -> impl Observer<Value=F::Output>
33    where
34        Self: Sized,
35        F: 'executor,
36    /* I am a little uncertain whether this is really required */
37        <F as Future>::Output: Unpin,
38        <F as Future>::Output: 'static,
39    {
40        self.executor.spawn_local(task)
41    }
42
43    fn spawn_local_async<F: Future, Notifier: ObserverNotified<F::Output>>(&mut self, task: Task<F, Notifier>) -> impl Future<Output=impl Observer<Value=F::Output>>
44    where
45        Self: Sized,
46        F: 'executor,
47        F::Output: 'static + Unpin,
48    {
49        async {
50            self.executor.spawn_local_async(task).await
51        }
52    }
53
54
55    fn spawn_local_objsafe(&mut self, task: Task<Pin<Box<dyn Future<Output=Box<dyn Any>>>>, Box<dyn ObserverNotified<(dyn Any + 'static)>>>) -> Box<dyn Observer<Value=Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>> {
56        self.executor.spawn_local_objsafe(task)
57    }
58
59    fn spawn_local_objsafe_async<'s>(&'s mut self, task: Task<Pin<Box<dyn Future<Output=Box<dyn Any>>>>, Box<dyn ObserverNotified<(dyn Any + 'static)>>>) -> Box<dyn Future<Output=Box<dyn Observer<Value=Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>>> + 's> {
60        Box::new(async {
61            let objsafe_spawn_fut = self.executor.spawn_local_objsafe_async(task);
62            Box::into_pin(objsafe_spawn_fut).await
63        })
64    }
65
66
67    fn executor_notifier(&mut self) -> Option<Self::ExecutorNotifier> {
68        self.executor.executor_notifier().map(|x| Box::new(x) as Self::ExecutorNotifier)
69    }
70}
71
72/**
73Like `SomeLocalExecutorErasingNotifier`, but owns the underlying executor.
74*/
75
76pub(crate) struct OwnedSomeLocalExecutorErasingNotifier<'underlying, UnderlyingExecutor> {
77    executor: UnderlyingExecutor,
78    _phantom: PhantomData<&'underlying ()>
79}
80
81impl<'underlying,UnderlyingExecutor> OwnedSomeLocalExecutorErasingNotifier<'underlying,UnderlyingExecutor> {
82    pub(crate) fn new(executor: UnderlyingExecutor) -> Self {
83        Self {
84            executor,
85            _phantom: PhantomData
86        }
87    }
88}
89
90impl <'underlying, UnderlyingExecutor: SomeLocalExecutor<'underlying>> SomeLocalExecutor<'underlying> for OwnedSomeLocalExecutorErasingNotifier<'underlying, UnderlyingExecutor> {
91    type ExecutorNotifier = Box<dyn ExecutorNotified>;
92
93    fn spawn_local<F: Future, Notifier: ObserverNotified<F::Output>>(&mut self, task: Task<F, Notifier>) -> impl Observer<Value=F::Output>
94    where
95        Self: Sized,
96        F: 'underlying,
97    /* I am a little uncertain whether this is really required */
98        <F as Future>::Output: Unpin,
99        <F as Future>::Output: 'static,
100    {
101        self.executor.spawn_local(task)
102    }
103
104    fn spawn_local_async<F: Future, Notifier: ObserverNotified<F::Output>>(&mut self, task: Task<F, Notifier>) -> impl Future<Output=impl Observer<Value=F::Output>>
105    where
106        Self: Sized,
107        F: 'underlying,
108        F::Output: 'static + Unpin,
109    {
110        async {
111            self.executor.spawn_local_async(task).await
112        }
113    }
114
115    fn spawn_local_objsafe(&mut self, task: Task<Pin<Box<dyn Future<Output=Box<dyn Any>>>>, Box<dyn ObserverNotified<(dyn Any + 'static)>>>) -> Box<dyn Observer<Value=Box<dyn Any>, Output=FinishedObservation<Box<dyn Any>>>> {
116        self.executor.spawn_local_objsafe(task)
117    }
118
119    fn spawn_local_objsafe_async<'s>(&'s mut self, task: Task<Pin<Box<dyn Future<Output=Box<dyn Any>>>>, Box<dyn ObserverNotified<(dyn Any + 'static)>>>) -> Box<dyn Future<Output=Box<dyn Observer<Value=Box<dyn Any>, Output=FinishedObservation<Box<dyn Any>>>>> + 's> {
120        Box::new(async {
121            let objsafe_spawn_fut = self.executor.spawn_local_objsafe_async(task);
122            Box::into_pin(objsafe_spawn_fut).await
123        })
124    }
125
126    fn executor_notifier(&mut self) -> Option<Self::ExecutorNotifier> {
127        self.executor.executor_notifier().map(|x| Box::new(x) as Self::ExecutorNotifier)
128    }
129}
130
131
132pub (crate) struct UnsafeErasedLocalExecutor {
133    underlying: *mut dyn SomeLocalExecutor<'static, ExecutorNotifier=Box<dyn ExecutorNotified>>,
134}
135
136impl UnsafeErasedLocalExecutor {
137    /**
138    Creates a new type.
139
140    # Safety
141
142    The underlying executor must be valid for the lifetime of this type.
143    */
144    pub unsafe fn new<'e>(underlying:&mut (dyn SomeLocalExecutor<ExecutorNotifier=Box<dyn ExecutorNotified>> + 'e)) -> Self {
145        Self {
146            underlying: std::mem::transmute(underlying),
147        }
148    }
149
150    fn executor(&mut self) -> &mut (dyn SomeLocalExecutor<ExecutorNotifier=Box<dyn ExecutorNotified>> + '_) {
151        // Safety: `underlying` is assumed to be valid for the duration of `&mut self`
152        unsafe {
153            std::mem::transmute::<
154                &mut dyn SomeLocalExecutor<ExecutorNotifier=Box<dyn ExecutorNotified>>,
155                &mut dyn SomeLocalExecutor<ExecutorNotifier=Box<dyn ExecutorNotified>>
156            >(&mut *self.underlying)
157        }
158    }
159}
160
161impl<'a> SomeLocalExecutor<'a> for UnsafeErasedLocalExecutor {
162    type ExecutorNotifier = Box<dyn ExecutorNotified>;
163
164    fn spawn_local<F: Future, Notifier: ObserverNotified<F::Output>>(&mut self, _task: Task<F, Notifier>) -> impl Observer<Value=F::Output>
165    where
166        Self: Sized,
167        F: 'a,
168    /* I am a little uncertain whether this is really required */
169        <F as Future>::Output: Unpin,
170        <F as Future>::Output: 'static,
171    {
172        #[allow(unreachable_code)] {
173            unimplemented!("Not implemented for erased executor; use objsafe method") as TypedObserver<F::Output, Infallible>
174        }
175    }
176
177    fn spawn_local_async<F: Future, Notifier: ObserverNotified<F::Output>>(&mut self, _task: Task<F, Notifier>) -> impl Future<Output=impl Observer<Value=F::Output>>
178    where
179        Self: Sized,
180        F::Output: 'static,
181    {
182        #[allow(unreachable_code)] {
183            async { unimplemented!("Not implemented for erased executor; use objsafe method") as TypedObserver<F::Output, Infallible> }
184        }
185    }
186
187    fn spawn_local_objsafe(&mut self, task: Task<Pin<Box<dyn Future<Output=Box<dyn Any>>>>, Box<dyn ObserverNotified<(dyn Any + 'static)>>>) -> Box<dyn Observer<Value=Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>> {
188        let ex = self.executor();
189        ex.spawn_local_objsafe(task)
190    }
191
192    fn spawn_local_objsafe_async<'s>(&'s mut self, task: Task<Pin<Box<dyn Future<Output=Box<dyn Any>>>>, Box<dyn ObserverNotified<(dyn Any + 'static)>>>) -> Box<dyn Future<Output=Box<dyn Observer<Value=Box<dyn Any>, Output = FinishedObservation<Box<dyn Any>>>>> + 's> {
193        let ex = self.executor();
194        ex.spawn_local_objsafe_async(task)
195    }
196
197    fn executor_notifier(&mut self) -> Option<Self::ExecutorNotifier> {
198        self.executor().executor_notifier()
199    }
200}