// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![unstable(feature = "futures_api", reason = "futures in libcore are unstable", issue = "50547")] use fmt; use future::Future; use marker::{PhantomData, Unpin}; use mem::PinMut; use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to /// `Box + 'a>`. /// /// This custom trait object was introduced for two reasons: /// - Currently it is not possible to take `dyn Trait` by value and /// `Box` is not available in no_std contexts. /// - The `Future` trait is currently not object safe: The `Future::poll` /// method makes uses the arbitrary self types feature and traits in which /// this feature is used are currently not object safe due to current compiler /// limitations. (See tracking issue for arbitray self types for more /// information #44874) pub struct LocalFutureObj<'a, T> { ptr: *mut (), poll_fn: unsafe fn(*mut (), &mut Context) -> Poll, drop_fn: unsafe fn(*mut ()), _marker: PhantomData<&'a ()>, } impl<'a, T> Unpin for LocalFutureObj<'a, T> {} impl<'a, T> LocalFutureObj<'a, T> { /// Create a `LocalFutureObj` from a custom trait object representation. #[inline] pub fn new + 'a>(f: F) -> LocalFutureObj<'a, T> { LocalFutureObj { ptr: f.into_raw(), poll_fn: F::poll, drop_fn: F::drop, _marker: PhantomData, } } /// Converts the `LocalFutureObj` into a `FutureObj` /// To make this operation safe one has to ensure that the `UnsafeFutureObj` /// instance from which this `LocalFutureObj` was created actually /// implements `Send`. #[inline] pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> { FutureObj(self) } } impl<'a, T> fmt::Debug for LocalFutureObj<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("LocalFutureObj") .finish() } } impl<'a, T> From> for LocalFutureObj<'a, T> { #[inline] fn from(f: FutureObj<'a, T>) -> LocalFutureObj<'a, T> { f.0 } } impl<'a, T> Future for LocalFutureObj<'a, T> { type Output = T; #[inline] fn poll(self: PinMut, cx: &mut Context) -> Poll { unsafe { (self.poll_fn)(self.ptr, cx) } } } impl<'a, T> Drop for LocalFutureObj<'a, T> { fn drop(&mut self) { unsafe { (self.drop_fn)(self.ptr) } } } /// A custom trait object for polling futures, roughly akin to /// `Box + Send + 'a>`. /// /// This custom trait object was introduced for two reasons: /// - Currently it is not possible to take `dyn Trait` by value and /// `Box` is not available in no_std contexts. /// - The `Future` trait is currently not object safe: The `Future::poll` /// method makes uses the arbitrary self types feature and traits in which /// this feature is used are currently not object safe due to current compiler /// limitations. (See tracking issue for arbitray self types for more /// information #44874) pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); impl<'a, T> Unpin for FutureObj<'a, T> {} unsafe impl<'a, T> Send for FutureObj<'a, T> {} impl<'a, T> FutureObj<'a, T> { /// Create a `FutureObj` from a custom trait object representation. #[inline] pub fn new + Send>(f: F) -> FutureObj<'a, T> { FutureObj(LocalFutureObj::new(f)) } } impl<'a, T> fmt::Debug for FutureObj<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("FutureObj") .finish() } } impl<'a, T> Future for FutureObj<'a, T> { type Output = T; #[inline] fn poll(self: PinMut, cx: &mut Context) -> Poll { let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) }; pinned_field.poll(cx) } } /// A custom implementation of a future trait object for `FutureObj`, providing /// a hand-rolled vtable. /// /// This custom representation is typically used only in `no_std` contexts, /// where the default `Box`-based implementation is not available. /// /// The implementor must guarantee that it is safe to call `poll` repeatedly (in /// a non-concurrent fashion) with the result of `into_raw` until `drop` is /// called. pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// Convert an owned instance into a (conceptually owned) void pointer. fn into_raw(self) -> *mut (); /// Poll the future represented by the given void pointer. /// /// # Safety /// /// The trait implementor must guarantee that it is safe to repeatedly call /// `poll` with the result of `into_raw` until `drop` is called; such calls /// are not, however, allowed to race with each other or with calls to /// `drop`. unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll; /// Drops the future represented by the given void pointer. /// /// # Safety /// /// The trait implementor must guarantee that it is safe to call this /// function once per `into_raw` invocation; that call cannot race with /// other calls to `drop` or `poll`. unsafe fn drop(ptr: *mut ()); } unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F where F: Future + Unpin + 'a { fn into_raw(self) -> *mut () { self as *mut F as *mut () } unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) } unsafe fn drop(_ptr: *mut ()) {} }