1 | use core::{ |
2 | fmt, |
3 | future::Future, |
4 | marker::PhantomData, |
5 | mem, |
6 | pin::Pin, |
7 | task::{Context, Poll}, |
8 | }; |
9 | |
10 | /// A custom trait object for polling futures, roughly akin to |
11 | /// `Box<dyn Future<Output = T> + 'a>`. |
12 | /// |
13 | /// This custom trait object was introduced as currently it is not possible to |
14 | /// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std |
15 | /// contexts. |
16 | pub struct LocalFutureObj<'a, T> { |
17 | future: *mut (dyn Future<Output = T> + 'static), |
18 | drop_fn: unsafe fn(*mut (dyn Future<Output = T> + 'static)), |
19 | _marker: PhantomData<&'a ()>, |
20 | } |
21 | |
22 | // As LocalFutureObj only holds pointers, even if we move it, the pointed to values won't move, |
23 | // so this is safe as long as we don't provide any way for a user to directly access the pointers |
24 | // and move their values. |
25 | impl<T> Unpin for LocalFutureObj<'_, T> {} |
26 | |
27 | #[allow (single_use_lifetimes)] |
28 | #[allow (clippy::transmute_ptr_to_ptr)] |
29 | unsafe fn remove_future_lifetime<'a, T>( |
30 | ptr: *mut (dyn Future<Output = T> + 'a), |
31 | ) -> *mut (dyn Future<Output = T> + 'static) { |
32 | mem::transmute(ptr) |
33 | } |
34 | |
35 | #[allow (single_use_lifetimes)] |
36 | unsafe fn remove_drop_lifetime<'a, T>( |
37 | ptr: unsafe fn(*mut (dyn Future<Output = T> + 'a)), |
38 | ) -> unsafe fn(*mut (dyn Future<Output = T> + 'static)) { |
39 | mem::transmute(ptr) |
40 | } |
41 | |
42 | impl<'a, T> LocalFutureObj<'a, T> { |
43 | /// Create a `LocalFutureObj` from a custom trait object representation. |
44 | #[inline ] |
45 | pub fn new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> Self { |
46 | Self { |
47 | future: unsafe { remove_future_lifetime(f.into_raw()) }, |
48 | drop_fn: unsafe { remove_drop_lifetime(F::drop) }, |
49 | _marker: PhantomData, |
50 | } |
51 | } |
52 | |
53 | /// Converts the `LocalFutureObj` into a `FutureObj`. |
54 | /// |
55 | /// # Safety |
56 | /// |
57 | /// To make this operation safe one has to ensure that the `UnsafeFutureObj` |
58 | /// instance from which this `LocalFutureObj` was created actually |
59 | /// implements `Send`. |
60 | #[inline ] |
61 | pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> { |
62 | FutureObj(self) |
63 | } |
64 | } |
65 | |
66 | impl<T> fmt::Debug for LocalFutureObj<'_, T> { |
67 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
68 | f.debug_struct("LocalFutureObj" ).finish() |
69 | } |
70 | } |
71 | |
72 | impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> { |
73 | #[inline ] |
74 | fn from(f: FutureObj<'a, T>) -> Self { |
75 | f.0 |
76 | } |
77 | } |
78 | |
79 | impl<T> Future for LocalFutureObj<'_, T> { |
80 | type Output = T; |
81 | |
82 | #[inline ] |
83 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> { |
84 | unsafe { Pin::new_unchecked(&mut *self.future).poll(cx) } |
85 | } |
86 | } |
87 | |
88 | impl<T> Drop for LocalFutureObj<'_, T> { |
89 | fn drop(&mut self) { |
90 | unsafe { (self.drop_fn)(self.future) } |
91 | } |
92 | } |
93 | |
94 | /// A custom trait object for polling futures, roughly akin to |
95 | /// `Box<dyn Future<Output = T> + Send + 'a>`. |
96 | /// |
97 | /// This custom trait object was introduced as currently it is not possible to |
98 | /// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std |
99 | /// contexts. |
100 | /// |
101 | /// You should generally not need to use this type outside of `no_std` or when |
102 | /// implementing `Spawn`, consider using `BoxFuture` instead. |
103 | pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); |
104 | |
105 | impl<T> Unpin for FutureObj<'_, T> {} |
106 | unsafe impl<T> Send for FutureObj<'_, T> {} |
107 | |
108 | impl<'a, T> FutureObj<'a, T> { |
109 | /// Create a `FutureObj` from a custom trait object representation. |
110 | #[inline ] |
111 | pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> Self { |
112 | Self(LocalFutureObj::new(f)) |
113 | } |
114 | } |
115 | |
116 | impl<T> fmt::Debug for FutureObj<'_, T> { |
117 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
118 | f.debug_struct("FutureObj" ).finish() |
119 | } |
120 | } |
121 | |
122 | impl<T> Future for FutureObj<'_, T> { |
123 | type Output = T; |
124 | |
125 | #[inline ] |
126 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> { |
127 | Pin::new(&mut self.0).poll(cx) |
128 | } |
129 | } |
130 | |
131 | /// A custom implementation of a future trait object for `FutureObj`, providing |
132 | /// a vtable with drop support. |
133 | /// |
134 | /// This custom representation is typically used only in `no_std` contexts, |
135 | /// where the default `Box`-based implementation is not available. |
136 | /// |
137 | /// # Safety |
138 | /// |
139 | /// See the safety notes on individual methods for what guarantees an |
140 | /// implementor must provide. |
141 | pub unsafe trait UnsafeFutureObj<'a, T>: 'a { |
142 | /// Convert an owned instance into a (conceptually owned) fat pointer. |
143 | /// |
144 | /// # Safety |
145 | /// |
146 | /// ## Implementor |
147 | /// |
148 | /// The trait implementor must guarantee that it is safe to convert the |
149 | /// provided `*mut (dyn Future<Output = T> + 'a)` into a `Pin<&mut (dyn |
150 | /// Future<Output = T> + 'a)>` and call methods on it, non-reentrantly, |
151 | /// until `UnsafeFutureObj::drop` is called with it. |
152 | #[allow (clippy::unnecessary_safety_doc)] |
153 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a); |
154 | |
155 | /// Drops the future represented by the given fat pointer. |
156 | /// |
157 | /// # Safety |
158 | /// |
159 | /// ## Implementor |
160 | /// |
161 | /// The trait implementor must guarantee that it is safe to call this |
162 | /// function once per `into_raw` invocation. |
163 | /// |
164 | /// ## Caller |
165 | /// |
166 | /// The caller must ensure: |
167 | /// |
168 | /// * the pointer passed was obtained from an `into_raw` invocation from |
169 | /// this same trait object |
170 | /// * the pointer is not currently in use as a `Pin<&mut (dyn Future<Output |
171 | /// = T> + 'a)>` |
172 | /// * the pointer must not be used again after this function is called |
173 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)); |
174 | } |
175 | |
176 | unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F |
177 | where |
178 | F: Future<Output = T> + Unpin + 'a, |
179 | { |
180 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
181 | self as *mut dyn Future<Output = T> |
182 | } |
183 | |
184 | unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {} |
185 | } |
186 | |
187 | unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future<Output = T> + Unpin + 'a) { |
188 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
189 | self as *mut dyn Future<Output = T> |
190 | } |
191 | |
192 | unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {} |
193 | } |
194 | |
195 | unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F> |
196 | where |
197 | F: Future<Output = T> + 'a, |
198 | { |
199 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
200 | unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> } |
201 | } |
202 | |
203 | unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {} |
204 | } |
205 | |
206 | unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future<Output = T> + 'a)> { |
207 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
208 | unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> } |
209 | } |
210 | |
211 | unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {} |
212 | } |
213 | |
214 | #[cfg (feature = "alloc" )] |
215 | mod if_alloc { |
216 | use super::*; |
217 | use alloc::boxed::Box; |
218 | |
219 | unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F> |
220 | where |
221 | F: Future<Output = T> + 'a, |
222 | { |
223 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
224 | Box::into_raw(self) |
225 | } |
226 | |
227 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) { |
228 | drop(Box::from_raw(ptr.cast::<F>())) |
229 | } |
230 | } |
231 | |
232 | unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + 'a> { |
233 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
234 | Box::into_raw(self) |
235 | } |
236 | |
237 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) { |
238 | drop(Box::from_raw(ptr)) |
239 | } |
240 | } |
241 | |
242 | unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + Send + 'a> { |
243 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
244 | Box::into_raw(self) |
245 | } |
246 | |
247 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) { |
248 | drop(Box::from_raw(ptr)) |
249 | } |
250 | } |
251 | |
252 | unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>> |
253 | where |
254 | F: Future<Output = T> + 'a, |
255 | { |
256 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
257 | let mut this = mem::ManuallyDrop::new(self); |
258 | unsafe { this.as_mut().get_unchecked_mut() as *mut _ } |
259 | } |
260 | |
261 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) { |
262 | drop(Pin::from(Box::from_raw(ptr))) |
263 | } |
264 | } |
265 | |
266 | unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + 'a>> { |
267 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
268 | let mut this = mem::ManuallyDrop::new(self); |
269 | unsafe { this.as_mut().get_unchecked_mut() as *mut _ } |
270 | } |
271 | |
272 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) { |
273 | drop(Pin::from(Box::from_raw(ptr))) |
274 | } |
275 | } |
276 | |
277 | unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + Send + 'a>> { |
278 | fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) { |
279 | let mut this = mem::ManuallyDrop::new(self); |
280 | unsafe { this.as_mut().get_unchecked_mut() as *mut _ } |
281 | } |
282 | |
283 | unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) { |
284 | drop(Pin::from(Box::from_raw(ptr))) |
285 | } |
286 | } |
287 | |
288 | impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> { |
289 | fn from(boxed: Box<F>) -> Self { |
290 | Self::new(boxed) |
291 | } |
292 | } |
293 | |
294 | impl<'a> From<Box<dyn Future<Output = ()> + Send + 'a>> for FutureObj<'a, ()> { |
295 | fn from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self { |
296 | Self::new(boxed) |
297 | } |
298 | } |
299 | |
300 | impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> { |
301 | fn from(boxed: Pin<Box<F>>) -> Self { |
302 | Self::new(boxed) |
303 | } |
304 | } |
305 | |
306 | impl<'a> From<Pin<Box<dyn Future<Output = ()> + Send + 'a>>> for FutureObj<'a, ()> { |
307 | fn from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self { |
308 | Self::new(boxed) |
309 | } |
310 | } |
311 | |
312 | impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> { |
313 | fn from(boxed: Box<F>) -> Self { |
314 | Self::new(boxed) |
315 | } |
316 | } |
317 | |
318 | impl<'a> From<Box<dyn Future<Output = ()> + 'a>> for LocalFutureObj<'a, ()> { |
319 | fn from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self { |
320 | Self::new(boxed) |
321 | } |
322 | } |
323 | |
324 | impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> { |
325 | fn from(boxed: Pin<Box<F>>) -> Self { |
326 | Self::new(boxed) |
327 | } |
328 | } |
329 | |
330 | impl<'a> From<Pin<Box<dyn Future<Output = ()> + 'a>>> for LocalFutureObj<'a, ()> { |
331 | fn from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self { |
332 | Self::new(boxed) |
333 | } |
334 | } |
335 | } |
336 | |